diff --git a/.gitattributes b/.gitattributes index aced01d485c18..6b281f33f737d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,10 +1,3 @@ -# Checkout as native, commit as LF except in specific circumstances -* text=auto -*.bat text eol=crlf -*.rc text eol=crlf -*.sln text eol=crlf -*.natvis text eol=crlf - libcxx/src/**/*.cpp merge=libcxx-reformat libcxx/include/**/*.h merge=libcxx-reformat diff --git a/.github/workflows/containers/github-action-ci/stage1.Dockerfile b/.github/workflows/containers/github-action-ci/stage1.Dockerfile index 73828cc05736e..3e2c1ab11d58b 100644 --- a/.github/workflows/containers/github-action-ci/stage1.Dockerfile +++ b/.github/workflows/containers/github-action-ci/stage1.Dockerfile @@ -2,7 +2,7 @@ FROM docker.io/library/ubuntu:22.04 as base ENV LLVM_SYSROOT=/opt/llvm FROM base as stage1-toolchain -ENV LLVM_VERSION=18.1.8 +ENV LLVM_VERSION=19.1.2 RUN apt-get update && \ apt-get install -y \ diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp index 8d781fc5e04ff..414912ea1c207 100644 --- a/bolt/lib/Core/DIEBuilder.cpp +++ b/bolt/lib/Core/DIEBuilder.cpp @@ -281,8 +281,7 @@ void DIEBuilder::buildTypeUnits(DebugStrOffsetsWriter *StrOffsetWriter, for (auto &Row : TUIndex.getRows()) { uint64_t Signature = Row.getSignature(); // manually populate TypeUnit to UnitVector - DwarfContext->getTypeUnitForHash(DwarfContext->getMaxVersion(), Signature, - true); + DwarfContext->getTypeUnitForHash(Signature, true); } } const unsigned int CUNum = getCUNum(DwarfContext, isDWO()); diff --git a/clang-tools-extra/clang-doc/Generators.h b/clang-tools-extra/clang-doc/Generators.h index ba0ef64d3d0f5..d62d7faa9a69f 100644 --- a/clang-tools-extra/clang-doc/Generators.h +++ b/clang-tools-extra/clang-doc/Generators.h @@ -55,4 +55,8 @@ std::string getTagType(TagTypeKind AS); } // namespace doc } // namespace clang +namespace llvm { +extern template class Registry; +} // namespace llvm + #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H diff --git a/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h b/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h index 78d914bfedbc9..8a07b05c26446 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h +++ b/clang-tools-extra/clang-tidy/ClangTidyModuleRegistry.h @@ -18,4 +18,8 @@ using ClangTidyModuleRegistry = llvm::Registry; } // namespace clang::tidy +namespace llvm { +extern template class Registry; +} // namespace llvm + #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp index 1ed444e630ec2..c29c4eb60f9d1 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeUnionAccessCheck.cpp @@ -23,8 +23,11 @@ void ProTypeUnionAccessCheck::registerMatchers(MatchFinder *Finder) { void ProTypeUnionAccessCheck::check(const MatchFinder::MatchResult &Result) { const auto *Matched = Result.Nodes.getNodeAs("expr"); - diag(Matched->getMemberLoc(), - "do not access members of unions; use (boost::)variant instead"); + SourceLocation Loc = Matched->getMemberLoc(); + if (Loc.isInvalid()) + Loc = Matched->getBeginLoc(); + diag(Loc, "do not access members of unions; consider using (boost::)variant " + "instead"); } } // namespace clang::tidy::cppcoreguidelines diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp index e20cf6fbcb55a..71a4cee4bdc6e 100644 --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp @@ -172,8 +172,8 @@ void ConstCorrectnessCheck::check(const MatchFinder::MatchResult &Result) { using namespace utils::fixit; if (VC == VariableCategory::Value && TransformValues) { - Diag << addQualifierToVarDecl(*Variable, *Result.Context, - DeclSpec::TQ_const, QualifierTarget::Value, + Diag << addQualifierToVarDecl(*Variable, *Result.Context, Qualifiers::Const, + QualifierTarget::Value, QualifierPolicy::Right); // FIXME: Add '{}' for default initialization if no user-defined default // constructor exists and there is no initializer. @@ -181,8 +181,8 @@ void ConstCorrectnessCheck::check(const MatchFinder::MatchResult &Result) { } if (VC == VariableCategory::Reference && TransformReferences) { - Diag << addQualifierToVarDecl(*Variable, *Result.Context, - DeclSpec::TQ_const, QualifierTarget::Value, + Diag << addQualifierToVarDecl(*Variable, *Result.Context, Qualifiers::Const, + QualifierTarget::Value, QualifierPolicy::Right); return; } @@ -190,7 +190,7 @@ void ConstCorrectnessCheck::check(const MatchFinder::MatchResult &Result) { if (VC == VariableCategory::Pointer) { if (WarnPointersAsValues && TransformPointersAsValues) { Diag << addQualifierToVarDecl(*Variable, *Result.Context, - DeclSpec::TQ_const, QualifierTarget::Value, + Qualifiers::Const, QualifierTarget::Value, QualifierPolicy::Right); } return; diff --git a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp index 655e480ffa62c..f7d44bf863141 100644 --- a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp @@ -91,7 +91,7 @@ bool ForRangeCopyCheck::handleConstValueCopy(const VarDecl &LoopVar, << utils::fixit::changeVarDeclToReference(LoopVar, Context); if (!LoopVar.getType().isConstQualified()) { if (std::optional Fix = utils::fixit::addQualifierToVarDecl( - LoopVar, Context, DeclSpec::TQ::TQ_const)) + LoopVar, Context, Qualifiers::Const)) Diagnostic << *Fix; } return true; @@ -129,7 +129,7 @@ bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced( "making it a const reference"); if (std::optional Fix = utils::fixit::addQualifierToVarDecl( - LoopVar, Context, DeclSpec::TQ::TQ_const)) + LoopVar, Context, Qualifiers::Const)) Diag << *Fix << utils::fixit::changeVarDeclToReference(LoopVar, Context); return true; diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index 61240fa4b0eb8..034894c11bf2c 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -36,7 +36,7 @@ void recordFixes(const VarDecl &Var, ASTContext &Context, Diagnostic << utils::fixit::changeVarDeclToReference(Var, Context); if (!Var.getType().isLocalConstQualified()) { if (std::optional Fix = utils::fixit::addQualifierToVarDecl( - Var, Context, DeclSpec::TQ::TQ_const)) + Var, Context, Qualifiers::Const)) Diagnostic << *Fix; } } diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp index 3a255c5c133f1..d356f866a8804 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -172,7 +172,7 @@ void UnnecessaryValueParamCheck::handleConstRefFix(const FunctionDecl &Function, // declaration. if (!CurrentParam.getType().getCanonicalType().isConstQualified()) { if (std::optional Fix = utils::fixit::addQualifierToVarDecl( - CurrentParam, Context, DeclSpec::TQ::TQ_const)) + CurrentParam, Context, Qualifiers::Const)) Diag << *Fix; } } diff --git a/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp b/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp index bbdd4326b0bac..a15589f9721c7 100644 --- a/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp @@ -11,6 +11,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" +#include "clang/Sema/DeclSpec.h" #include "clang/Tooling/FixIt.h" #include @@ -71,15 +72,17 @@ static std::optional fixIfNotDangerous(SourceLocation Loc, // Build a string that can be emitted as FixIt with either a space in before // or after the qualifier, either ' const' or 'const '. -static std::string buildQualifier(DeclSpec::TQ Qualifier, +static std::string buildQualifier(Qualifiers::TQ Qualifier, bool WhitespaceBefore = false) { if (WhitespaceBefore) - return (llvm::Twine(' ') + DeclSpec::getSpecifierName(Qualifier)).str(); - return (llvm::Twine(DeclSpec::getSpecifierName(Qualifier)) + " ").str(); + return (llvm::Twine(' ') + Qualifiers::fromCVRMask(Qualifier).getAsString()) + .str(); + return (llvm::Twine(Qualifiers::fromCVRMask(Qualifier).getAsString()) + " ") + .str(); } static std::optional changeValue(const VarDecl &Var, - DeclSpec::TQ Qualifier, + Qualifiers::TQ Qualifier, QualifierTarget QualTarget, QualifierPolicy QualPolicy, const ASTContext &Context) { @@ -99,7 +102,7 @@ static std::optional changeValue(const VarDecl &Var, } static std::optional changePointerItself(const VarDecl &Var, - DeclSpec::TQ Qualifier, + Qualifiers::TQ Qualifier, const ASTContext &Context) { if (locDangerous(Var.getLocation())) return std::nullopt; @@ -112,7 +115,7 @@ static std::optional changePointerItself(const VarDecl &Var, } static std::optional -changePointer(const VarDecl &Var, DeclSpec::TQ Qualifier, const Type *Pointee, +changePointer(const VarDecl &Var, Qualifiers::TQ Qualifier, const Type *Pointee, QualifierTarget QualTarget, QualifierPolicy QualPolicy, const ASTContext &Context) { // The pointer itself shall be marked as `const`. This is always to the right @@ -163,7 +166,7 @@ changePointer(const VarDecl &Var, DeclSpec::TQ Qualifier, const Type *Pointee, } static std::optional -changeReferencee(const VarDecl &Var, DeclSpec::TQ Qualifier, QualType Pointee, +changeReferencee(const VarDecl &Var, Qualifiers::TQ Qualifier, QualType Pointee, QualifierTarget QualTarget, QualifierPolicy QualPolicy, const ASTContext &Context) { if (QualPolicy == QualifierPolicy::Left && isValueType(Pointee)) @@ -183,7 +186,7 @@ changeReferencee(const VarDecl &Var, DeclSpec::TQ Qualifier, QualType Pointee, std::optional addQualifierToVarDecl(const VarDecl &Var, const ASTContext &Context, - DeclSpec::TQ Qualifier, + Qualifiers::TQ Qualifier, QualifierTarget QualTarget, QualifierPolicy QualPolicy) { assert((QualPolicy == QualifierPolicy::Left || diff --git a/clang-tools-extra/clang-tidy/utils/FixItHintUtils.h b/clang-tools-extra/clang-tidy/utils/FixItHintUtils.h index 2b96b2b2ce600..e690dbaefe642 100644 --- a/clang-tools-extra/clang-tidy/utils/FixItHintUtils.h +++ b/clang-tools-extra/clang-tidy/utils/FixItHintUtils.h @@ -11,7 +11,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "clang/Sema/DeclSpec.h" +#include "clang/AST/Type.h" #include namespace clang::tidy::utils::fixit { @@ -41,7 +41,7 @@ enum class QualifierTarget { /// Requires that `Var` is isolated in written code like in `int foo = 42;`. std::optional addQualifierToVarDecl(const VarDecl &Var, const ASTContext &Context, - DeclSpec::TQ Qualifier, + Qualifiers::TQ Qualifier, QualifierTarget QualTarget = QualifierTarget::Pointee, QualifierPolicy QualPolicy = QualifierPolicy::Left); diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h index 8fcbc5c33469f..e174f7fabe344 100644 --- a/clang-tools-extra/clangd/Config.h +++ b/clang-tools-extra/clangd/Config.h @@ -162,6 +162,7 @@ struct Config { bool DeducedTypes = true; bool Designators = true; bool BlockEnd = false; + bool DefaultArguments = false; // Limit the length of type names in inlay hints. (0 means no limit) uint32_t TypeNameLimit = 32; } InlayHints; diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp index 58610a5b87922..fb7692998d05c 100644 --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/clang-tools-extra/clangd/ConfigCompile.cpp @@ -43,7 +43,6 @@ #include "llvm/Support/Regex.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" -#include #include #include #include @@ -669,6 +668,11 @@ struct FragmentCompiler { Out.Apply.push_back([Value(**F.BlockEnd)](const Params &, Config &C) { C.InlayHints.BlockEnd = Value; }); + if (F.DefaultArguments) + Out.Apply.push_back( + [Value(**F.DefaultArguments)](const Params &, Config &C) { + C.InlayHints.DefaultArguments = Value; + }); if (F.TypeNameLimit) Out.Apply.push_back( [Value(**F.TypeNameLimit)](const Params &, Config &C) { diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h index fc1b45f5d4c3e..36f7d04231c41 100644 --- a/clang-tools-extra/clangd/ConfigFragment.h +++ b/clang-tools-extra/clangd/ConfigFragment.h @@ -339,6 +339,9 @@ struct Fragment { std::optional> Designators; /// Show defined symbol names at the end of a definition block. std::optional> BlockEnd; + /// Show parameter names and default values of default arguments after all + /// of the explicit arguments. + std::optional> DefaultArguments; /// Limit the length of type name hints. (0 means no limit) std::optional> TypeNameLimit; }; diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp index bcdda99eeed67..32e028981d424 100644 --- a/clang-tools-extra/clangd/ConfigYAML.cpp +++ b/clang-tools-extra/clangd/ConfigYAML.cpp @@ -14,7 +14,6 @@ #include "llvm/Support/YAMLParser.h" #include #include -#include namespace clang { namespace clangd { @@ -268,6 +267,10 @@ class Parser { if (auto Value = boolValue(N, "BlockEnd")) F.BlockEnd = *Value; }); + Dict.handle("DefaultArguments", [&](Node &N) { + if (auto Value = boolValue(N, "DefaultArguments")) + F.DefaultArguments = *Value; + }); Dict.handle("TypeNameLimit", [&](Node &N) { if (auto Value = uint32Value(N, "TypeNameLimit")) F.TypeNameLimit = *Value; diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index cd4f1931b3ce1..c4053fced81d6 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -11,9 +11,11 @@ #include "Config.h" #include "HeuristicResolver.h" #include "ParsedAST.h" +#include "Protocol.h" #include "SourceCode.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -23,15 +25,22 @@ #include "clang/AST/Type.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" +#include +#include #include #include @@ -372,6 +381,23 @@ maybeDropCxxExplicitObjectParameters(ArrayRef Params) { return Params; } +template +std::string joinAndTruncate(const R &Range, size_t MaxLength) { + std::string Out; + llvm::raw_string_ostream OS(Out); + llvm::ListSeparator Sep(", "); + for (auto &&Element : Range) { + OS << Sep; + if (Out.size() + Element.size() >= MaxLength) { + OS << "..."; + break; + } + OS << Element; + } + OS.flush(); + return Out; +} + struct Callee { // Only one of Decl or Loc is set. // Loc is for calls through function pointers. @@ -422,7 +448,8 @@ class InlayHintVisitor : public RecursiveASTVisitor { Callee.Decl = E->getConstructor(); if (!Callee.Decl) return true; - processCall(Callee, {E->getArgs(), E->getNumArgs()}); + processCall(Callee, E->getParenOrBraceRange().getEnd(), + {E->getArgs(), E->getNumArgs()}); return true; } @@ -495,7 +522,7 @@ class InlayHintVisitor : public RecursiveASTVisitor { dyn_cast_or_null(Callee.Decl)) if (IsFunctor || Method->hasCXXExplicitFunctionObjectParameter()) Args = Args.drop_front(1); - processCall(Callee, Args); + processCall(Callee, E->getRParenLoc(), Args); return true; } @@ -709,10 +736,12 @@ class InlayHintVisitor : public RecursiveASTVisitor { private: using NameVec = SmallVector; - void processCall(Callee Callee, llvm::ArrayRef Args) { + void processCall(Callee Callee, SourceLocation RParenOrBraceLoc, + llvm::ArrayRef Args) { assert(Callee.Decl || Callee.Loc); - if (!Cfg.InlayHints.Parameters || Args.size() == 0) + if ((!Cfg.InlayHints.Parameters && !Cfg.InlayHints.DefaultArguments) || + Args.size() == 0) return; // The parameter name of a move or copy constructor is not very interesting. @@ -721,6 +750,9 @@ class InlayHintVisitor : public RecursiveASTVisitor { if (Ctor->isCopyOrMoveConstructor()) return; + SmallVector FormattedDefaultArgs; + bool HasNonDefaultArgs = false; + ArrayRef Params, ForwardedParams; // Resolve parameter packs to their forwarded parameter SmallVector ForwardedParamsStorage; @@ -752,15 +784,44 @@ class InlayHintVisitor : public RecursiveASTVisitor { } StringRef Name = ParameterNames[I]; - bool NameHint = shouldHintName(Args[I], Name); - bool ReferenceHint = shouldHintReference(Params[I], ForwardedParams[I]); - - if (NameHint || ReferenceHint) { + const bool NameHint = + shouldHintName(Args[I], Name) && Cfg.InlayHints.Parameters; + const bool ReferenceHint = + shouldHintReference(Params[I], ForwardedParams[I]) && + Cfg.InlayHints.Parameters; + + const bool IsDefault = isa(Args[I]); + HasNonDefaultArgs |= !IsDefault; + if (IsDefault) { + if (Cfg.InlayHints.DefaultArguments) { + const auto SourceText = Lexer::getSourceText( + CharSourceRange::getTokenRange(Params[I]->getDefaultArgRange()), + AST.getSourceManager(), AST.getLangOpts()); + const auto Abbrev = + (SourceText.size() > Cfg.InlayHints.TypeNameLimit || + SourceText.contains("\n")) + ? "..." + : SourceText; + if (NameHint) + FormattedDefaultArgs.emplace_back( + llvm::formatv("{0}: {1}", Name, Abbrev)); + else + FormattedDefaultArgs.emplace_back(llvm::formatv("{0}", Abbrev)); + } + } else if (NameHint || ReferenceHint) { addInlayHint(Args[I]->getSourceRange(), HintSide::Left, InlayHintKind::Parameter, ReferenceHint ? "&" : "", NameHint ? Name : "", ": "); } } + + if (!FormattedDefaultArgs.empty()) { + std::string Hint = + joinAndTruncate(FormattedDefaultArgs, Cfg.InlayHints.TypeNameLimit); + addInlayHint(SourceRange{RParenOrBraceLoc}, HintSide::Left, + InlayHintKind::DefaultArgument, + HasNonDefaultArgs ? ", " : "", Hint, ""); + } } static bool isSetter(const FunctionDecl *Callee, const NameVec &ParamNames) { @@ -968,6 +1029,7 @@ class InlayHintVisitor : public RecursiveASTVisitor { CHECK_KIND(Type, DeducedTypes); CHECK_KIND(Designator, Designators); CHECK_KIND(BlockEnd, BlockEnd); + CHECK_KIND(DefaultArgument, DefaultArguments); #undef CHECK_KIND } diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index c08f80442eaa0..295ccd26a4045 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1477,6 +1477,7 @@ llvm::json::Value toJSON(const InlayHintKind &Kind) { return 2; case InlayHintKind::Designator: case InlayHintKind::BlockEnd: + case InlayHintKind::DefaultArgument: // This is an extension, don't serialize. return nullptr; } @@ -1517,6 +1518,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) { return "designator"; case InlayHintKind::BlockEnd: return "block-end"; + case InlayHintKind::DefaultArgument: + return "default-argument"; } llvm_unreachable("Unknown clang.clangd.InlayHintKind"); }; diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index a0f8b04bc4ffd..5b28095758198 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1681,6 +1681,15 @@ enum class InlayHintKind { /// This is a clangd extension. BlockEnd = 4, + /// An inlay hint that is for a default argument. + /// + /// An example of a parameter hint for a default argument: + /// void foo(bool A = true); + /// foo(^); + /// Adds an inlay hint "A: true". + /// This is a clangd extension. + DefaultArgument = 6, + /// Other ideas for hints that are not currently implemented: /// /// * Chaining hints, showing the types of intermediate expressions diff --git a/clang-tools-extra/clangd/URI.h b/clang-tools-extra/clangd/URI.h index 7f3bc9d1645a8..d4629f17551cc 100644 --- a/clang-tools-extra/clangd/URI.h +++ b/clang-tools-extra/clangd/URI.h @@ -133,4 +133,8 @@ typedef llvm::Registry URISchemeRegistry; } // namespace clangd } // namespace clang +namespace llvm { +extern template class Registry; +} // namespace llvm + #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_URI_H diff --git a/clang-tools-extra/clangd/refactor/Tweak.h b/clang-tools-extra/clangd/refactor/Tweak.h index 2769b401d8943..257f44a285f88 100644 --- a/clang-tools-extra/clangd/refactor/Tweak.h +++ b/clang-tools-extra/clangd/refactor/Tweak.h @@ -147,4 +147,8 @@ prepareTweak(StringRef ID, const Tweak::Selection &S, } // namespace clangd } // namespace clang +namespace llvm { +extern template class Registry; +} // namespace llvm + #endif diff --git a/clang-tools-extra/clangd/test/.gitattributes b/clang-tools-extra/clangd/test/.gitattributes deleted file mode 100644 index 20971adc2b5d0..0000000000000 --- a/clang-tools-extra/clangd/test/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -input-mirror.test text eol=crlf -too_large.test text eol=crlf -protocol.test text eol=crlf diff --git a/clang-tools-extra/clangd/test/input-mirror.test b/clang-tools-extra/clangd/test/input-mirror.test index bce3f9923a3b9..a34a4a08cf60c 100644 --- a/clang-tools-extra/clangd/test/input-mirror.test +++ b/clang-tools-extra/clangd/test/input-mirror.test @@ -1,17 +1,17 @@ -# RUN: clangd -pretty -sync -input-mirror-file %t < %s -# Note that we have to use '-b' as -input-mirror-file does not have a newline at the end of file. -# RUN: diff -b %t %s -# It is absolutely vital that this file has CRLF line endings. -# -Content-Length: 125 - -{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} -Content-Length: 172 - -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}} -Content-Length: 44 - -{"jsonrpc":"2.0","id":3,"method":"shutdown"} -Content-Length: 33 - -{"jsonrpc":"2.0","method":"exit"} +# RUN: clangd -pretty -sync -input-mirror-file %t < %s +# Note that we have to use '-b' as -input-mirror-file does not have a newline at the end of file. +# RUN: diff -b %t %s +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 125 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +Content-Length: 172 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}} +Content-Length: 44 + +{"jsonrpc":"2.0","id":3,"method":"shutdown"} +Content-Length: 33 + +{"jsonrpc":"2.0","method":"exit"} diff --git a/clang-tools-extra/clangd/test/log.test b/clang-tools-extra/clangd/test/log.test index 7a53d361ddde5..5cc871972f989 100644 --- a/clang-tools-extra/clangd/test/log.test +++ b/clang-tools-extra/clangd/test/log.test @@ -1,7 +1,7 @@ # RUN: env CLANGD_FLAGS=-compile-commands-dir=no-such-dir not clangd -lit-test &1 >/dev/null | FileCheck %s CHECK: I[{{.*}}]{{.*}} clangd version {{.*}} CHECK: Working directory: {{.*}} -CHECK: argv[0]: clangd +CHECK: argv[0]: {{.*}}clangd CHECK: argv[1]: -lit-test CHECK: CLANGD_FLAGS: -compile-commands-dir=no-such-dir CHECK: E[{{.*}}] Path specified by --compile-commands-dir does not exist. diff --git a/clang-tools-extra/clangd/test/protocol.test b/clang-tools-extra/clangd/test/protocol.test index 64ccfaef18911..5e852d1d9deeb 100644 --- a/clang-tools-extra/clangd/test/protocol.test +++ b/clang-tools-extra/clangd/test/protocol.test @@ -1,113 +1,113 @@ -# RUN: not clangd -pretty -sync -enable-test-uri-scheme < %s | FileCheck -strict-whitespace %s -# RUN: not clangd -pretty -sync -enable-test-uri-scheme < %s 2>&1 | FileCheck -check-prefix=STDERR %s -# vim: fileformat=dos -# It is absolutely vital that this file has CRLF line endings. -# -# Note that we invert the test because we intent to let clangd exit prematurely. -# -# Test protocol parsing -Content-Length: 125 -Content-Type: application/vscode-jsonrpc; charset-utf-8 - -{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} -# Test message with Content-Type after Content-Length -# -# CHECK: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK: } -Content-Length: 246 - -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct fake { int a, bb, ccc; int f(int i, const float f) const; };\nint main() {\n fake f;\n f.\n}\n"}}} - -Content-Length: 104 - -{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp"}}} - -Content-Type: application/vscode-jsonrpc; charset-utf-8 -Content-Length: 146 - -{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} -# Test message with Content-Type before Content-Length -# -# CHECK: "id": 1, -# CHECK-NEXT: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK-NEXT: "isIncomplete": false, -# CHECK-NEXT: "items": [ -# CHECK: "filterText": "a", -# CHECK-NEXT: "insertText": "a", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 5, -# CHECK-NEXT: "label": " a", -# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK: ] -# CHECK-NEXT: } - -X-Test: Testing -Content-Type: application/vscode-jsonrpc; charset-utf-8 -Content-Length: 146 -Content-Type: application/vscode-jsonrpc; charset-utf-8 -X-Testing: Test - -{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} - -Content-Type: application/vscode-jsonrpc; charset-utf-8 -Content-Length: 10 -Content-Length: 146 - -{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} -# Test message with duplicate Content-Length headers -# -# CHECK: "id": 3, -# CHECK-NEXT: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK-NEXT: "isIncomplete": false, -# CHECK-NEXT: "items": [ -# CHECK: "filterText": "a", -# CHECK-NEXT: "insertText": "a", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 5, -# CHECK-NEXT: "label": " a", -# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK: ] -# CHECK-NEXT: } -# STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored. - -Content-Type: application/vscode-jsonrpc; charset-utf-8 -Content-Length: 10 - -{"jsonrpc":"2.0","id":4,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} -# Test message with malformed Content-Length -# -# STDERR: JSON parse error -# Ensure we recover by sending another (valid) message - -Content-Length: 146 - -{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} -# Test message with Content-Type before Content-Length -# -# CHECK: "id": 5, -# CHECK-NEXT: "jsonrpc": "2.0", -# CHECK-NEXT: "result": { -# CHECK-NEXT: "isIncomplete": false, -# CHECK-NEXT: "items": [ -# CHECK: "filterText": "a", -# CHECK-NEXT: "insertText": "a", -# CHECK-NEXT: "insertTextFormat": 1, -# CHECK-NEXT: "kind": 5, -# CHECK-NEXT: "label": " a", -# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, -# CHECK-NEXT: "sortText": "{{.*}}" -# CHECK: ] -# CHECK-NEXT: } -Content-Length: 1024 - -{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} -# Test message which reads beyond the end of the stream. -# -# Ensure this is the last test in the file! -# STDERR: Input was aborted. Read only {{[0-9]+}} bytes of expected {{[0-9]+}}. - +# RUN: not clangd -pretty -sync -enable-test-uri-scheme < %s | FileCheck -strict-whitespace %s +# RUN: not clangd -pretty -sync -enable-test-uri-scheme < %s 2>&1 | FileCheck -check-prefix=STDERR %s +# vim: fileformat=dos +# It is absolutely vital that this file has CRLF line endings. +# +# Note that we invert the test because we intent to let clangd exit prematurely. +# +# Test protocol parsing +Content-Length: 125 +Content-Type: application/vscode-jsonrpc; charset-utf-8 + +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} +# Test message with Content-Type after Content-Length +# +# CHECK: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK: } +Content-Length: 246 + +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct fake { int a, bb, ccc; int f(int i, const float f) const; };\nint main() {\n fake f;\n f.\n}\n"}}} + +Content-Length: 104 + +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp"}}} + +Content-Type: application/vscode-jsonrpc; charset-utf-8 +Content-Length: 146 + +{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} +# Test message with Content-Type before Content-Length +# +# CHECK: "id": 1, +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "isIncomplete": false, +# CHECK-NEXT: "items": [ +# CHECK: "filterText": "a", +# CHECK-NEXT: "insertText": "a", +# CHECK-NEXT: "insertTextFormat": 1, +# CHECK-NEXT: "kind": 5, +# CHECK-NEXT: "label": " a", +# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, +# CHECK-NEXT: "sortText": "{{.*}}" +# CHECK: ] +# CHECK-NEXT: } + +X-Test: Testing +Content-Type: application/vscode-jsonrpc; charset-utf-8 +Content-Length: 146 +Content-Type: application/vscode-jsonrpc; charset-utf-8 +X-Testing: Test + +{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} + +Content-Type: application/vscode-jsonrpc; charset-utf-8 +Content-Length: 10 +Content-Length: 146 + +{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} +# Test message with duplicate Content-Length headers +# +# CHECK: "id": 3, +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "isIncomplete": false, +# CHECK-NEXT: "items": [ +# CHECK: "filterText": "a", +# CHECK-NEXT: "insertText": "a", +# CHECK-NEXT: "insertTextFormat": 1, +# CHECK-NEXT: "kind": 5, +# CHECK-NEXT: "label": " a", +# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, +# CHECK-NEXT: "sortText": "{{.*}}" +# CHECK: ] +# CHECK-NEXT: } +# STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored. + +Content-Type: application/vscode-jsonrpc; charset-utf-8 +Content-Length: 10 + +{"jsonrpc":"2.0","id":4,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} +# Test message with malformed Content-Length +# +# STDERR: JSON parse error +# Ensure we recover by sending another (valid) message + +Content-Length: 146 + +{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} +# Test message with Content-Type before Content-Length +# +# CHECK: "id": 5, +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "isIncomplete": false, +# CHECK-NEXT: "items": [ +# CHECK: "filterText": "a", +# CHECK-NEXT: "insertText": "a", +# CHECK-NEXT: "insertTextFormat": 1, +# CHECK-NEXT: "kind": 5, +# CHECK-NEXT: "label": " a", +# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, +# CHECK-NEXT: "sortText": "{{.*}}" +# CHECK: ] +# CHECK-NEXT: } +Content-Length: 1024 + +{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}} +# Test message which reads beyond the end of the stream. +# +# Ensure this is the last test in the file! +# STDERR: Input was aborted. Read only {{[0-9]+}} bytes of expected {{[0-9]+}}. + diff --git a/clang-tools-extra/clangd/test/too_large.test b/clang-tools-extra/clangd/test/too_large.test index 6986bd5e258e8..7df981e794207 100644 --- a/clang-tools-extra/clangd/test/too_large.test +++ b/clang-tools-extra/clangd/test/too_large.test @@ -1,7 +1,7 @@ -# RUN: not clangd -sync < %s 2>&1 | FileCheck -check-prefix=STDERR %s -# vim: fileformat=dos -# It is absolutely vital that this file has CRLF line endings. -# -Content-Length: 2147483648 - -# STDERR: Refusing to read message +# RUN: not clangd -sync < %s 2>&1 | FileCheck -check-prefix=STDERR %s +# vim: fileformat=dos +# It is absolutely vital that this file has CRLF line endings. +# +Content-Length: 2147483648 + +# STDERR: Refusing to read message diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index a5a349e93037a..73dd273d6c39d 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -15,9 +15,12 @@ #include "support/Context.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/raw_ostream.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include #include +#include #include namespace clang { @@ -81,6 +84,7 @@ Config noHintsConfig() { C.InlayHints.DeducedTypes = false; C.InlayHints.Designators = false; C.InlayHints.BlockEnd = false; + C.InlayHints.DefaultArguments = false; return C; } @@ -1465,6 +1469,75 @@ TEST(TypeHints, DefaultTemplateArgs) { ExpectedHint{": A", "binding"}); } +TEST(DefaultArguments, Smoke) { + Config Cfg; + Cfg.InlayHints.Parameters = + true; // To test interplay of parameters and default parameters + Cfg.InlayHints.DeducedTypes = false; + Cfg.InlayHints.Designators = false; + Cfg.InlayHints.BlockEnd = false; + + Cfg.InlayHints.DefaultArguments = true; + WithContextValue WithCfg(Config::Key, std::move(Cfg)); + + const auto *Code = R"cpp( + int foo(int A = 4) { return A; } + int bar(int A, int B = 1, bool C = foo($default1[[)]]) { return A; } + int A = bar($explicit[[2]]$default2[[)]]; + + void baz(int = 5) { if (false) baz($unnamed[[)]]; }; + )cpp"; + + assertHints(InlayHintKind::DefaultArgument, Code, + ExpectedHint{"A: 4", "default1", Left}, + ExpectedHint{", B: 1, C: foo()", "default2", Left}, + ExpectedHint{"5", "unnamed", Left}); + + assertHints(InlayHintKind::Parameter, Code, + ExpectedHint{"A: ", "explicit", Left}); +} + +TEST(DefaultArguments, WithoutParameterNames) { + Config Cfg; + Cfg.InlayHints.Parameters = false; // To test just default args this time + Cfg.InlayHints.DeducedTypes = false; + Cfg.InlayHints.Designators = false; + Cfg.InlayHints.BlockEnd = false; + + Cfg.InlayHints.DefaultArguments = true; + WithContextValue WithCfg(Config::Key, std::move(Cfg)); + + const auto *Code = R"cpp( + struct Baz { + Baz(float a = 3 // + + 2); + }; + struct Foo { + Foo(int, Baz baz = // + Baz{$abbreviated[[}]] + + // + ) {} + }; + + int main() { + Foo foo1(1$paren[[)]]; + Foo foo2{2$brace1[[}]]; + Foo foo3 = {3$brace2[[}]]; + auto foo4 = Foo{4$brace3[[}]]; + } + )cpp"; + + assertHints(InlayHintKind::DefaultArgument, Code, + ExpectedHint{"...", "abbreviated", Left}, + ExpectedHint{", Baz{}", "paren", Left}, + ExpectedHint{", Baz{}", "brace1", Left}, + ExpectedHint{", Baz{}", "brace2", Left}, + ExpectedHint{", Baz{}", "brace3", Left}); + + assertHints(InlayHintKind::Parameter, Code); +} + TEST(TypeHints, Deduplication) { assertTypeHints(R"cpp( template diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index e8148e06b6af2..9afe497fb3d8b 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -56,6 +56,8 @@ Improvements to clangd Inlay hints ^^^^^^^^^^^ +- Added `DefaultArguments` Inlay Hints option. + Diagnostics ^^^^^^^^^^^ @@ -178,6 +180,10 @@ Changes in existing checks avoid false positive when member initialization depends on a structured binding variable. +- Fixed :doc:`cppcoreguidelines-pro-type-union-access + ` check to + report a location even when the member location is not valid. + - Improved :doc:`misc-definitions-in-headers ` check by rewording the diagnostic note that suggests adding ``inline``. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst index 97fe37b535356..815b5cdeeebe2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst @@ -76,6 +76,16 @@ For example: } } +Exception: accessor methods +``````````````````````````` + +The check assumes *accessor* methods of a class are stable, with a heuristic to +determine which methods are accessors. Specifically, parameter-free ``const`` +methods are treated as accessors. Note that this is not guaranteed to be safe +-- but, it is widely used (safely) in practice, and so we have chosen to treat +it as generally safe. Calls to non ``const`` methods are assumed to modify +the state of the object and affect the stability of earlier accessor calls. + Rely on invariants of uncommon APIs ----------------------------------- diff --git a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h index 98aee5f277cf1..b07b9ed1ac25f 100644 --- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h +++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/IncludeSpeller.h @@ -46,4 +46,8 @@ using IncludeSpellingStrategy = llvm::Registry; std::string spellHeader(const IncludeSpeller::Input &Input); } // namespace clang::include_cleaner +namespace llvm { +extern template class Registry; +} // namespace llvm + #endif diff --git a/clang-tools-extra/test/clang-query/invalid-command-line.cpp b/clang-tools-extra/test/clang-query/invalid-command-line.cpp index e3e8af1d5e7ae..a66acc8037f7d 100644 --- a/clang-tools-extra/test/clang-query/invalid-command-line.cpp +++ b/clang-tools-extra/test/clang-query/invalid-command-line.cpp @@ -1,4 +1,4 @@ // RUN: not clang-query --invalid-arg 2>&1 | FileCheck %s -// CHECK: error: clang-query{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: 'clang-query{{(\.exe)?}} --help' +// CHECK: error: clang-query{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: '{{.*}}clang-query{{(\.exe)?}} --help' // CHECK-NEXT: clang-query{{(\.exe)?}}: Did you mean '--extra-arg'? diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-union-access.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-union-access.cpp index 6abc22b9e4345..2823d38c9b69e 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-union-access.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-union-access.cpp @@ -5,6 +5,10 @@ union U { char union_member2; } u; +union W { + template operator TP *() const; +}; + struct S { int non_union_member; union { @@ -20,17 +24,18 @@ void f(char); void f2(U); void f3(U&); void f4(U*); +W f5(); void check() { u.union_member1 = true; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not access members of unions; use (boost::)variant instead [cppcoreguidelines-pro-type-union-access] + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not access members of unions; consider using (boost::)variant instead [cppcoreguidelines-pro-type-union-access] auto b = u.union_member2; - // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not access members of unions; use (boost::)variant instead + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not access members of unions; consider using (boost::)variant instead auto a = &s.union_member; - // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not access members of unions; use (boost::)variant instead + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not access members of unions; consider using (boost::)variant instead f(s.u.union_member2); - // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not access members of unions; use (boost::)variant instead + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not access members of unions; consider using (boost::)variant instead s.non_union_member = 2; // OK @@ -38,4 +43,6 @@ void check() f2(u); // OK f3(u); // OK f4(&u); // OK + void *ret = f5(); + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not access members of unions; consider using (boost::)variant instead } diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp index c06b09d90004e..4bdca50af32ca 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/invalid-command-line.cpp @@ -1,4 +1,4 @@ // RUN: not clang-tidy --invalid-arg 2>&1 | FileCheck %s -// CHECK: error: clang-tidy{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: 'clang-tidy{{(\.exe)?}} --help' +// CHECK: error: clang-tidy{{(\.exe)?}}: Unknown command line argument '--invalid-arg'. Try: '{{.*}}clang-tidy{{(\.exe)?}} --help' // CHECK-NEXT: clang-tidy{{(\.exe)?}}: Did you mean '--extra-arg'? diff --git a/clang-tools-extra/unittests/clang-tidy/AddConstTest.cpp b/clang-tools-extra/unittests/clang-tidy/AddConstTest.cpp index dfae25f3f26eb..d8c76049e393f 100644 --- a/clang-tools-extra/unittests/clang-tidy/AddConstTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/AddConstTest.cpp @@ -27,8 +27,8 @@ class ConstTransform : public ClangTidyCheck { void check(const MatchFinder::MatchResult &Result) override { const auto *D = Result.Nodes.getNodeAs("var"); using utils::fixit::addQualifierToVarDecl; - std::optional Fix = addQualifierToVarDecl( - *D, *Result.Context, DeclSpec::TQ::TQ_const, CT, CP); + std::optional Fix = + addQualifierToVarDecl(*D, *Result.Context, Qualifiers::Const, CT, CP); auto Diag = diag(D->getBeginLoc(), "doing const transformation"); if (Fix) Diag << *Fix; diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b7a6ace8bb895..28bb83a1c9d60 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -439,8 +439,10 @@ Bug Fixes in This Version - Fixed a crash when trying to transform a dependent address space type. Fixes #GH101685. - Fixed a crash when diagnosing format strings and encountering an empty delimited escape sequence (e.g., ``"\o{}"``). #GH102218 +- Fixed a crash using ``__array_rank`` on 64-bit targets. (#GH113044). - The warning emitted for an unsupported register variable type now points to the unsupported type instead of the ``register`` keyword (#GH109776). +- Fixed a crash when emit ctor for global variant with flexible array init (#GH113187). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +509,7 @@ Bug Fixes to C++ Support - Clang no longer tries to capture non-odr used default arguments of template parameters of generic lambdas (#GH107048) - Fixed a bug where defaulted comparison operators would remove ``const`` from base classes. (#GH102588) - Fix a crash when using ``source_location`` in the trailing return type of a lambda expression. (#GH67134) -- A follow-up fix was added for (#GH61460), as the previous fix was not entirely correct. (#GH86361) +- A follow-up fix was added for (#GH61460), as the previous fix was not entirely correct. (#GH86361), (#GH112352) - Fixed a crash in the typo correction of an invalid CTAD guide. (#GH107887) - Fixed a crash when clang tries to subtitute parameter pack while retaining the parameter pack. (#GH63819), (#GH107560) @@ -539,6 +541,9 @@ Bug Fixes to C++ Support - Fix erroneous templated array size calculation leading to crashes in generated code. (#GH41441) - During the lookup for a base class name, non-type names are ignored. (#GH16855) - Fix a crash when recovering an invalid expression involving an explicit object member conversion operator. (#GH112559) +- Clang incorrectly considered a class with an anonymous union member to not be + const-default-constructible even if a union member has a default member initializer. + (#GH95854). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/docs/analyzer/user-docs/CommandLineUsage.rst b/clang/docs/analyzer/user-docs/CommandLineUsage.rst index d7f8253469df4..59f8187f374a9 100644 --- a/clang/docs/analyzer/user-docs/CommandLineUsage.rst +++ b/clang/docs/analyzer/user-docs/CommandLineUsage.rst @@ -2,7 +2,7 @@ Command Line Usage: scan-build and CodeChecker ============================================== This document provides guidelines for running the static analyzer from the command line on whole projects. -CodeChecker and scan-build are two CLI tools for using CSA on multiple files (tranlation units). +CodeChecker and scan-build are two CLI tools for using CSA on multiple files (translation units). Both provide a way of driving the analyzer, detecting compilation flags, and generating reports. CodeChecker is more actively maintained, provides heuristics for working with multiple versions of popular compilers and it also comes with a web-based GUI for viewing, filtering, categorizing and suppressing the results. Therefore CodeChecker is recommended in case you need any of the above features or just more customizability in general. diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 4f99bf4ebe309..0c5ac80772e2b 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2980,7 +2980,7 @@ enum CXTypeKind { CXType_Atomic = 177, CXType_BTFTagAttributed = 178, - // HLSL Types + /* HLSL Types */ CXType_HLSLResource = 179, CXType_HLSLAttributedResource = 180 }; diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 975bcdac5069b..cfe3938f83847 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -876,13 +876,13 @@ class CXXTypeidExpr : public Expr { /// Best-effort check if the expression operand refers to a most derived /// object. This is not a strong guarantee. - bool isMostDerived(ASTContext &Context) const; + bool isMostDerived(const ASTContext &Context) const; bool isTypeOperand() const { return Operand.is(); } /// Retrieves the type operand of this typeid() expression after /// various required adjustments (removing reference types, cv-qualifiers). - QualType getTypeOperand(ASTContext &Context) const; + QualType getTypeOperand(const ASTContext &Context) const; /// Retrieve source information for the type operand. TypeSourceInfo *getTypeOperandSourceInfo() const { diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h index 29913fd84c58b..f3e32ce396198 100644 --- a/clang/include/clang/AST/ExprConcepts.h +++ b/clang/include/clang/AST/ExprConcepts.h @@ -489,14 +489,6 @@ class NestedRequirement : public Requirement { return R->getKind() == RK_Nested; } }; - -using EntityPrinter = llvm::function_ref; - -/// \brief create a Requirement::SubstitutionDiagnostic with only a -/// SubstitutedEntity and DiagLoc using Sema's allocator. -Requirement::SubstitutionDiagnostic * -createSubstDiagAt(Sema &S, SourceLocation Location, EntityPrinter Printer); - } // namespace concepts /// C++2a [expr.prim.req]: diff --git a/clang/include/clang/AST/ExternalASTSource.h b/clang/include/clang/AST/ExternalASTSource.h index 385c32edbae0f..582ed7c65f58c 100644 --- a/clang/include/clang/AST/ExternalASTSource.h +++ b/clang/include/clang/AST/ExternalASTSource.h @@ -25,10 +25,12 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/Support/PointerLikeTypeTraits.h" +#include #include #include #include #include +#include #include #include @@ -326,29 +328,49 @@ struct LazyOffsetPtr { /// /// If the low bit is clear, a pointer to the AST node. If the low /// bit is set, the upper 63 bits are the offset. - mutable uint64_t Ptr = 0; + static constexpr size_t DataSize = std::max(sizeof(uint64_t), sizeof(T *)); + alignas(uint64_t) alignas(T *) mutable unsigned char Data[DataSize] = {}; + + unsigned char GetLSB() const { + return Data[llvm::sys::IsBigEndianHost ? DataSize - 1 : 0]; + } + + template U &As(bool New) const { + unsigned char *Obj = + Data + (llvm::sys::IsBigEndianHost ? DataSize - sizeof(U) : 0); + if (New) + return *new (Obj) U; + return *std::launder(reinterpret_cast(Obj)); + } + + T *&GetPtr() const { return As(false); } + uint64_t &GetU64() const { return As(false); } + void SetPtr(T *Ptr) const { As(true) = Ptr; } + void SetU64(uint64_t U64) const { As(true) = U64; } public: LazyOffsetPtr() = default; - explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast(Ptr)) {} + explicit LazyOffsetPtr(T *Ptr) : Data() { SetPtr(Ptr); } - explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { + explicit LazyOffsetPtr(uint64_t Offset) : Data() { assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); if (Offset == 0) - Ptr = 0; + SetPtr(nullptr); + else + SetU64((Offset << 1) | 0x01); } LazyOffsetPtr &operator=(T *Ptr) { - this->Ptr = reinterpret_cast(Ptr); + SetPtr(Ptr); return *this; } LazyOffsetPtr &operator=(uint64_t Offset) { assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); if (Offset == 0) - Ptr = 0; + SetPtr(nullptr); else - Ptr = (Offset << 1) | 0x01; + SetU64((Offset << 1) | 0x01); return *this; } @@ -356,15 +378,15 @@ struct LazyOffsetPtr { /// Whether this pointer is non-NULL. /// /// This operation does not require the AST node to be deserialized. - explicit operator bool() const { return Ptr != 0; } + explicit operator bool() const { return isOffset() || GetPtr() != nullptr; } /// Whether this pointer is non-NULL. /// /// This operation does not require the AST node to be deserialized. - bool isValid() const { return Ptr != 0; } + bool isValid() const { return isOffset() || GetPtr() != nullptr; } /// Whether this pointer is currently stored as an offset. - bool isOffset() const { return Ptr & 0x01; } + bool isOffset() const { return GetLSB() & 0x01; } /// Retrieve the pointer to the AST node that this lazy pointer points to. /// @@ -375,9 +397,9 @@ struct LazyOffsetPtr { if (isOffset()) { assert(Source && "Cannot deserialize a lazy pointer without an AST source"); - Ptr = reinterpret_cast((Source->*Get)(OffsT(Ptr >> 1))); + SetPtr((Source->*Get)(OffsT(GetU64() >> 1))); } - return reinterpret_cast(Ptr); + return GetPtr(); } /// Retrieve the address of the AST node pointer. Deserializes the pointee if @@ -385,7 +407,7 @@ struct LazyOffsetPtr { T **getAddressOfPointer(ExternalASTSource *Source) const { // Ensure the integer is in pointer form. (void)get(Source); - return reinterpret_cast(&Ptr); + return &GetPtr(); } }; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 40e617bf8f3b8..ba3161c366f4d 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2661,8 +2661,10 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) bool is##Id##Type() const; #include "clang/Basic/HLSLIntangibleTypes.def" bool isHLSLSpecificType() const; // Any HLSL specific type - bool isHLSLIntangibleType() const; // Any HLSL intangible type + bool isHLSLBuiltinIntangibleType() const; // Any HLSL builtin intangible type bool isHLSLAttributedResourceType() const; + bool isHLSLIntangibleType() + const; // Any HLSL intangible type (builtin, array, class) /// Determines if this type, which must satisfy /// isObjCLifetimeType(), is implicitly __unsafe_unretained rather @@ -8450,15 +8452,15 @@ inline bool Type::isOpenCLSpecificType() const { } #include "clang/Basic/HLSLIntangibleTypes.def" -inline bool Type::isHLSLIntangibleType() const { +inline bool Type::isHLSLBuiltinIntangibleType() const { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) is##Id##Type() || return #include "clang/Basic/HLSLIntangibleTypes.def" - isHLSLAttributedResourceType(); + false; } inline bool Type::isHLSLSpecificType() const { - return isHLSLIntangibleType() || isa(this); + return isHLSLBuiltinIntangibleType() || isHLSLAttributedResourceType(); } inline bool Type::isHLSLAttributedResourceType() const { diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h index 592a3898a2959..f781e0a565eb3 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -49,6 +49,8 @@ #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H +#include "clang/Support/Compiler.h" + /// AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... } /// defines a zero parameter function named DefineMatcher() that returns a /// ReturnType object. @@ -367,7 +369,7 @@ static QualType (T::*value())() const { return &T::FunctionName; } \ }; \ } \ - extern const ::clang::ast_matchers::internal:: \ + CLANG_ABI extern const ::clang::ast_matchers::internal:: \ TypeTraversePolymorphicMatcher< \ QualType, \ ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \ @@ -407,7 +409,7 @@ static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \ }; \ } \ - extern const ::clang::ast_matchers::internal:: \ + CLANG_ABI extern const ::clang::ast_matchers::internal:: \ TypeTraversePolymorphicMatcher< \ TypeLoc, \ ::clang::ast_matchers::internal:: \ diff --git a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h index 09eb8b9382261..9d81cacb50735 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h +++ b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h @@ -17,6 +17,7 @@ #include "clang/AST/ASTContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h" +#include "clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/NoopLattice.h" @@ -39,23 +40,28 @@ struct UncheckedOptionalAccessModelOptions { bool IgnoreSmartPointerDereference = false; }; +using UncheckedOptionalAccessLattice = CachedConstAccessorsLattice; + /// Dataflow analysis that models whether optionals hold values or not. /// /// Models the `std::optional`, `absl::optional`, and `base::Optional` types. class UncheckedOptionalAccessModel - : public DataflowAnalysis { + : public DataflowAnalysis { public: UncheckedOptionalAccessModel(ASTContext &Ctx, dataflow::Environment &Env); /// Returns a matcher for the optional classes covered by this model. static ast_matchers::DeclarationMatcher optionalClassDecl(); - static NoopLattice initialElement() { return {}; } + static UncheckedOptionalAccessLattice initialElement() { return {}; } - void transfer(const CFGElement &Elt, NoopLattice &L, Environment &Env); + void transfer(const CFGElement &Elt, UncheckedOptionalAccessLattice &L, + Environment &Env); private: - CFGMatchSwitch> TransferMatchSwitch; + CFGMatchSwitch> + TransferMatchSwitch; }; class UncheckedOptionalAccessDiagnoser { @@ -65,7 +71,8 @@ class UncheckedOptionalAccessDiagnoser { llvm::SmallVector operator()(const CFGElement &Elt, ASTContext &Ctx, - const TransferStateForDiagnostics &State) { + const TransferStateForDiagnostics + &State) { return DiagnoseMatchSwitch(Elt, Ctx, State.Env); } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b1512e22ee2dd..ee8126cadae23 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2669,7 +2669,7 @@ sign. For example: .. code-block:: c++ - __attribute__((target_clones("sha2+memtag2", "fcma+sve2-pmull128"))) + __attribute__((target_clones("sha2+memtag", "fcma+sve2-pmull128"))) void foo() {} For every multiversioned function a ``default`` (fallback) implementation diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index c02970f55b22e..e887213aa945e 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -224,8 +224,8 @@ TARGET_BUILTIN(__builtin_amdgcn_frexp_exph, "sh", "nc", "16-bit-insts") TARGET_BUILTIN(__builtin_amdgcn_fracth, "hh", "nc", "16-bit-insts") TARGET_BUILTIN(__builtin_amdgcn_classh, "bhi", "nc", "16-bit-insts") TARGET_BUILTIN(__builtin_amdgcn_s_memrealtime, "WUi", "n", "s-memrealtime") -TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nc", "dpp") -TARGET_BUILTIN(__builtin_amdgcn_update_dpp, "iiiIiIiIiIb", "nc", "dpp") +TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nct", "dpp") +TARGET_BUILTIN(__builtin_amdgcn_update_dpp, "iiiIiIiIiIb", "nct", "dpp") TARGET_BUILTIN(__builtin_amdgcn_s_dcache_wb, "v", "n", "gfx8-insts") TARGET_BUILTIN(__builtin_amdgcn_perm, "UiUiUiUi", "nc", "gfx8-insts") diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index eac831278ee20..e45370bde74a5 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -136,6 +136,8 @@ CODEGENOPT(XRayIgnoreLoops , 1, 0) ///< Emit the XRay function index section. CODEGENOPT(XRayFunctionIndex , 1, 1) +///< Set when -fxray-shared is enabled +CODEGENOPT(XRayShared , 1, 0) ///< Set the minimum number of instructions in a function to determine selective ///< XRay instrumentation. diff --git a/clang/include/clang/Basic/Cuda.h b/clang/include/clang/Basic/Cuda.h index a18e62620dd5d..7b4f435dc39f2 100644 --- a/clang/include/clang/Basic/Cuda.h +++ b/clang/include/clang/Basic/Cuda.h @@ -127,6 +127,7 @@ enum class OffloadArch { GFX1150, GFX1151, GFX1152, + GFX1153, GFX12_GENERIC, GFX1200, GFX1201, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 883db838ca014..8e4718008ece7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10188,7 +10188,7 @@ def warn_new_dangling_initializer_list : Warning< "will be destroyed at the end of the full-expression">, InGroup; def warn_dangling_pointer_assignment : Warning< - "object backing the pointer %0 " + "object backing %select{|the pointer }0%1 " "will be destroyed at the end of the full-expression">, InGroup; diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index ce4e8c1fbe16e..6cc6c2bfd2b6b 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -124,8 +124,8 @@ class FileManager : public RefCountedBase { std::unique_ptr StatCache; std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status, - bool isFile, - std::unique_ptr *F); + bool isFile, std::unique_ptr *F, + bool IsText = true); /// Add all ancestors of the given path (pointing to either a file /// or a directory) as virtual directories. @@ -230,7 +230,8 @@ class FileManager : public RefCountedBase { /// the failure to find this file. llvm::Expected getFileRef(StringRef Filename, bool OpenFile = false, - bool CacheFailure = true); + bool CacheFailure = true, + bool IsText = true); /// Get the FileEntryRef for stdin, returning an error if stdin cannot be /// read. @@ -290,23 +291,28 @@ class FileManager : public RefCountedBase { /// Open the specified file as a MemoryBuffer, returning a new /// MemoryBuffer if successful, otherwise returning null. + /// The IsText parameter controls whether the file should be opened as a text + /// or binary file, and should be set to false if the file contents should be + /// treated as binary. llvm::ErrorOr> getBufferForFile(FileEntryRef Entry, bool isVolatile = false, bool RequiresNullTerminator = true, - std::optional MaybeLimit = std::nullopt); + std::optional MaybeLimit = std::nullopt, + bool IsText = true); llvm::ErrorOr> getBufferForFile(StringRef Filename, bool isVolatile = false, bool RequiresNullTerminator = true, - std::optional MaybeLimit = std::nullopt) const { + std::optional MaybeLimit = std::nullopt, + bool IsText = true) const { return getBufferForFileImpl(Filename, /*FileSize=*/MaybeLimit.value_or(-1), - isVolatile, RequiresNullTerminator); + isVolatile, RequiresNullTerminator, IsText); } private: llvm::ErrorOr> getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile, - bool RequiresNullTerminator) const; + bool RequiresNullTerminator, bool IsText) const; DirectoryEntry *&getRealDirEntry(const llvm::vfs::Status &Status); diff --git a/clang/include/clang/Basic/FileSystemStatCache.h b/clang/include/clang/Basic/FileSystemStatCache.h index 5a003a748178d..73c256a016971 100644 --- a/clang/include/clang/Basic/FileSystemStatCache.h +++ b/clang/include/clang/Basic/FileSystemStatCache.h @@ -48,10 +48,10 @@ class FileSystemStatCache { /// success for directories (not files). On a successful file lookup, the /// implementation can optionally fill in \p F with a valid \p File object and /// the client guarantees that it will close it. - static std::error_code - get(StringRef Path, llvm::vfs::Status &Status, bool isFile, - std::unique_ptr *F, - FileSystemStatCache *Cache, llvm::vfs::FileSystem &FS); + static std::error_code get(StringRef Path, llvm::vfs::Status &Status, + bool isFile, std::unique_ptr *F, + FileSystemStatCache *Cache, + llvm::vfs::FileSystem &FS, bool IsText = true); protected: // FIXME: The pointer here is a non-owning/optional reference to the diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index e86f4303d732b..9c5d33fbb562c 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -48,6 +48,7 @@ namespace clang { class FileManager; class LangOptions; +class ModuleMap; class TargetInfo; /// Describes the name of a module. @@ -99,6 +100,15 @@ struct ASTFileSignature : std::array { } }; +/// Required to construct a Module. +/// +/// This tag type is only constructible by ModuleMap, guaranteeing it ownership +/// of all Module instances. +class ModuleConstructorTag { + explicit ModuleConstructorTag() = default; + friend ModuleMap; +}; + /// Describes a module or submodule. /// /// Aligned to 8 bytes to allow for llvm::PointerIntPair. @@ -497,8 +507,9 @@ class alignas(8) Module { std::vector Conflicts; /// Construct a new module or submodule. - Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - bool IsFramework, bool IsExplicit, unsigned VisibilityID); + Module(ModuleConstructorTag, StringRef Name, SourceLocation DefinitionLoc, + Module *Parent, bool IsFramework, bool IsExplicit, + unsigned VisibilityID); ~Module(); @@ -749,7 +760,6 @@ class alignas(8) Module { /// /// \returns The submodule if found, or NULL otherwise. Module *findSubmodule(StringRef Name) const; - Module *findOrInferSubmodule(StringRef Name); /// Get the Global Module Fragment (sub-module) for this module, it there is /// one. diff --git a/clang/include/clang/Basic/ParsedAttrInfo.h b/clang/include/clang/Basic/ParsedAttrInfo.h index fab5c6f1377d2..3b5f5d3c3f92a 100644 --- a/clang/include/clang/Basic/ParsedAttrInfo.h +++ b/clang/include/clang/Basic/ParsedAttrInfo.h @@ -17,6 +17,7 @@ #include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/AttributeCommonInfo.h" +#include "clang/Support/Compiler.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Registry.h" #include @@ -175,4 +176,8 @@ const std::list> &getAttributePluginInstances(); } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI Registry; +} // namespace llvm + #endif // LLVM_CLANG_BASIC_PARSEDATTRINFO_H diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 5778385060629..e7469e1e98912 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -87,6 +87,7 @@ enum class FloatModeKind { struct TransferrableTargetInfo { unsigned char PointerWidth, PointerAlign; unsigned char BoolWidth, BoolAlign; + unsigned char ShortWidth, ShortAlign; unsigned char IntWidth, IntAlign; unsigned char HalfWidth, HalfAlign; unsigned char BFloat16Width, BFloat16Align; @@ -497,13 +498,10 @@ class TargetInfo : public TransferrableTargetInfo, unsigned getCharWidth() const { return 8; } // FIXME unsigned getCharAlign() const { return 8; } // FIXME - /// Return the size of 'signed short' and 'unsigned short' for this - /// target, in bits. - unsigned getShortWidth() const { return 16; } // FIXME - - /// Return the alignment of 'signed short' and 'unsigned short' for - /// this target. - unsigned getShortAlign() const { return 16; } // FIXME + /// getShortWidth/Align - Return the size of 'signed short' and + /// 'unsigned short' for this target, in bits. + unsigned getShortWidth() const { return ShortWidth; } + unsigned getShortAlign() const { return ShortAlign; } /// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for /// this target, in bits. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 152c43d7908ff..8472be3719cde 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2948,6 +2948,11 @@ def fxray_selected_function_group : HelpText<"When using -fxray-function-groups, select which group of functions to instrument. Valid range is 0 to fxray-function-groups - 1">, MarshallingInfoInt, "0">; +defm xray_shared : BoolFOption<"xray-shared", + CodeGenOpts<"XRayShared">, DefaultFalse, + PosFlag, + NegFlag>; defm fine_grained_bitfield_accesses : BoolOption<"f", "fine-grained-bitfield-accesses", CodeGenOpts<"FineGrainedBitfieldAccesses">, DefaultFalse, @@ -5394,6 +5399,10 @@ def mfrecipe : Flag<["-"], "mfrecipe">, Group, HelpText<"Enable frecipe.{s/d} and frsqrte.{s/d}">; def mno_frecipe : Flag<["-"], "mno-frecipe">, Group, HelpText<"Disable frecipe.{s/d} and frsqrte.{s/d}">; +def mlam_bh : Flag<["-"], "mlam-bh">, Group, + HelpText<"Enable amswap_[db].{b/h} and amadd_[db].{b/h}">; +def mno_lam_bh : Flag<["-"], "mno-lam-bh">, Group, + HelpText<"Disable amswap_[db].{b/h} and amadd_[db].{b/h}">; def mannotate_tablejump : Flag<["-"], "mannotate-tablejump">, Group, HelpText<"Enable annotate table jump instruction to correlate it with the jump table.">; def mno_annotate_tablejump : Flag<["-"], "mno-annotate-tablejump">, Group, @@ -8102,7 +8111,7 @@ def fnative_half_type: Flag<["-"], "fnative-half-type">, def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and-returns">, HelpText<"Use the native __fp16 type for arguments and returns (and skip ABI-specific lowering)">, MarshallingInfoFlag>, - ImpliedByAnyOf<[open_cl.KeyPath, render_script.KeyPath, hlsl.KeyPath]>; + ImpliedByAnyOf<[open_cl.KeyPath, render_script.KeyPath, hlsl.KeyPath, hip.KeyPath]>; def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">, HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall,rtdcall">, diff --git a/clang/include/clang/Driver/XRayArgs.h b/clang/include/clang/Driver/XRayArgs.h index bdd3d979547ee..1b5c4a4c42f12 100644 --- a/clang/include/clang/Driver/XRayArgs.h +++ b/clang/include/clang/Driver/XRayArgs.h @@ -27,6 +27,7 @@ class XRayArgs { XRayInstrSet InstrumentationBundle; llvm::opt::Arg *XRayInstrument = nullptr; bool XRayRT = true; + bool XRayShared = false; public: /// Parses the XRay arguments from an argument list. @@ -35,6 +36,7 @@ class XRayArgs { llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const; bool needsXRayRt() const { return XRayInstrument && XRayRT; } + bool needsXRayDSORt() const { return XRayInstrument && XRayRT && XRayShared; } llvm::ArrayRef modeList() const { return Modes; } XRayInstrSet instrumentationBundle() const { return InstrumentationBundle; } }; diff --git a/clang/include/clang/Frontend/FrontendPluginRegistry.h b/clang/include/clang/Frontend/FrontendPluginRegistry.h index 810578534acb4..5eea9c2fd89a3 100644 --- a/clang/include/clang/Frontend/FrontendPluginRegistry.h +++ b/clang/include/clang/Frontend/FrontendPluginRegistry.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H #include "clang/Frontend/FrontendAction.h" +#include "clang/Support/Compiler.h" #include "llvm/Support/Registry.h" namespace clang { @@ -23,4 +24,8 @@ using FrontendPluginRegistry = llvm::Registry; } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI Registry; +} // namespace llvm + #endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index 2e28ff6823cb2..75b567a347cb6 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -93,9 +93,12 @@ class ModuleMap { /// named LangOpts::CurrentModule, if we've loaded it). Module *SourceModule = nullptr; + /// The allocator for all (sub)modules. + llvm::SpecificBumpPtrAllocator ModulesAlloc; + /// Submodules of the current module that have not yet been attached to it. - /// (Ownership is transferred if/when we create an enclosing module.) - llvm::SmallVector, 8> PendingSubmodules; + /// (Relationship is set up if/when we create an enclosing module.) + llvm::SmallVector PendingSubmodules; /// The top-level modules that are known. llvm::StringMap Modules; @@ -502,6 +505,8 @@ class ModuleMap { /// \returns The named module, if known; otherwise, returns null. Module *findModule(StringRef Name) const; + Module *findOrInferSubmodule(Module *Parent, StringRef Name); + /// Retrieve a module with the given name using lexical name lookup, /// starting at the given context. /// diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 4643b0213815f..92749e4de44b5 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -32,6 +32,7 @@ #include "clang/Lex/PPEmbedParameters.h" #include "clang/Lex/Token.h" #include "clang/Lex/TokenLexer.h" +#include "clang/Support/Compiler.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -3060,4 +3061,8 @@ using PragmaHandlerRegistry = llvm::Registry; } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI Registry; +} // namespace llvm + #endif // LLVM_CLANG_LEX_PREPROCESSOR_H diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index bc9c422ed4c47..9e6b04bc3f8f7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13435,6 +13435,13 @@ class Sema final : public SemaBase { return CodeSynthesisContexts.size() > NonInstantiationEntries; } + using EntityPrinter = llvm::function_ref; + + /// \brief create a Requirement::SubstitutionDiagnostic with only a + /// SubstitutedEntity and DiagLoc using ASTContext's allocator. + concepts::Requirement::SubstitutionDiagnostic * + createSubstDiagAt(SourceLocation Location, EntityPrinter Printer); + ///@} // diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 4f1fc9a31404c..e30acd87f7721 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -132,7 +132,6 @@ class SemaHLSL : public SemaBase { // HLSL Type trait implementations bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const; - bool IsIntangibleType(QualType T1); bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old); diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h index 30e7f6b3e57bd..29d3354d07a12 100644 --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_SERIALIZATION_MODULEFILE_H #include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "clang/Serialization/ASTBitCodes.h" @@ -144,8 +145,8 @@ class ModuleFile { /// The base directory of the module. std::string BaseDirectory; - std::string getTimestampFilename() const { - return FileName + ".timestamp"; + static std::string getTimestampFilename(StringRef FileName) { + return (FileName + ".timestamp").str(); } /// The original source file name that was used to build the diff --git a/clang/include/clang/Support/Compiler.h b/clang/include/clang/Support/Compiler.h index c35815e106d2e..13582b899dc2a 100644 --- a/clang/include/clang/Support/Compiler.h +++ b/clang/include/clang/Support/Compiler.h @@ -49,7 +49,8 @@ #define CLANG_TEMPLATE_ABI __declspec(dllimport) #define CLANG_EXPORT_TEMPLATE #endif -#elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX) +#elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX) || \ + defined(__MVS__) #define CLANG_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT #define CLANG_TEMPLATE_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT #define CLANG_EXPORT_TEMPLATE diff --git a/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h index 8c58ad926a402..e6bcac542b0ec 100644 --- a/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h +++ b/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H #define LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H +#include "clang/Support/Compiler.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/Registry.h" @@ -42,4 +43,9 @@ using CompilationDatabasePluginRegistry = } // namespace tooling } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI + Registry; +} // namespace llvm + #endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H diff --git a/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h b/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h index 5304ff26252de..8d54583234684 100644 --- a/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h +++ b/clang/include/clang/Tooling/ToolExecutorPluginRegistry.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H #define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H +#include "clang/Support/Compiler.h" #include "clang/Tooling/Execution.h" #include "llvm/Support/Registry.h" @@ -20,4 +21,9 @@ using ToolExecutorPluginRegistry = llvm::Registry; } // namespace tooling } // namespace clang +namespace llvm { +extern template class CLANG_TEMPLATE_ABI + Registry; +} // namespace llvm + #endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 672fa7fc25d6d..59e09a44d747b 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -2371,9 +2371,9 @@ bool Compiler::VisitStringLiteral(const StringLiteral *E) { template bool Compiler::VisitObjCStringLiteral(const ObjCStringLiteral *E) { - if (std::optional I = P.getOrCreateDummy(E)) - return this->emitGetPtrGlobal(*I, E); - return false; + if (DiscardResult) + return true; + return this->emitDummyPtr(E, E); } template @@ -3445,11 +3445,8 @@ bool Compiler::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { assert(RD); // If the definiton of the result type is incomplete, just return a dummy. // If (and when) that is read from, we will fail, but not now. - if (!RD->isCompleteDefinition()) { - if (std::optional I = P.getOrCreateDummy(GuidDecl)) - return this->emitGetPtrGlobal(*I, E); - return false; - } + if (!RD->isCompleteDefinition()) + return this->emitDummyPtr(GuidDecl, E); std::optional GlobalIndex = P.getOrCreateGlobal(GuidDecl); if (!GlobalIndex) @@ -3687,11 +3684,11 @@ bool Compiler::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { if (!E->isExpressibleAsConstantInitializer()) return this->discard(SubExpr) && this->emitInvalid(E); - assert(classifyPrim(E) == PT_Ptr); - if (std::optional I = P.getOrCreateDummy(E)) - return this->emitGetPtrGlobal(*I, E); + if (DiscardResult) + return true; - return false; + assert(classifyPrim(E) == PT_Ptr); + return this->emitDummyPtr(E, E); } template @@ -4483,15 +4480,9 @@ bool Compiler::VisitBuiltinCallExpr(const CallExpr *E, BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString || BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant || BuiltinID == Builtin::BI__builtin_function_start) { - if (std::optional GlobalOffset = P.getOrCreateDummy(E)) { - if (!this->emitGetPtrGlobal(*GlobalOffset, E)) - return false; - - if (PrimType PT = classifyPrim(E); PT != PT_Ptr && isPtrType(PT)) - return this->emitDecayPtr(PT_Ptr, PT, E); + if (DiscardResult) return true; - } - return false; + return this->emitDummyPtr(E, E); } QualType ReturnType = E->getType(); @@ -5738,9 +5729,17 @@ bool Compiler::VisitUnaryOperator(const UnaryOperator *E) { // We should already have a pointer when we get here. return this->delegate(SubExpr); case UO_Deref: // *x - if (DiscardResult) + if (DiscardResult) { + // assert(false); return this->discard(SubExpr); - return this->visit(SubExpr); + } + + if (!this->visit(SubExpr)) + return false; + if (classifyPrim(SubExpr) == PT_Ptr) + return this->emitNarrowPtr(E); + return true; + case UO_Not: // ~x if (!T) return this->emitError(E); @@ -6089,7 +6088,12 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { if (VD->evaluateValue()) return revisit(VD); - return this->emitInvalidDeclRef(cast(E), E); + + if (!D->getType()->isReferenceType()) + return this->emitDummyPtr(D, E); + + return this->emitInvalidDeclRef(cast(E), + /*InitializerFailed=*/true, E); } } } else { @@ -6100,23 +6104,7 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { } } - if (std::optional I = P.getOrCreateDummy(D)) { - if (!this->emitGetPtrGlobal(*I, E)) - return false; - if (E->getType()->isVoidType()) - return true; - // Convert the dummy pointer to another pointer type if we have to. - if (PrimType PT = classifyPrim(E); PT != PT_Ptr) { - if (isPtrType(PT)) - return this->emitDecayPtr(PT_Ptr, PT, E); - return false; - } - return true; - } - - if (const auto *DRE = dyn_cast(E)) - return this->emitInvalidDeclRef(DRE, E); - return false; + return this->emitDummyPtr(D, E); } template @@ -6419,6 +6407,29 @@ bool Compiler::emitDestruction(const Descriptor *Desc, return this->emitRecordDestruction(Desc->ElemRecord, Loc); } +/// Create a dummy pointer for the given decl (or expr) and +/// push a pointer to it on the stack. +template +bool Compiler::emitDummyPtr(const DeclTy &D, const Expr *E) { + assert(!DiscardResult && "Should've been checked before"); + + unsigned DummyID = P.getOrCreateDummy(D); + + if (!this->emitGetPtrGlobal(DummyID, E)) + return false; + if (E->getType()->isVoidType()) + return true; + + // Convert the dummy pointer to another pointer type if we have to. + if (PrimType PT = classifyPrim(E); PT != PT_Ptr) { + if (isPtrType(PT)) + return this->emitDecayPtr(PT_Ptr, PT, E); + return false; + } + + return true; +} + namespace clang { namespace interp { diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 4253e7b3248c9..5627d5071e810 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -370,6 +370,7 @@ class Compiler : public ConstStmtVisitor, bool>, const BinaryOperator *E); bool emitRecordDestruction(const Record *R, SourceInfo Loc); bool emitDestruction(const Descriptor *Desc, SourceInfo Loc); + bool emitDummyPtr(const DeclTy &D, const Expr *E); unsigned collectBaseOffset(const QualType BaseType, const QualType DerivedType); bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD); diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index fdc4b38b8aa6d..b7a6c224c80f8 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -81,11 +81,17 @@ static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC, return false; } - if (!D->getType().isConstQualified()) + if (!D->getType().isConstQualified()) { diagnoseNonConstVariable(S, OpPC, D); - else if (const auto *VD = dyn_cast(D); - VD && !VD->getAnyInitializer()) - diagnoseMissingInitializer(S, OpPC, VD); + } else if (const auto *VD = dyn_cast(D)) { + if (!VD->getAnyInitializer()) { + diagnoseMissingInitializer(S, OpPC, VD); + } else { + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD; + S.Note(VD->getLocation(), diag::note_declared_at); + } + } return false; } diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index aafc848a9c53f..c95b18ef72c96 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1944,14 +1944,14 @@ inline bool CastMemberPtrPtr(InterpState &S, CodePtr OpPC) { template bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, - const Pointer &Ptr) { + const Pointer &Ptr, bool IsPointerArith = false) { // A zero offset does not change the pointer. if (Offset.isZero()) { S.Stk.push(Ptr); return true; } - if (!CheckNull(S, OpPC, Ptr, CSK_ArrayIndex)) { + if (IsPointerArith && !CheckNull(S, OpPC, Ptr, CSK_ArrayIndex)) { // The CheckNull will have emitted a note already, but we only // abort in C++, since this is fine in C. if (S.getLangOpts().CPlusPlus) @@ -2063,14 +2063,16 @@ bool AddOffset(InterpState &S, CodePtr OpPC) { Pointer Ptr = S.Stk.pop(); if (Ptr.isBlockPointer()) Ptr = Ptr.expand(); - return OffsetHelper(S, OpPC, Offset, Ptr); + return OffsetHelper(S, OpPC, Offset, Ptr, + /*IsPointerArith=*/true); } template ::T> bool SubOffset(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop(); const Pointer &Ptr = S.Stk.pop(); - return OffsetHelper(S, OpPC, Offset, Ptr); + return OffsetHelper(S, OpPC, Offset, Ptr, + /*IsPointerArith=*/true); } template @@ -2090,7 +2092,7 @@ static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC, // Now the current Ptr again and a constant 1. OneT One = OneT::from(1); - if (!OffsetHelper(S, OpPC, One, P)) + if (!OffsetHelper(S, OpPC, One, P, /*IsPointerArith=*/true)) return false; // Store the new value. @@ -2816,9 +2818,18 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, return false; } -inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, - const DeclRefExpr *DR) { +inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR, + bool InitializerFailed) { assert(DR); + + if (InitializerFailed) { + const SourceInfo &Loc = S.Current->getSource(OpPC); + const auto *VD = cast(DR->getDecl()); + S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD; + S.Note(VD->getLocation(), diag::note_declared_at); + return false; + } + return CheckDeclRef(S, OpPC, DR); } diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index d4a8e6c2035ee..10e33c14f4b45 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1253,6 +1253,10 @@ static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call) { + if (!Call->getArg(0)->getType()->isIntegerType() || + !Call->getArg(1)->getType()->isIntegerType()) + return false; + PrimType ValT = *S.Ctx.classify(Call->getArg(0)); PrimType IndexT = *S.Ctx.classify(Call->getArg(1)); APSInt Val = peekToAPSInt(S.Stk, ValT, @@ -1331,6 +1335,10 @@ static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call) { + if (!Call->getArg(0)->getType()->isIntegerType() || + !Call->getArg(1)->getType()->isIntegerType()) + return false; + PrimType ValT = *S.Ctx.classify(Call->getArg(0)); PrimType MaskT = *S.Ctx.classify(Call->getArg(1)); @@ -1352,6 +1360,10 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call) { + if (!Call->getArg(0)->getType()->isIntegerType() || + !Call->getArg(1)->getType()->isIntegerType()) + return false; + PrimType ValT = *S.Ctx.classify(Call->getArg(0)); PrimType MaskT = *S.Ctx.classify(Call->getArg(1)); diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index a1970f25ca977..9136e6b51660d 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -769,7 +769,7 @@ def InvalidCast : Opcode { } def InvalidDeclRef : Opcode { - let Args = [ArgDeclRef]; + let Args = [ArgDeclRef, ArgBool]; } def SizelessVectorElementSize : Opcode; diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 75b00dcb2ab24..c9de039c195d9 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -635,7 +635,7 @@ std::optional Pointer::toRValue(const Context &Ctx, // Return the composite type. APValue Result; - if (!Composite(getType(), *this, Result)) + if (!Composite(ResultType, *this, Result)) return std::nullopt; return Result; } diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index cd2665f755d7c..0da518ec92afa 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -147,7 +147,7 @@ std::optional Program::getOrCreateGlobal(const ValueDecl *VD, return std::nullopt; } -std::optional Program::getOrCreateDummy(const DeclTy &D) { +unsigned Program::getOrCreateDummy(const DeclTy &D) { assert(D); // Dedup blocks since they are immutable and pointers cannot be compared. if (auto It = DummyVariables.find(D.getOpaqueValue()); diff --git a/clang/lib/AST/ByteCode/Program.h b/clang/lib/AST/ByteCode/Program.h index f676672fb7ced..9aabe67b550ec 100644 --- a/clang/lib/AST/ByteCode/Program.h +++ b/clang/lib/AST/ByteCode/Program.h @@ -85,7 +85,7 @@ class Program final { const Expr *Init = nullptr); /// Returns or creates a dummy value for unknown declarations. - std::optional getOrCreateDummy(const DeclTy &D); + unsigned getOrCreateDummy(const DeclTy &D); /// Creates a global and returns its index. std::optional createGlobal(const ValueDecl *VD, const Expr *Init); diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 08615d4393f5d..17ebee0d6b22f 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1060,6 +1060,9 @@ void CXXRecordDecl::addedMember(Decl *D) { if (isUnion() && !Field->isAnonymousStructOrUnion()) data().HasVariantMembers = true; + if (isUnion() && IsFirstField) + data().HasUninitializedFields = true; + // C++0x [class]p9: // A POD struct is a class that is both a trivial class and a // standard-layout class, and has no non-static data members of type @@ -1128,7 +1131,10 @@ void CXXRecordDecl::addedMember(Decl *D) { data().DefaultedCopyConstructorIsDeleted = true; } - if (!Field->hasInClassInitializer() && !Field->isMutable()) { + if (isUnion() && !Field->isMutable()) { + if (Field->hasInClassInitializer()) + data().HasUninitializedFields = false; + } else if (!Field->hasInClassInitializer() && !Field->isMutable()) { if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) { if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit()) data().HasUninitializedFields = true; @@ -1414,7 +1420,8 @@ void CXXRecordDecl::addedMember(Decl *D) { if (const RecordType *RT = dyn_cast(Ty)) data().IsHLSLIntangible |= RT->getAsCXXRecordDecl()->isHLSLIntangible(); else - data().IsHLSLIntangible |= Ty->isHLSLIntangibleType(); + data().IsHLSLIntangible |= (Ty->isHLSLAttributedResourceType() || + Ty->isHLSLBuiltinIntangibleType()); } } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 83ce404add5f5..a2c0c60d43dd1 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -147,7 +147,7 @@ bool CXXTypeidExpr::isPotentiallyEvaluated() const { return false; } -bool CXXTypeidExpr::isMostDerived(ASTContext &Context) const { +bool CXXTypeidExpr::isMostDerived(const ASTContext &Context) const { assert(!isTypeOperand() && "Cannot call isMostDerived for typeid(type)"); const Expr *E = getExprOperand()->IgnoreParenNoopCasts(Context); if (const auto *DRE = dyn_cast(E)) { @@ -159,7 +159,7 @@ bool CXXTypeidExpr::isMostDerived(ASTContext &Context) const { return false; } -QualType CXXTypeidExpr::getTypeOperand(ASTContext &Context) const { +QualType CXXTypeidExpr::getTypeOperand(const ASTContext &Context) const { assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); Qualifiers Quals; return Context.getUnqualifiedArrayType( diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 5232efae4e363..0afba0a1c92af 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -5030,6 +5030,29 @@ bool Type::hasSizedVLAType() const { return false; } +bool Type::isHLSLIntangibleType() const { + const Type *Ty = getUnqualifiedDesugaredType(); + + // check if it's a builtin type first + if (Ty->isBuiltinType()) + return Ty->isHLSLBuiltinIntangibleType(); + + // unwrap arrays + while (isa(Ty)) + Ty = Ty->getArrayElementTypeNoTypeQual(); + + const RecordType *RT = + dyn_cast(Ty->getUnqualifiedDesugaredType()); + if (!RT) + return false; + + CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); + assert(RD != nullptr && + "all HLSL struct and classes should be CXXRecordDecl"); + assert(RD->isCompleteDefinition() && "expecting complete type"); + return RD->isHLSLIntangible(); +} + QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { switch (type.getObjCLifetime()) { case Qualifiers::OCL_None: diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp index 70ffe92753e05..b0bd8274405d0 100644 --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -17,13 +17,14 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchersMacros.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/Formula.h" -#include "clang/Analysis/FlowSensitive/NoopLattice.h" +#include "clang/Analysis/FlowSensitive/RecordOps.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Basic/SourceLocation.h" @@ -104,10 +105,17 @@ static const CXXRecordDecl *getOptionalBaseClass(const CXXRecordDecl *RD) { return nullptr; } +static bool isSupportedOptionalType(QualType Ty) { + const CXXRecordDecl *Optional = + getOptionalBaseClass(Ty->getAsCXXRecordDecl()); + return Optional != nullptr; +} + namespace { using namespace ::clang::ast_matchers; -using LatticeTransferState = TransferState; + +using LatticeTransferState = TransferState; AST_MATCHER(CXXRecordDecl, optionalClass) { return hasOptionalClassName(Node); } @@ -325,6 +333,19 @@ auto isValueOrNotEqX() { ComparesToSame(integerLiteral(equals(0))))); } +auto isZeroParamConstMemberCall() { + return cxxMemberCallExpr( + callee(cxxMethodDecl(parameterCountIs(0), isConst()))); +} + +auto isNonConstMemberCall() { + return cxxMemberCallExpr(callee(cxxMethodDecl(unless(isConst())))); +} + +auto isNonConstMemberOperatorCall() { + return cxxOperatorCallExpr(callee(cxxMethodDecl(unless(isConst())))); +} + auto isCallReturningOptional() { return callExpr(hasType(qualType( anyOf(desugarsToOptionalOrDerivedType(), @@ -523,6 +544,99 @@ void transferCallReturningOptional(const CallExpr *E, setHasValue(*Loc, State.Env.makeAtomicBoolValue(), State.Env); } +void handleConstMemberCall(const CallExpr *CE, + dataflow::RecordStorageLocation *RecordLoc, + const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + // If the const method returns an optional or reference to an optional. + if (RecordLoc != nullptr && isSupportedOptionalType(CE->getType())) { + StorageLocation *Loc = + State.Lattice.getOrCreateConstMethodReturnStorageLocation( + *RecordLoc, CE, State.Env, [&](StorageLocation &Loc) { + setHasValue(cast(Loc), + State.Env.makeAtomicBoolValue(), State.Env); + }); + if (Loc == nullptr) + return; + if (CE->isGLValue()) { + // If the call to the const method returns a reference to an optional, + // link the call expression to the cached StorageLocation. + State.Env.setStorageLocation(*CE, *Loc); + } else { + // If the call to the const method returns an optional by value, we + // need to use CopyRecord to link the optional to the result object + // of the call expression. + auto &ResultLoc = State.Env.getResultObjectLocation(*CE); + copyRecord(*cast(Loc), ResultLoc, State.Env); + } + return; + } + + // Cache if the const method returns a boolean type. + // We may decide to cache other return types in the future. + if (RecordLoc != nullptr && CE->getType()->isBooleanType()) { + Value *Val = State.Lattice.getOrCreateConstMethodReturnValue(*RecordLoc, CE, + State.Env); + if (Val == nullptr) + return; + State.Env.setValue(*CE, *Val); + return; + } + + // Perform default handling if the call returns an optional + // but wasn't handled above (if RecordLoc is nullptr). + if (isSupportedOptionalType(CE->getType())) { + transferCallReturningOptional(CE, Result, State); + } +} + +void transferValue_ConstMemberCall(const CXXMemberCallExpr *MCE, + const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + handleConstMemberCall( + MCE, dataflow::getImplicitObjectLocation(*MCE, State.Env), Result, State); +} + +void handleNonConstMemberCall(const CallExpr *CE, + dataflow::RecordStorageLocation *RecordLoc, + const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + // When a non-const member function is called, reset some state. + if (RecordLoc != nullptr) { + for (const auto &[Field, FieldLoc] : RecordLoc->children()) { + if (isSupportedOptionalType(Field->getType())) { + auto *FieldRecordLoc = cast_or_null(FieldLoc); + if (FieldRecordLoc) { + setHasValue(*FieldRecordLoc, State.Env.makeAtomicBoolValue(), + State.Env); + } + } + } + State.Lattice.clearConstMethodReturnValues(*RecordLoc); + State.Lattice.clearConstMethodReturnStorageLocations(*RecordLoc); + } + + // Perform default handling if the call returns an optional. + if (isSupportedOptionalType(CE->getType())) { + transferCallReturningOptional(CE, Result, State); + } +} + +void transferValue_NonConstMemberCall(const CXXMemberCallExpr *MCE, + const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + handleNonConstMemberCall( + MCE, dataflow::getImplicitObjectLocation(*MCE, State.Env), Result, State); +} + +void transferValue_NonConstMemberOperatorCall( + const CXXOperatorCallExpr *OCE, const MatchFinder::MatchResult &Result, + LatticeTransferState &State) { + auto *RecordLoc = cast_or_null( + State.Env.getStorageLocation(*OCE->getArg(0))); + handleNonConstMemberCall(OCE, RecordLoc, Result, State); +} + void constructOptionalValue(const Expr &E, Environment &Env, BoolValue &HasValueVal) { RecordStorageLocation &Loc = Env.getResultObjectLocation(E); @@ -899,7 +1013,17 @@ auto buildTransferMatchSwitch() { transferOptionalAndValueCmp(Cmp, Cmp->getArg(1), State.Env); }) - // returns optional + // const accessor calls + .CaseOfCFGStmt(isZeroParamConstMemberCall(), + transferValue_ConstMemberCall) + // non-const member calls that may modify the state of an object. + .CaseOfCFGStmt(isNonConstMemberCall(), + transferValue_NonConstMemberCall) + .CaseOfCFGStmt( + isNonConstMemberOperatorCall(), + transferValue_NonConstMemberOperatorCall) + + // other cases of returning optional .CaseOfCFGStmt(isCallReturningOptional(), transferCallReturningOptional) @@ -958,7 +1082,8 @@ UncheckedOptionalAccessModel::optionalClassDecl() { UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(ASTContext &Ctx, Environment &Env) - : DataflowAnalysis(Ctx), + : DataflowAnalysis(Ctx), TransferMatchSwitch(buildTransferMatchSwitch()) { Env.getDataflowAnalysisContext().setSyntheticFieldCallback( [&Ctx](QualType Ty) -> llvm::StringMap { @@ -972,7 +1097,8 @@ UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(ASTContext &Ctx, } void UncheckedOptionalAccessModel::transfer(const CFGElement &Elt, - NoopLattice &L, Environment &Env) { + UncheckedOptionalAccessLattice &L, + Environment &Env) { LatticeTransferState State(L, Env); TransferMatchSwitch(Elt, getASTContext(), State); } diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp index 08989b6c2c03f..d765baef913e2 100644 --- a/clang/lib/Basic/Cuda.cpp +++ b/clang/lib/Basic/Cuda.cpp @@ -145,6 +145,7 @@ static const OffloadArchToStringMap arch_names[] = { GFX(1150), // gfx1150 GFX(1151), // gfx1151 GFX(1152), // gfx1152 + GFX(1153), // gfx1153 {OffloadArch::GFX12_GENERIC, "gfx12-generic", "compute_amdgcn"}, GFX(1200), // gfx1200 GFX(1201), // gfx1201 diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index 6097b85a03064..2876c290a26b1 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -212,8 +212,10 @@ FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) { return llvm::errorToErrorCode(Result.takeError()); } -llvm::Expected -FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { +llvm::Expected FileManager::getFileRef(StringRef Filename, + bool openFile, + bool CacheFailure, + bool IsText) { ++NumFileLookups; // See if there is already an entry in the map. @@ -259,7 +261,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { std::unique_ptr F; llvm::vfs::Status Status; auto statError = getStatValue(InterndFileName, Status, true, - openFile ? &F : nullptr); + openFile ? &F : nullptr, IsText); if (statError) { // There's no real file at the given path. if (CacheFailure) @@ -531,7 +533,7 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) { llvm::ErrorOr> FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile, bool RequiresNullTerminator, - std::optional MaybeLimit) { + std::optional MaybeLimit, bool IsText) { const FileEntry *Entry = &FE.getFileEntry(); // If the content is living on the file entry, return a reference to it. if (Entry->Content) @@ -558,21 +560,21 @@ FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile, // Otherwise, open the file. return getBufferForFileImpl(Filename, FileSize, isVolatile, - RequiresNullTerminator); + RequiresNullTerminator, IsText); } llvm::ErrorOr> FileManager::getBufferForFileImpl(StringRef Filename, int64_t FileSize, - bool isVolatile, - bool RequiresNullTerminator) const { + bool isVolatile, bool RequiresNullTerminator, + bool IsText) const { if (FileSystemOpts.WorkingDir.empty()) return FS->getBufferForFile(Filename, FileSize, RequiresNullTerminator, - isVolatile); + isVolatile, IsText); SmallString<128> FilePath(Filename); FixupRelativePath(FilePath); return FS->getBufferForFile(FilePath, FileSize, RequiresNullTerminator, - isVolatile); + isVolatile, IsText); } /// getStatValue - Get the 'stat' information for the specified path, @@ -580,20 +582,22 @@ FileManager::getBufferForFileImpl(StringRef Filename, int64_t FileSize, /// if the path points to a virtual file or does not exist, or returns /// false if it's an existent real file. If FileDescriptor is NULL, /// do directory look-up instead of file look-up. -std::error_code -FileManager::getStatValue(StringRef Path, llvm::vfs::Status &Status, - bool isFile, std::unique_ptr *F) { +std::error_code FileManager::getStatValue(StringRef Path, + llvm::vfs::Status &Status, + bool isFile, + std::unique_ptr *F, + bool IsText) { // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be // absolute! if (FileSystemOpts.WorkingDir.empty()) - return FileSystemStatCache::get(Path, Status, isFile, F, - StatCache.get(), *FS); + return FileSystemStatCache::get(Path, Status, isFile, F, StatCache.get(), + *FS, IsText); SmallString<128> FilePath(Path); FixupRelativePath(FilePath); return FileSystemStatCache::get(FilePath.c_str(), Status, isFile, F, - StatCache.get(), *FS); + StatCache.get(), *FS, IsText); } std::error_code diff --git a/clang/lib/Basic/FileSystemStatCache.cpp b/clang/lib/Basic/FileSystemStatCache.cpp index 415a4e2025df8..183eea0986637 100644 --- a/clang/lib/Basic/FileSystemStatCache.cpp +++ b/clang/lib/Basic/FileSystemStatCache.cpp @@ -30,11 +30,12 @@ void FileSystemStatCache::anchor() {} /// success for directories (not files). On a successful file lookup, the /// implementation can optionally fill in FileDescriptor with a valid /// descriptor and the client guarantees that it will close it. -std::error_code -FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status, - bool isFile, std::unique_ptr *F, - FileSystemStatCache *Cache, - llvm::vfs::FileSystem &FS) { +std::error_code FileSystemStatCache::get(StringRef Path, + llvm::vfs::Status &Status, bool isFile, + std::unique_ptr *F, + FileSystemStatCache *Cache, + llvm::vfs::FileSystem &FS, + bool IsText) { bool isForDir = !isFile; std::error_code RetCode; @@ -58,7 +59,8 @@ FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status, // // Because of this, check to see if the file exists with 'open'. If the // open succeeds, use fstat to get the stat info. - auto OwnedFile = FS.openFileForRead(Path); + auto OwnedFile = + IsText ? FS.openFileForRead(Path) : FS.openFileForReadBinary(Path); if (!OwnedFile) { // If the open fails, our "stat" fails. diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index fee372bce3a36..ad52fccff5dc7 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -34,8 +34,9 @@ using namespace clang; -Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - bool IsFramework, bool IsExplicit, unsigned VisibilityID) +Module::Module(ModuleConstructorTag, StringRef Name, + SourceLocation DefinitionLoc, Module *Parent, bool IsFramework, + bool IsExplicit, unsigned VisibilityID) : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), VisibilityID(VisibilityID), IsUnimportable(false), HasIncompatibleModuleFile(false), IsAvailable(true), @@ -58,11 +59,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, } } -Module::~Module() { - for (auto *Submodule : SubModules) { - delete Submodule; - } -} +Module::~Module() = default; static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) { StringRef Platform = Target.getPlatformName(); @@ -361,21 +358,6 @@ Module *Module::findSubmodule(StringRef Name) const { return SubModules[Pos->getValue()]; } -Module *Module::findOrInferSubmodule(StringRef Name) { - llvm::StringMap::const_iterator Pos = SubModuleIndex.find(Name); - if (Pos != SubModuleIndex.end()) - return SubModules[Pos->getValue()]; - if (!InferSubmodules) - return nullptr; - Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0); - Result->InferExplicitSubmodules = InferExplicitSubmodules; - Result->InferSubmodules = InferSubmodules; - Result->InferExportWildcard = InferExportWildcard; - if (Result->InferExportWildcard) - Result->Exports.push_back(Module::ExportDecl(nullptr, true)); - return Result; -} - Module *Module::getGlobalModuleFragment() const { assert(isNamedModuleUnit() && "We should only query the global module " "fragment from the C++20 Named modules"); diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 9219533382109..145ca545854da 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -70,6 +70,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) { HasStrictFP = false; PointerWidth = PointerAlign = 32; BoolWidth = BoolAlign = 8; + ShortWidth = ShortAlign = 16; IntWidth = IntAlign = 32; LongWidth = LongAlign = 32; LongLongWidth = LongLongAlign = 64; @@ -437,6 +438,7 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { // what these normally are for the target. // We also define long long and long double here, although the // OpenCL standard only mentions these as "reserved". + ShortWidth = ShortAlign = 16; IntWidth = IntAlign = 32; LongWidth = LongAlign = 64; LongLongWidth = LongLongAlign = 128; diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index b96fab978a3fc..3dbba2b4d25bd 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -784,7 +784,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const { .Case("sme-fa64", HasSMEFA64) .Case("sme-f16f16", HasSMEF16F16) .Case("sme-b16b16", HasSMEB16B16) - .Cases("memtag", "memtag2", HasMTE) + .Case("memtag", HasMTE) .Case("sb", HasSB) .Case("predres", HasPredRes) .Cases("ssbs", "ssbs2", HasSSBS) diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp index 3b748d0249d57..078819183afda 100644 --- a/clang/lib/Basic/Targets/AMDGPU.cpp +++ b/clang/lib/Basic/Targets/AMDGPU.cpp @@ -260,9 +260,9 @@ AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple, void AMDGPUTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { TargetInfo::adjust(Diags, Opts); // ToDo: There are still a few places using default address space as private - // address space in OpenCL, which needs to be cleaned up, then Opts.OpenCL - // can be removed from the following line. - setAddressSpaceMap(/*DefaultIsPrivate=*/Opts.OpenCL || + // address space in OpenCL, which needs to be cleaned up, then the references + // to OpenCL can be removed from the following line. + setAddressSpaceMap((Opts.OpenCL && !Opts.OpenCLGenericAddressSpace) || !isAMDGCN(getTriple())); } diff --git a/clang/lib/Basic/Targets/AVR.h b/clang/lib/Basic/Targets/AVR.h index feeb04f37eeba..0a2f51747f8a7 100644 --- a/clang/lib/Basic/Targets/AVR.h +++ b/clang/lib/Basic/Targets/AVR.h @@ -29,6 +29,8 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo { TLSSupported = false; PointerWidth = 16; PointerAlign = 8; + ShortWidth = 16; + ShortAlign = 8; IntWidth = 16; IntAlign = 8; LongWidth = 32; @@ -65,6 +67,8 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo { return std::nullopt; } + bool allowsLargerPreferedTypeAlignment() const override { return false; } + BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; } diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp index cb3fd12c48ddb..07b22b35f603c 100644 --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -205,7 +205,7 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts, // TODO: As more features of the V1.1 ISA are supported, a unified "v1.1" // arch feature set will be used to include all sub-features belonging to // the V1.1 ISA version. - if (HasFeatureFrecipe) + if (HasFeatureFrecipe && HasFeatureLAM_BH) Builder.defineMacro("__loongarch_arch", Twine('"') + "la64v1.1" + Twine('"')); else @@ -236,6 +236,9 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts, if (HasFeatureFrecipe) Builder.defineMacro("__loongarch_frecipe", Twine(1)); + if (HasFeatureLAM_BH) + Builder.defineMacro("__loongarch_lam_bh", Twine(1)); + StringRef ABI = getABI(); if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s") Builder.defineMacro("__loongarch_lp64"); @@ -312,6 +315,8 @@ bool LoongArchTargetInfo::handleTargetFeatures( HasUnalignedAccess = false; else if (Feature == "+frecipe") HasFeatureFrecipe = true; + else if (Feature == "+lam-bh") + HasFeatureLAM_BH = true; } return true; } diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h index c668ca7eca047..3585e9f7968b4 100644 --- a/clang/lib/Basic/Targets/LoongArch.h +++ b/clang/lib/Basic/Targets/LoongArch.h @@ -30,6 +30,7 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { bool HasFeatureLSX; bool HasFeatureLASX; bool HasFeatureFrecipe; + bool HasFeatureLAM_BH; public: LoongArchTargetInfo(const llvm::Triple &Triple, const TargetOptions &) @@ -39,6 +40,7 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { HasFeatureLSX = false; HasFeatureLASX = false; HasFeatureFrecipe = false; + HasFeatureLAM_BH = false; LongDoubleWidth = 128; LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad(); diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp index 88a0dbde52d52..e0bd0b096324d 100644 --- a/clang/lib/Basic/Targets/NVPTX.cpp +++ b/clang/lib/Basic/Targets/NVPTX.cpp @@ -229,6 +229,7 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, case OffloadArch::GFX1150: case OffloadArch::GFX1151: case OffloadArch::GFX1152: + case OffloadArch::GFX1153: case OffloadArch::GFX12_GENERIC: case OffloadArch::GFX1200: case OffloadArch::GFX1201: diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 684fda7440731..41bb8d19d161e 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1397,7 +1397,8 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D, DI->setLocation(D->getLocation()); DI->EmitDeclareOfBlockLiteralArgVariable( *BlockInfo, D->getName(), argNum, - cast(alloc.getPointer()), Builder); + cast(alloc.getPointer()->stripPointerCasts()), + Builder); } } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 28f28c70b5ae5..3f28b7f26c36f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -5853,8 +5853,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, /*IndexTypeQuals=*/0); auto Tmp = CreateMemTemp(SizeArrayTy, "block_sizes"); llvm::Value *TmpPtr = Tmp.getPointer(); + // The EmitLifetime* pair expect a naked Alloca as their last argument, + // however for cases where the default AS is not the Alloca AS, Tmp is + // actually the Alloca ascasted to the default AS, hence the + // stripPointerCasts() + llvm::Value *Alloca = TmpPtr->stripPointerCasts(); llvm::Value *TmpSize = EmitLifetimeStart( - CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), TmpPtr); + CGM.getDataLayout().getTypeAllocSize(Tmp.getElementType()), Alloca); llvm::Value *ElemPtr; // Each of the following arguments specifies the size of the corresponding // argument passed to the enqueued block. @@ -5870,7 +5875,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateAlignedStore( V, GEP, CGM.getDataLayout().getPrefTypeAlign(SizeTy)); } - return std::tie(ElemPtr, TmpSize, TmpPtr); + // Return the Alloca itself rather than a potential ascast as this is only + // used by the paired EmitLifetimeEnd. + return std::tie(ElemPtr, TmpSize, Alloca); }; // Could have events and/or varargs. @@ -19037,15 +19044,32 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, ASTContext::GetBuiltinTypeError Error; getContext().GetBuiltinType(BuiltinID, Error, &ICEArguments); assert(Error == ASTContext::GE_None && "Should not codegen an error"); + llvm::Type *DataTy = ConvertType(E->getArg(0)->getType()); + unsigned Size = DataTy->getPrimitiveSizeInBits(); + llvm::Type *IntTy = + llvm::IntegerType::get(Builder.getContext(), std::max(Size, 32u)); + Function *F = CGM.getIntrinsic(Intrinsic::amdgcn_update_dpp, IntTy); + assert(E->getNumArgs() == 5 || E->getNumArgs() == 6); + bool InsertOld = E->getNumArgs() == 5; + if (InsertOld) + Args.push_back(llvm::PoisonValue::get(IntTy)); for (unsigned I = 0; I != E->getNumArgs(); ++I) { - Args.push_back(EmitScalarOrConstFoldImmArg(ICEArguments, I, E)); + llvm::Value *V = EmitScalarOrConstFoldImmArg(ICEArguments, I, E); + if (I <= !InsertOld && Size < 32) { + if (!DataTy->isIntegerTy()) + V = Builder.CreateBitCast( + V, llvm::IntegerType::get(Builder.getContext(), Size)); + V = Builder.CreateZExtOrBitCast(V, IntTy); + } + llvm::Type *ExpTy = + F->getFunctionType()->getFunctionParamType(I + InsertOld); + Args.push_back(Builder.CreateTruncOrBitCast(V, ExpTy)); } - assert(Args.size() == 5 || Args.size() == 6); - if (Args.size() == 5) - Args.insert(Args.begin(), llvm::PoisonValue::get(Args[0]->getType())); - Function *F = - CGM.getIntrinsic(Intrinsic::amdgcn_update_dpp, Args[0]->getType()); - return Builder.CreateCall(F, Args); + Value *V = Builder.CreateCall(F, Args); + if (Size < 32 && !DataTy->isIntegerTy()) + V = Builder.CreateTrunc( + V, llvm::IntegerType::get(Builder.getContext(), Size)); + return Builder.CreateTruncOrBitCast(V, DataTy); } case AMDGPU::BI__builtin_amdgcn_permlane16: case AMDGPU::BI__builtin_amdgcn_permlanex16: diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index b4f1a68cfe87f..2c3054605ee75 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -815,7 +815,10 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) { assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice || getLangOpts().GPUAllowDeviceInit); if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) { - Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); + if (getTriple().isSPIRV()) + Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL); + else + Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); Fn->addFnAttr("device-init"); } @@ -973,7 +976,10 @@ CodeGenModule::EmitCXXGlobalInitFunc() { assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice || getLangOpts().GPUAllowDeviceInit); if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) { - Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); + if (getTriple().isSPIRV()) + Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL); + else + Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); Fn->addFnAttr("device-init"); } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 7529d4465f2c3..9e2c2ad5e0250 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -722,7 +722,7 @@ class ScalarExprEmitter } Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { - return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue()); + return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue()); } Value *VisitExpressionTraitExpr(const ExpressionTraitExpr *E) { diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 3747b00d4893a..5e9f89b18918d 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -9672,8 +9672,8 @@ static void emitTargetCallKernelLaunch( DynCGGroupMem, HasNoWait); CGF.Builder.restoreIP(OMPRuntime->getOMPBuilder().emitKernelLaunch( - CGF.Builder, OutlinedFn, OutlinedFnID, EmitTargetCallFallbackCB, Args, - DeviceID, RTLoc, AllocaIP)); + CGF.Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID, + RTLoc, AllocaIP)); }; if (RequiresOuterTask) diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 35ff75416cb77..2e5ab6e7b9ac5 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -2322,6 +2322,7 @@ void CGOpenMPRuntimeGPU::processRequiresDirective(const OMPRequiresDecl *D) { case OffloadArch::GFX1150: case OffloadArch::GFX1151: case OffloadArch::GFX1152: + case OffloadArch::GFX1153: case OffloadArch::GFX12_GENERIC: case OffloadArch::GFX1200: case OffloadArch::GFX1201: diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 2306043c90f40..465dc8c661af5 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2904,19 +2904,18 @@ void CodeGenFunction::EmitMultiVersionResolver( } } -static int getPriorityFromAttrString(StringRef AttrStr) { +static unsigned getPriorityFromAttrString(StringRef AttrStr) { SmallVector Attrs; AttrStr.split(Attrs, ';'); // Default Priority is zero. - int Priority = 0; + unsigned Priority = 0; for (auto Attr : Attrs) { if (Attr.consume_front("priority=")) { - int Result; - if (!Attr.getAsInteger(0, Result)) { + unsigned Result; + if (!Attr.getAsInteger(0, Result)) Priority = Result; - } } } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 24655b809b2ef..2bcca5e85bdfe 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5529,12 +5529,14 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, T = D->getType(); if (getLangOpts().CPlusPlus) { - if (InitDecl->hasFlexibleArrayInit(getContext())) - ErrorUnsupported(D, "flexible array initializer"); Init = EmitNullConstant(T); - if (!IsDefinitionAvailableExternally) NeedsGlobalCtor = true; + if (InitDecl->hasFlexibleArrayInit(getContext())) { + ErrorUnsupported(D, "flexible array initializer"); + // We cannot create ctor for flexible array initializer + NeedsGlobalCtor = false; + } } else { ErrorUnsupported(D, "static initializer"); Init = llvm::UndefValue::get(getTypes().ConvertType(T)); diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 5b3393ec150e4..ec175b7fabe61 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -39,8 +39,9 @@ CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes, llvm::Module &M, const CodeGenOptions &CGO, const LangOptions &Features) : Context(Ctx), CGTypes(CGTypes), Module(M), CodeGenOpts(CGO), - Features(Features), MDHelper(M.getContext()), Root(nullptr), - Char(nullptr) {} + Features(Features), + MangleCtx(ItaniumMangleContext::create(Ctx, Ctx.getDiagnostics())), + MDHelper(M.getContext()), Root(nullptr), Char(nullptr) {} CodeGenTBAA::~CodeGenTBAA() { } @@ -202,14 +203,6 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { // Other qualifiers could theoretically be distinguished, especially if // they involve a significant representation difference. We don't // currently do so, however. - // - // Computing the pointee type string recursively is implicitly more - // forgiving than the standards require. Effectively, we are turning - // the question "are these types compatible/similar" into "are - // accesses to these types allowed to alias". In both C and C++, - // the latter question has special carve-outs for signedness - // mismatches that only apply at the top level. As a result, we are - // allowing e.g. `int *` l-values to access `unsigned *` objects. if (Ty->isPointerType() || Ty->isReferenceType()) { llvm::MDNode *AnyPtr = createScalarTypeNode("any pointer", getChar(), Size); if (!CodeGenOpts.PointerTBAA) @@ -221,21 +214,34 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { PtrDepth++; Ty = Ty->getPointeeType().getTypePtr(); } while (Ty->isPointerType()); - // TODO: Implement C++'s type "similarity" and consider dis-"similar" - // pointers distinct for non-builtin types. + Ty = Context.getBaseElementType(QualType(Ty, 0)).getTypePtr(); + assert(!isa(Ty)); + // When the underlying type is a builtin type, we compute the pointee type + // string recursively, which is implicitly more forgiving than the standards + // require. Effectively, we are turning the question "are these types + // compatible/similar" into "are accesses to these types allowed to alias". + // In both C and C++, the latter question has special carve-outs for + // signedness mismatches that only apply at the top level. As a result, we + // are allowing e.g. `int *` l-values to access `unsigned *` objects. + SmallString<256> TyName; if (isa(Ty)) { llvm::MDNode *ScalarMD = getTypeInfoHelper(Ty); StringRef Name = cast( ScalarMD->getOperand(CodeGenOpts.NewStructPathTBAA ? 2 : 0)) ->getString(); - SmallString<256> OutName("p"); - OutName += std::to_string(PtrDepth); - OutName += " "; - OutName += Name; - return createScalarTypeNode(OutName, AnyPtr, Size); + TyName = Name; + } else { + // For non-builtin types use the mangled name of the canonical type. + llvm::raw_svector_ostream TyOut(TyName); + MangleCtx->mangleCanonicalTypeName(QualType(Ty, 0), TyOut); } - return AnyPtr; + + SmallString<256> OutName("p"); + OutName += std::to_string(PtrDepth); + OutName += " "; + OutName += TyName; + return createScalarTypeNode(OutName, AnyPtr, Size); } // Accesses to arrays are accesses to objects of their element types. diff --git a/clang/lib/CodeGen/CodeGenTBAA.h b/clang/lib/CodeGen/CodeGenTBAA.h index ba74a39a4d25e..ab3b05df7713b 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.h +++ b/clang/lib/CodeGen/CodeGenTBAA.h @@ -24,6 +24,7 @@ namespace clang { class ASTContext; class CodeGenOptions; class LangOptions; + class MangleContext; class QualType; class Type; @@ -119,6 +120,7 @@ class CodeGenTBAA { llvm::Module &Module; const CodeGenOptions &CodeGenOpts; const LangOptions &Features; + std::unique_ptr MangleCtx; // MDHelper - Helper for creating metadata. llvm::MDBuilder MDHelper; diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 577a0f571e16e..0a63c50d44f4b 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1098,12 +1098,6 @@ struct CounterCoverageMappingBuilder return ExitCount; } - /// Determine whether the given condition can be constant folded. - bool ConditionFoldsToBool(const Expr *Cond) { - Expr::EvalResult Result; - return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext())); - } - /// Create a Branch Region around an instrumentable condition for coverage /// and add it to the function's SourceRegions. A branch region tracks a /// "True" counter and a "False" counter for boolean expressions that @@ -1133,13 +1127,15 @@ struct CounterCoverageMappingBuilder // Alternatively, we can prevent any optimization done via // constant-folding by ensuring that ConstantFoldsToSimpleInteger() in // CodeGenFunction.c always returns false, but that is very heavy-handed. - if (ConditionFoldsToBool(C)) - popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C), - Counter::getZero(), BranchParams)); - else - // Otherwise, create a region with the True counter and False counter. - popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, - BranchParams)); + Expr::EvalResult Result; + if (C->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext())) { + if (Result.Val.getInt().getBoolValue()) + FalseCnt = Counter::getZero(); + else + TrueCnt = Counter::getZero(); + } + popRegions( + pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, BranchParams)); } } @@ -1153,12 +1149,12 @@ struct CounterCoverageMappingBuilder /// Create a Branch Region around a SwitchCase for code coverage /// and add it to the function's SourceRegions. - void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt, - Counter FalseCnt) { + void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt) { // Push region onto RegionStack but immediately pop it (which adds it to // the function's SourceRegions) because it doesn't apply to any other // source other than the SwitchCase. - popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt)); + popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), + Counter::getZero())); } /// Check whether a region with bounds \c StartLoc and \c EndLoc @@ -1870,24 +1866,16 @@ struct CounterCoverageMappingBuilder const SwitchCase *Case = S->getSwitchCaseList(); for (; Case; Case = Case->getNextSwitchCase()) { HasDefaultCase = HasDefaultCase || isa(Case); - CaseCountSum = - addCounters(CaseCountSum, getRegionCounter(Case), /*Simplify=*/false); - createSwitchCaseRegion( - Case, getRegionCounter(Case), - subtractCounters(ParentCount, getRegionCounter(Case))); + auto CaseCount = getRegionCounter(Case); + CaseCountSum = addCounters(CaseCountSum, CaseCount, /*Simplify=*/false); + createSwitchCaseRegion(Case, CaseCount); } - // Simplify is skipped while building the counters above: it can get really - // slow on top of switches with thousands of cases. Instead, trigger - // simplification by adding zero to the last counter. - CaseCountSum = addCounters(CaseCountSum, Counter::getZero()); - // If no explicit default case exists, create a branch region to represent // the hidden branch, which will be added later by the CodeGen. This region // will be associated with the switch statement's condition. if (!HasDefaultCase) { - Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum); - Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue); - createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse); + Counter DefaultCount = subtractCounters(ParentCount, CaseCountSum); + createBranchRegion(S->getCond(), Counter::getZero(), DefaultCount); } } diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp index 355253e4b3b07..e69a5562137cc 100644 --- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp +++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp @@ -260,6 +260,15 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, else Features.push_back("-frecipe"); } + + // Select lam-bh feature determined by -m[no-]lam-bh. + if (const Arg *A = + Args.getLastArg(options::OPT_mlam_bh, options::OPT_mno_lam_bh)) { + if (A->getOption().matches(options::OPT_mlam_bh)) + Features.push_back("+lam-bh"); + else + Features.push_back("-lam-bh"); + } } std::string loongarch::postProcessTargetCPUString(const std::string &CPU, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 91605a67a37fc..1c3c8c816594e 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1623,10 +1623,14 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, } bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) { - if (Args.hasArg(options::OPT_shared)) - return false; - - if (TC.getXRayArgs().needsXRayRt()) { + if (Args.hasArg(options::OPT_shared)) { + if (TC.getXRayArgs().needsXRayDSORt()) { + CmdArgs.push_back("--whole-archive"); + CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray-dso")); + CmdArgs.push_back("--no-whole-archive"); + return true; + } + } else if (TC.getXRayArgs().needsXRayRt()) { CmdArgs.push_back("--whole-archive"); CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray")); for (const auto &Mode : TC.getXRayArgs().modeList()) diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index b368c47375673..412b379304b1e 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -634,8 +634,8 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, std::vector Features; getNVPTXTargetFeatures(C.getDriver(), getToolChain().getTriple(), Args, Features); - for (StringRef Feature : Features) - CmdArgs.append({"--feature", Args.MakeArgString(Feature)}); + CmdArgs.push_back( + Args.MakeArgString("--plugin-opt=-mattr=" + llvm::join(Features, ","))); // Add paths for the default clang library path. SmallString<256> DefaultLibPath = diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index 7c028f18c0308..02b1e034c2878 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -229,6 +229,8 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, const Driver &D = TC.getDriver(); ArgStringList CmdArgs; + const bool Relocatable = Args.hasArg(options::OPT_r); + // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" @@ -246,6 +248,28 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasFlag(options::OPT_pie, options::OPT_no_pie, PIE)) CmdArgs.push_back("-pie"); + if (!Relocatable) { + // Lazy binding of PLTs is not supported on PlayStation. They are placed in + // the RelRo segment. + CmdArgs.push_back("-z"); + CmdArgs.push_back("now"); + + // Don't export linker-generated __start/stop... section bookends. + CmdArgs.push_back("-z"); + CmdArgs.push_back("start-stop-visibility=hidden"); + + // Patch relocated regions of DWARF whose targets are eliminated at link + // time with specific tombstones, such that they're recognisable by the + // PlayStation debugger. + CmdArgs.push_back("-z"); + CmdArgs.push_back("dead-reloc-in-nonalloc=.debug_*=0xffffffffffffffff"); + CmdArgs.push_back("-z"); + CmdArgs.push_back( + "dead-reloc-in-nonalloc=.debug_ranges=0xfffffffffffffffe"); + CmdArgs.push_back("-z"); + CmdArgs.push_back("dead-reloc-in-nonalloc=.debug_loc=0xfffffffffffffffe"); + } + if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-static"); if (Args.hasArg(options::OPT_rdynamic)) diff --git a/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp index 8c5134e250135..d0bb5d4887c18 100644 --- a/clang/lib/Driver/XRayArgs.cpp +++ b/clang/lib/Driver/XRayArgs.cpp @@ -63,6 +63,23 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) { << XRayInstrument->getSpelling() << Triple.str(); } + if (Args.hasFlag(options::OPT_fxray_shared, options::OPT_fno_xray_shared, + false)) { + XRayShared = true; + + // DSO instrumentation is currently limited to x86_64 + if (Triple.getArch() != llvm::Triple::x86_64) { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << "-fxray-shared" << Triple.str(); + } + + unsigned PICLvl = std::get<1>(tools::ParsePICArgs(TC, Args)); + if (!PICLvl) { + D.Diag(diag::err_opt_not_valid_without_opt) << "-fxray-shared" + << "-fPIC"; + } + } + // Both XRay and -fpatchable-function-entry use // TargetOpcode::PATCHABLE_FUNCTION_ENTER. if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) @@ -177,6 +194,10 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args, Args.addOptOutFlag(CmdArgs, options::OPT_fxray_function_index, options::OPT_fno_xray_function_index); + if (XRayShared) + Args.addOptInFlag(CmdArgs, options::OPT_fxray_shared, + options::OPT_fno_xray_shared); + if (const Arg *A = Args.getLastArg(options::OPT_fxray_instruction_threshold_EQ)) { int Value; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index c612960ff37ac..f85fe440f50a6 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1968,6 +1968,7 @@ FormatStyle getClangFormatStyle() { Style.IntegerLiteralSeparator.DecimalMinDigits = 5; Style.LineEnding = FormatStyle::LE_LF; Style.RemoveBracesLLVM = true; + Style.RemoveEmptyLinesInUnwrappedLines = true; Style.RemoveParentheses = FormatStyle::RPS_ReturnStatement; Style.RemoveSemicolon = true; return Style; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index bda9850670ab0..1d425ad23f596 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1568,6 +1568,11 @@ void UnwrappedLineParser::parseStructuralElement( } parseCaseLabel(); return; + case tok::kw_goto: + nextToken(); + if (FormatTok->is(tok::kw_case)) + nextToken(); + break; case tok::kw_try: case tok::kw___try: if (Style.isJavaScript() && Line->MustBeDeclaration) { @@ -2148,7 +2153,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { if (!Style.isCSharp()) return false; // See if it's a property accessor. - if (FormatTok->Previous->isNot(tok::identifier)) + if (!FormatTok->Previous || FormatTok->Previous->isNot(tok::identifier)) return false; // See if we are inside a property accessor. @@ -3484,10 +3489,10 @@ bool UnwrappedLineParser::parseRequires() { case tok::r_paren: case tok::kw_noexcept: case tok::kw_const: + case tok::amp: // This is a requires clause. parseRequiresClause(RequiresToken); return true; - case tok::amp: case tok::ampamp: { // This can be either: // if (... && requires (T t) ...) diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h index 786678b9d8a75..b6bcf32c09c08 100644 --- a/clang/lib/Headers/opencl-c-base.h +++ b/clang/lib/Headers/opencl-c-base.h @@ -46,6 +46,7 @@ #define __opencl_c_ext_fp32_global_atomic_min_max 1 #define __opencl_c_ext_fp32_local_atomic_min_max 1 #define __opencl_c_ext_image_raw10_raw12 1 +#define __opencl_c_ext_image_unorm_int_2_101010 1 #define cl_khr_kernel_clock 1 #define __opencl_c_kernel_clock_scope_device 1 #define __opencl_c_kernel_clock_scope_work_group 1 @@ -486,6 +487,9 @@ typedef enum memory_order #define CLK_UNSIGNED_INT_RAW10_EXT 0x10E3 #define CLK_UNSIGNED_INT_RAW12_EXT 0x10E4 #endif // __opencl_c_ext_image_raw10_raw12 +#ifdef __opencl_c_ext_image_unorm_int_2_101010 +#define CLK_UNORM_INT_2_101010_EXT 0x10E5 +#endif // __opencl_c_ext_image_unorm_int_2_101010 // Channel order, numbering must be aligned with cl_channel_order in cl.h // diff --git a/clang/lib/Lex/HeaderMap.cpp b/clang/lib/Lex/HeaderMap.cpp index 00bf880726ee3..b04f67a4b2ed3 100644 --- a/clang/lib/Lex/HeaderMap.cpp +++ b/clang/lib/Lex/HeaderMap.cpp @@ -54,7 +54,10 @@ std::unique_ptr HeaderMap::Create(FileEntryRef FE, FileManager &FM) { unsigned FileSize = FE.getSize(); if (FileSize <= sizeof(HMapHeader)) return nullptr; - auto FileBuffer = FM.getBufferForFile(FE); + auto FileBuffer = + FM.getBufferForFile(FE, /*IsVolatile=*/false, + /*RequiresNullTerminator=*/true, + /*MaybeList=*/std::nullopt, /*IsText=*/false); if (!FileBuffer || !*FileBuffer) return nullptr; bool NeedsByteSwap; diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 2aada51c71c50..fd6bc17ae9cda 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -362,12 +362,7 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, MMapLangOpts.LineComment = true; } -ModuleMap::~ModuleMap() { - for (auto &M : Modules) - delete M.getValue(); - for (auto *M : ShadowModules) - delete M; -} +ModuleMap::~ModuleMap() = default; void ModuleMap::setTarget(const TargetInfo &Target) { assert((!this->Target || this->Target == &Target) && @@ -831,6 +826,22 @@ Module *ModuleMap::findModule(StringRef Name) const { return nullptr; } +Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) { + if (Module *SubM = Parent->findSubmodule(Name)) + return SubM; + if (!Parent->InferSubmodules) + return nullptr; + Module *Result = new (ModulesAlloc.Allocate()) + Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false, + Parent->InferExplicitSubmodules, 0); + Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules; + Result->InferSubmodules = Parent->InferSubmodules; + Result->InferExportWildcard = Parent->InferExportWildcard; + if (Result->InferExportWildcard) + Result->Exports.push_back(Module::ExportDecl(nullptr, true)); + return Result; +} + Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) const { for(; Context; Context = Context->Parent) { @@ -857,8 +868,9 @@ std::pair ModuleMap::findOrCreateModule(StringRef Name, return std::make_pair(Sub, false); // Create a new module with this name. - Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, - IsExplicit, NumCreatedModules++); + Module *Result = new (ModulesAlloc.Allocate()) + Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, + IsFramework, IsExplicit, NumCreatedModules++); if (!Parent) { if (LangOpts.CurrentModule == Name) SourceModule = Result; @@ -870,8 +882,9 @@ std::pair ModuleMap::findOrCreateModule(StringRef Name, Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc, Module *Parent) { - auto *Result = new Module("", Loc, Parent, /*IsFramework*/ false, - /*IsExplicit*/ true, NumCreatedModules++); + auto *Result = new (ModulesAlloc.Allocate()) Module( + ModuleConstructorTag{}, "", Loc, Parent, /*IsFramework=*/false, + /*IsExplicit=*/true, NumCreatedModules++); Result->Kind = Module::ExplicitGlobalModuleFragment; // If the created module isn't owned by a parent, send it to PendingSubmodules // to wait for its parent. @@ -888,9 +901,9 @@ ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc, // Note: Here the `IsExplicit` parameter refers to the semantics in clang // modules. All the non-explicit submodules in clang modules will be exported // too. Here we simplify the implementation by using the concept. - auto *Result = - new Module("", Loc, Parent, /*IsFramework=*/false, - /*IsExplicit=*/false, NumCreatedModules++); + auto *Result = new (ModulesAlloc.Allocate()) + Module(ModuleConstructorTag{}, "", Loc, Parent, + /*IsFramework=*/false, /*IsExplicit=*/false, NumCreatedModules++); Result->Kind = Module::ImplicitGlobalModuleFragment; return Result; } @@ -898,25 +911,23 @@ ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc, Module * ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent, SourceLocation Loc) { - auto *Result = - new Module("", Loc, Parent, /*IsFramework*/ false, - /*IsExplicit*/ true, NumCreatedModules++); + auto *Result = new (ModulesAlloc.Allocate()) Module( + ModuleConstructorTag{}, "", Loc, Parent, /*IsFramework=*/false, + /*IsExplicit=*/true, NumCreatedModules++); Result->Kind = Module::PrivateModuleFragment; return Result; } Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name, Module::ModuleKind Kind) { - auto *Result = - new Module(Name, Loc, nullptr, /*IsFramework*/ false, - /*IsExplicit*/ false, NumCreatedModules++); + auto *Result = new (ModulesAlloc.Allocate()) + Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false, + /*IsExplicit=*/false, NumCreatedModules++); Result->Kind = Kind; // Reparent any current global module fragment as a submodule of this module. - for (auto &Submodule : PendingSubmodules) { + for (auto &Submodule : PendingSubmodules) Submodule->setParent(Result); - Submodule.release(); // now owned by parent - } PendingSubmodules.clear(); return Result; } @@ -968,8 +979,9 @@ Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name, assert(LangOpts.CurrentModule == Name && "module name mismatch"); assert(!Modules[Name] && "redefining existing module"); - auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false, - /*IsExplicit*/ false, NumCreatedModules++); + auto *Result = new (ModulesAlloc.Allocate()) + Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false, + /*IsExplicit=*/false, NumCreatedModules++); Result->Kind = Module::ModuleHeaderUnit; Modules[Name] = SourceModule = Result; addHeader(Result, H, NormalHeader); @@ -1082,9 +1094,9 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir, if (!UmbrellaHeader) return nullptr; - Module *Result = new Module(ModuleName, SourceLocation(), Parent, - /*IsFramework=*/true, /*IsExplicit=*/false, - NumCreatedModules++); + Module *Result = new (ModulesAlloc.Allocate()) + Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent, + /*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++); InferredModuleAllowedBy[Result] = ModuleMapFID; Result->IsInferred = true; if (!Parent) { @@ -1173,9 +1185,9 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, Module *ShadowingModule) { // Create a new module with this name. - Module *Result = - new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, - /*IsExplicit=*/false, NumCreatedModules++); + Module *Result = new (ModulesAlloc.Allocate()) + Module(ModuleConstructorTag{}, Name, SourceLocation(), /*Parent=*/nullptr, + IsFramework, /*IsExplicit=*/false, NumCreatedModules++); Result->ShadowingModule = ShadowingModule; Result->markUnavailable(/*Unimportable*/true); ModuleScopeIDs[Result] = CurrentModuleScopeID; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 4e77df9ec444c..8e7d80aa8911c 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1080,8 +1080,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, FileManager &FM = this->getFileManager(); if (llvm::sys::path::is_absolute(Filename)) { // lookup path or immediately fail - llvm::Expected ShouldBeEntry = - FM.getFileRef(Filename, OpenFile); + llvm::Expected ShouldBeEntry = FM.getFileRef( + Filename, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); return llvm::expectedToOptional(std::move(ShouldBeEntry)); } @@ -1107,8 +1107,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, StringRef FullFileDir = LookupFromFile->tryGetRealPathName(); if (!FullFileDir.empty()) { SeparateComponents(LookupPath, FullFileDir, Filename, true); - llvm::Expected ShouldBeEntry = - FM.getFileRef(LookupPath, OpenFile); + llvm::Expected ShouldBeEntry = FM.getFileRef( + LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); if (ShouldBeEntry) return llvm::expectedToOptional(std::move(ShouldBeEntry)); llvm::consumeError(ShouldBeEntry.takeError()); @@ -1123,8 +1123,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, StringRef WorkingDir = WorkingDirEntry.getName(); if (!WorkingDir.empty()) { SeparateComponents(LookupPath, WorkingDir, Filename, false); - llvm::Expected ShouldBeEntry = - FM.getFileRef(LookupPath, OpenFile); + llvm::Expected ShouldBeEntry = FM.getFileRef( + LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); if (ShouldBeEntry) return llvm::expectedToOptional(std::move(ShouldBeEntry)); llvm::consumeError(ShouldBeEntry.takeError()); @@ -1135,8 +1135,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, for (const auto &Entry : PPOpts->EmbedEntries) { LookupPath.clear(); SeparateComponents(LookupPath, Entry, Filename, false); - llvm::Expected ShouldBeEntry = - FM.getFileRef(LookupPath, OpenFile); + llvm::Expected ShouldBeEntry = FM.getFileRef( + LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); if (ShouldBeEntry) return llvm::expectedToOptional(std::move(ShouldBeEntry)); llvm::consumeError(ShouldBeEntry.takeError()); diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index 10f0ab7180e62..6ec63b91df4be 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -1752,6 +1752,7 @@ struct PragmaModuleBeginHandler : public PragmaHandler { // Find the module we're entering. We require that a module map for it // be loaded or implicitly loadable. auto &HSI = PP.getHeaderSearchInfo(); + auto &MM = HSI.getModuleMap(); Module *M = HSI.lookupModule(Current, ModuleName.front().second); if (!M) { PP.Diag(ModuleName.front().second, @@ -1759,7 +1760,7 @@ struct PragmaModuleBeginHandler : public PragmaHandler { return; } for (unsigned I = 1; I != ModuleName.size(); ++I) { - auto *NewM = M->findOrInferSubmodule(ModuleName[I].first->getName()); + auto *NewM = MM.findOrInferSubmodule(M, ModuleName[I].first->getName()); if (!NewM) { PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule) << M->getFullModuleName() << ModuleName[I].first; diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 6f0f5a0311bc1..b28c2a9db91b0 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3148,11 +3148,13 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration( // we did nothing here, but this allows us to issue a more // helpful diagnostic. if (Tok.is(tok::kw_concept)) { - Diag(Tok.getLocation(), - DS.isFriendSpecified() || NextToken().is(tok::kw_friend) - ? diag::err_friend_concept - : diag:: - err_concept_decls_may_only_appear_in_global_namespace_scope); + Diag( + Tok.getLocation(), + DS.isFriendSpecified() || NextToken().is(tok::kw_friend) + ? llvm::to_underlying(diag::err_friend_concept) + : llvm::to_underlying( + diag:: + err_concept_decls_may_only_appear_in_global_namespace_scope)); SkipUntil(tok::semi, tok::r_brace, StopBeforeMatch); return nullptr; } diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp index 8caeae5fcf9f8..aa0a2e223e708 100644 --- a/clang/lib/Sema/CheckExprLifetime.cpp +++ b/clang/lib/Sema/CheckExprLifetime.cpp @@ -1206,11 +1206,13 @@ static void checkExprLifetimeImpl(Sema &SemaRef, assert(shouldLifetimeExtendThroughPath(Path) == PathLifetimeKind::NoExtend && "No lifetime extension for assignments"); - SemaRef.Diag(DiagLoc, - IsGslPtrValueFromGslTempOwner - ? diag::warn_dangling_lifetime_pointer_assignment - : diag::warn_dangling_pointer_assignment) - << AEntity->LHS << DiagRange; + if (IsGslPtrValueFromGslTempOwner) + SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment) + << AEntity->LHS << DiagRange; + else + SemaRef.Diag(DiagLoc, diag::warn_dangling_pointer_assignment) + << AEntity->LHS->getType()->isPointerType() << AEntity->LHS + << DiagRange; return false; } case LK_MemInitializer: { @@ -1412,8 +1414,14 @@ static void checkExprLifetimeImpl(Sema &SemaRef, }; llvm::SmallVector Path; - if (LK == LK_Assignment && shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity)) - Path.push_back({IndirectLocalPathEntry::GslPointerAssignment, Init}); + if (LK == LK_Assignment && + shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity)) { + Path.push_back( + {isAssignmentOperatorLifetimeBound(AEntity->AssignmentOperator) + ? IndirectLocalPathEntry::LifetimeBoundCall + : IndirectLocalPathEntry::GslPointerAssignment, + Init}); + } if (Init->isGLValue()) visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding, diff --git a/clang/lib/Sema/SemaAMDGPU.cpp b/clang/lib/Sema/SemaAMDGPU.cpp index d11bc9eec3301..f59654c14f08f 100644 --- a/clang/lib/Sema/SemaAMDGPU.cpp +++ b/clang/lib/Sema/SemaAMDGPU.cpp @@ -63,6 +63,50 @@ bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, OrderIndex = 0; ScopeIndex = 1; break; + case AMDGPU::BI__builtin_amdgcn_mov_dpp: { + if (SemaRef.checkArgCountRange(TheCall, 5, 5)) + return true; + Expr *ValArg = TheCall->getArg(0); + QualType Ty = ValArg->getType(); + // TODO: Vectors can also be supported. + if (!Ty->isArithmeticType() || Ty->isAnyComplexType()) { + SemaRef.Diag(ValArg->getBeginLoc(), + diag::err_typecheck_cond_expect_int_float) + << Ty << ValArg->getSourceRange(); + return true; + } + return false; + } + case AMDGPU::BI__builtin_amdgcn_update_dpp: { + if (SemaRef.checkArgCountRange(TheCall, 6, 6)) + return true; + Expr *Args[2]; + QualType ArgTys[2]; + for (unsigned I = 0; I != 2; ++I) { + Args[I] = TheCall->getArg(I); + ArgTys[I] = Args[I]->getType(); + // TODO: Vectors can also be supported. + if (!ArgTys[I]->isArithmeticType() || ArgTys[I]->isAnyComplexType()) { + SemaRef.Diag(Args[I]->getBeginLoc(), + diag::err_typecheck_cond_expect_int_float) + << ArgTys[I] << Args[I]->getSourceRange(); + return true; + } + } + if (getASTContext().hasSameUnqualifiedType(ArgTys[0], ArgTys[1])) + return false; + if (((ArgTys[0]->isUnsignedIntegerType() && + ArgTys[1]->isSignedIntegerType()) || + (ArgTys[0]->isSignedIntegerType() && + ArgTys[1]->isUnsignedIntegerType())) && + getASTContext().getTypeSize(ArgTys[0]) == + getASTContext().getTypeSize(ArgTys[1])) + return false; + SemaRef.Diag(Args[1]->getBeginLoc(), + diag::err_typecheck_call_different_arg_types) + << ArgTys[0] << ArgTys[1]; + return true; + } default: return false; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 6759aae37afac..601c6f2eef1d9 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3072,7 +3072,7 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, if (HasPriority) DuplicateAttr = true; HasPriority = true; - int Digit; + unsigned Digit; if (AttrStr.getAsInteger(0, Digit)) return Diag(LiteralLoc, diag::warn_unsupported_target_attribute) << Unsupported << None << AttrStr << TargetVersion; @@ -3226,7 +3226,7 @@ bool Sema::checkTargetClonesAttrString( HasDefault = true; } else if (AttrStr.consume_front("priority=")) { IsPriority = true; - int Digit; + unsigned Digit; if (AttrStr.getAsInteger(0, Digit)) return Diag(CurLoc, diag::warn_unsupported_target_attribute) << Unsupported << None << Str << TargetClones; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 40f24ea0ab2ea..50c1b24fce6da 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5713,7 +5713,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_hlsl_is_intangible)) return false; - return Self.HLSL().IsIntangibleType(T); + return T->isHLSLIntangibleType(); } } @@ -9444,11 +9444,11 @@ Sema::BuildExprRequirement( ExprResult Constraint = SubstExpr(IDC, MLTAL); if (Constraint.isInvalid()) { return new (Context) concepts::ExprRequirement( - concepts::createSubstDiagAt(*this, IDC->getExprLoc(), - [&](llvm::raw_ostream &OS) { - IDC->printPretty(OS, /*Helper=*/nullptr, - getPrintingPolicy()); - }), + createSubstDiagAt(IDC->getExprLoc(), + [&](llvm::raw_ostream &OS) { + IDC->printPretty(OS, /*Helper=*/nullptr, + getPrintingPolicy()); + }), IsSimple, NoexceptLoc, ReturnTypeRequirement); } SubstitutedConstraintExpr = diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 1d18a6308e2a5..1f6c5b8d4561b 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -102,8 +102,10 @@ static ResourceClass getResourceClass(RegisterType RT) { return ResourceClass::Sampler; case RegisterType::C: case RegisterType::I: - llvm_unreachable("unexpected RegisterType value"); + // Deliberately falling through to the unreachable below. + break; } + llvm_unreachable("unexpected RegisterType value"); } DeclBindingInfo *ResourceBindings::addDeclBindingInfo(const VarDecl *VD, @@ -2102,32 +2104,6 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return false; } -bool SemaHLSL::IsIntangibleType(clang::QualType QT) { - if (QT.isNull()) - return false; - - const Type *Ty = QT->getUnqualifiedDesugaredType(); - - // check if it's a builtin type first (simple check, no need to cache it) - if (Ty->isBuiltinType()) - return Ty->isHLSLIntangibleType(); - - // unwrap arrays - while (isa(Ty)) - Ty = Ty->getArrayElementTypeNoTypeQual(); - - const RecordType *RT = - dyn_cast(Ty->getUnqualifiedDesugaredType()); - if (!RT) - return false; - - CXXRecordDecl *RD = RT->getAsCXXRecordDecl(); - assert(RD != nullptr && - "all HLSL struct and classes should be CXXRecordDecl"); - assert(RD->isCompleteDefinition() && "expecting complete type"); - return RD->isHLSLIntangible(); -} - static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl &List) { llvm::SmallVector WorkList; @@ -2323,7 +2299,7 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) { } // find all resources on decl - if (IsIntangibleType(VD->getType())) + if (VD->getType()->isHLSLIntangibleType()) collectResourcesOnVarDecl(VD); // process explicit bindings @@ -2334,7 +2310,7 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) { // Walks though the global variable declaration, collects all resource binding // requirements and adds them to Bindings void SemaHLSL::collectResourcesOnVarDecl(VarDecl *VD) { - assert(VD->hasGlobalStorage() && IsIntangibleType(VD->getType()) && + assert(VD->hasGlobalStorage() && VD->getType()->isHLSLIntangibleType() && "expected global variable that contains HLSL resource"); // Cbuffers and Tbuffers are HLSLBufferDecl types diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 0232745b3c19e..fa81fc42c0ee5 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -18335,7 +18335,8 @@ static bool checkOMPArraySectionConstantForReduction( return false; // This is an array subscript which has implicit length 1! - ArraySizes.push_back(llvm::APSInt::get(1)); + llvm::APSInt ConstantOne = llvm::APSInt::get(1); + ArraySizes.push_back(ConstantOne); } else { Expr::EvalResult Result; if (!Length->EvaluateAsInt(Result, Context)) @@ -18354,7 +18355,8 @@ static bool checkOMPArraySectionConstantForReduction( if (!SingleElement) { while (const auto *TempASE = dyn_cast(Base)) { // Has implicit length 1! - ArraySizes.push_back(llvm::APSInt::get(1)); + llvm::APSInt ConstantOne = llvm::APSInt::get(1); + ArraySizes.push_back(ConstantOne); Base = TempASE->getBase()->IgnoreParenImpCasts(); } } diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp index d1ccc2774152b..e63d605349e06 100644 --- a/clang/lib/Sema/SemaRISCV.cpp +++ b/clang/lib/Sema/SemaRISCV.cpp @@ -50,7 +50,7 @@ struct RVVIntrinsicDef { struct RVVOverloadIntrinsicDef { // Indexes of RISCVIntrinsicManagerImpl::IntrinsicList. - SmallVector Indexes; + SmallVector Indexes; }; } // namespace @@ -169,7 +169,7 @@ class RISCVIntrinsicManagerImpl : public sema::RISCVIntrinsicManager { // List of all RVV intrinsic. std::vector IntrinsicList; // Mapping function name to index of IntrinsicList. - StringMap Intrinsics; + StringMap Intrinsics; // Mapping function name to RVVOverloadIntrinsicDef. StringMap OverloadIntrinsics; @@ -399,7 +399,7 @@ void RISCVIntrinsicManagerImpl::InitRVVIntrinsic( Record.HasFRMRoundModeOp); // Put into IntrinsicList. - uint16_t Index = IntrinsicList.size(); + uint32_t Index = IntrinsicList.size(); assert(IntrinsicList.size() == (size_t)Index && "Intrinsics indices overflow."); IntrinsicList.push_back({BuiltinName, Signature}); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 457a9968c32a4..198442dd9821e 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2654,7 +2654,7 @@ QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType( static concepts::Requirement::SubstitutionDiagnostic * createSubstDiag(Sema &S, TemplateDeductionInfo &Info, - concepts::EntityPrinter Printer) { + Sema::EntityPrinter Printer) { SmallString<128> Message; SourceLocation ErrorLoc; if (Info.hasSFINAEDiagnostic()) { @@ -2675,12 +2675,11 @@ createSubstDiag(Sema &S, TemplateDeductionInfo &Info, } concepts::Requirement::SubstitutionDiagnostic * -concepts::createSubstDiagAt(Sema &S, SourceLocation Location, - EntityPrinter Printer) { +Sema::createSubstDiagAt(SourceLocation Location, EntityPrinter Printer) { SmallString<128> Entity; llvm::raw_svector_ostream OS(Entity); Printer(OS); - const ASTContext &C = S.Context; + const ASTContext &C = Context; return new (C) concepts::Requirement::SubstitutionDiagnostic{ /*SubstitutedEntity=*/C.backupStr(Entity), /*DiagLoc=*/Location, /*DiagMessage=*/StringRef()}; diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 19bd454766583..151b328872bd7 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -41,7 +41,7 @@ namespace { unsigned DepthLimit = (unsigned)-1; #ifndef NDEBUG - bool ContainsFunctionParmPackExpr = false; + bool ContainsIntermediatePacks = false; #endif void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) { @@ -114,6 +114,11 @@ namespace { addUnexpanded(TTP); } +#ifndef NDEBUG + ContainsIntermediatePacks |= + (bool)Template.getAsSubstTemplateTemplateParmPack(); +#endif + return inherited::TraverseTemplateName(Template); } @@ -297,13 +302,28 @@ namespace { #ifndef NDEBUG bool TraverseFunctionParmPackExpr(FunctionParmPackExpr *) { - ContainsFunctionParmPackExpr = true; + ContainsIntermediatePacks = true; + return true; + } + + bool TraverseSubstNonTypeTemplateParmPackExpr( + SubstNonTypeTemplateParmPackExpr *) { + ContainsIntermediatePacks = true; + return true; + } + + bool VisitSubstTemplateTypeParmPackType(SubstTemplateTypeParmPackType *) { + ContainsIntermediatePacks = true; return true; } - bool containsFunctionParmPackExpr() const { - return ContainsFunctionParmPackExpr; + bool + VisitSubstTemplateTypeParmPackTypeLoc(SubstTemplateTypeParmPackTypeLoc) { + ContainsIntermediatePacks = true; + return true; } + + bool containsIntermediatePacks() const { return ContainsIntermediatePacks; } #endif }; } @@ -439,21 +459,20 @@ bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, if (!E->containsUnexpandedParameterPack()) return false; - // FunctionParmPackExprs are special: - // - // 1) they're used to model DeclRefExprs to packs that have been expanded but - // had that expansion held off in the process of transformation. - // - // 2) they always have the unexpanded dependencies but don't introduce new - // unexpanded packs. - // - // We might encounter a FunctionParmPackExpr being a full expression, which a - // larger CXXFoldExpr would expand. SmallVector Unexpanded; CollectUnexpandedParameterPacksVisitor Visitor(Unexpanded); Visitor.TraverseStmt(E); - assert((!Unexpanded.empty() || Visitor.containsFunctionParmPackExpr()) && +#ifndef NDEBUG + // The expression might contain a type/subexpression that has been substituted + // but has the expansion held off, e.g. a FunctionParmPackExpr which a larger + // CXXFoldExpr would expand. It's only possible when expanding a lambda as a + // pattern of a fold expression, so don't fire on an empty result in that + // case. + bool LambdaReferencingOuterPacks = + getEnclosingLambdaOrBlock() && Visitor.containsIntermediatePacks(); + assert((!Unexpanded.empty() || LambdaReferencingOuterPacks) && "Unable to find unexpanded parameter packs"); +#endif return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c44fc9c4194ca..6387fe9f1129b 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3738,12 +3738,12 @@ static CallingConv getCCForDeclaratorChunk( } } } else if (S.getLangOpts().CUDA) { - // If we're compiling CUDA/HIP code and targeting SPIR-V we need to make + // If we're compiling CUDA/HIP code and targeting HIPSPV we need to make // sure the kernels will be marked with the right calling convention so that - // they will be visible by the APIs that ingest SPIR-V. + // they will be visible by the APIs that ingest SPIR-V. We do not do this + // when targeting AMDGCNSPIRV, as it does not rely on OpenCL. llvm::Triple Triple = S.Context.getTargetInfo().getTriple(); - if (Triple.getArch() == llvm::Triple::spirv32 || - Triple.getArch() == llvm::Triple::spirv64) { + if (Triple.isSPIRV() && Triple.getVendor() != llvm::Triple::AMD) { for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) { if (AL.getKind() == ParsedAttr::AT_CUDAGlobal) { CC = CC_OpenCLKernel; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c5a6e677ef8de..bd474cc637a48 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -8385,14 +8385,19 @@ TreeTransform::TransformDeclStmt(DeclStmt *S) { if (Transformed != D) DeclChanged = true; - if (LSI && isa(Transformed)) - LSI->ContainsUnexpandedParameterPack |= - getSema() - .getASTContext() - .getTypeDeclType(cast(Transformed)) - .getCanonicalType() - .getTypePtr() - ->containsUnexpandedParameterPack(); + if (LSI) { + if (auto *TD = dyn_cast(Transformed)) + LSI->ContainsUnexpandedParameterPack |= + getSema() + .getASTContext() + .getTypeDeclType(TD) + .getCanonicalType() + ->containsUnexpandedParameterPack(); + + if (auto *VD = dyn_cast(Transformed)) + LSI->ContainsUnexpandedParameterPack |= + VD->getType()->containsUnexpandedParameterPack(); + } Decls.push_back(Transformed); } diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index ab4923de6346f..ec18e84255ca8 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -15,7 +15,10 @@ #include "clang/AST/DeclObjC.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Serialization/ASTDeserializationListener.h" +#include "clang/Serialization/ModuleFile.h" #include "llvm/Support/DJB.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; @@ -503,3 +506,15 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { return false; return isa(D); } + +void serialization::updateModuleTimestamp(StringRef ModuleFilename) { + // Overwrite the timestamp file contents so that file's mtime changes. + std::error_code EC; + llvm::raw_fd_ostream OS(ModuleFile::getTimestampFilename(ModuleFilename), EC, + llvm::sys::fs::OF_TextWithCRLF); + if (EC) + return; + OS << "Timestamp file\n"; + OS.close(); + OS.clear_error(); // Avoid triggering a fatal error. +} diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h index 0230908d3e052..2a765eafe0895 100644 --- a/clang/lib/Serialization/ASTCommon.h +++ b/clang/lib/Serialization/ASTCommon.h @@ -15,6 +15,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclFriend.h" +#include "clang/Basic/LLVM.h" #include "clang/Serialization/ASTBitCodes.h" namespace clang { @@ -100,6 +101,8 @@ inline bool isPartOfPerModuleInitializer(const Decl *D) { return false; } +void updateModuleTimestamp(StringRef ModuleFilename); + } // namespace serialization } // namespace clang diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 1cf6c9352f368..7d9170e7f0b47 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -4416,19 +4416,6 @@ bool ASTReader::isGlobalIndexUnavailable() const { !hasGlobalIndex() && TriedLoadingGlobalIndex; } -static void updateModuleTimestamp(ModuleFile &MF) { - // Overwrite the timestamp file contents so that file's mtime changes. - std::string TimestampFilename = MF.getTimestampFilename(); - std::error_code EC; - llvm::raw_fd_ostream OS(TimestampFilename, EC, - llvm::sys::fs::OF_TextWithCRLF); - if (EC) - return; - OS << "Timestamp file\n"; - OS.close(); - OS.clear_error(); // Avoid triggering a fatal error. -} - /// Given a cursor at the start of an AST file, scan ahead and drop the /// cursor into the start of the given block ID, returning false on success and /// true on failure. @@ -4707,7 +4694,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ModuleKind Type, ImportedModule &M = Loaded[I]; if (M.Mod->Kind == MK_ImplicitModule && M.Mod->InputFilesValidationTimestamp < HSOpts.BuildSessionTimestamp) - updateModuleTimestamp(*M.Mod); + updateModuleTimestamp(M.Mod->FileName); } } @@ -5334,7 +5321,9 @@ std::string ASTReader::getOriginalSourceFile( const PCHContainerReader &PCHContainerRdr, DiagnosticsEngine &Diags) { // Open the AST file. auto Buffer = FileMgr.getBufferForFile(ASTFileName, /*IsVolatile=*/false, - /*RequiresNullTerminator=*/false); + /*RequiresNullTerminator=*/false, + /*MaybeLimit=*/std::nullopt, + /*IsText=*/false); if (!Buffer) { Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << Buffer.getError().message(); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 938d7b525cb95..494890284d2f2 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4905,6 +4905,12 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, StringRef OutputFile, this->BaseDirectory.clear(); WritingAST = false; + + if (WritingModule && SemaRef.PP.getHeaderSearchInfo() + .getHeaderSearchOpts() + .ModulesValidateOncePerBuildSession) + updateModuleTimestamp(OutputFile); + if (ShouldCacheASTInMemory) { // Construct MemoryBuffer and update buffer manager. ModuleCache.addBuiltPCM(OutputFile, diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index e74a16b636802..ba78c9ef5af67 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -170,7 +170,8 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, NewModule->InputFilesValidationTimestamp = 0; if (NewModule->Kind == MK_ImplicitModule) { - std::string TimestampFilename = NewModule->getTimestampFilename(); + std::string TimestampFilename = + ModuleFile::getTimestampFilename(NewModule->FileName); llvm::vfs::Status Status; // A cached stat value would be fine as well. if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status)) diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index a76639bb86b20..f4de3b500499c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -78,7 +78,7 @@ SourceRange StackAddrEscapeChecker::genName(raw_ostream &os, const MemRegion *R, const CompoundLiteralExpr *CL = CR->getLiteralExpr(); os << "stack memory associated with a compound literal " "declared on line " - << SM.getExpansionLineNumber(CL->getBeginLoc()) << " returned to caller"; + << SM.getExpansionLineNumber(CL->getBeginLoc()); range = CL->getSourceRange(); } else if (const auto *AR = dyn_cast(R)) { const Expr *ARE = AR->getExpr(); diff --git a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp index 0cb96097415ea..01b3be700b9fa 100644 --- a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp +++ b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp @@ -335,10 +335,9 @@ HeaderIncludes::HeaderIncludes(StringRef FileName, StringRef Code, // \p Offset: the start of the line following this include directive. void HeaderIncludes::addExistingInclude(Include IncludeToAdd, unsigned NextLineOffset) { - auto Iter = - ExistingIncludes.try_emplace(trimInclude(IncludeToAdd.Name)).first; - Iter->second.push_back(std::move(IncludeToAdd)); - auto &CurInclude = Iter->second.back(); + auto &Incs = ExistingIncludes[trimInclude(IncludeToAdd.Name)]; + Incs.push_back(std::move(IncludeToAdd)); + auto &CurInclude = Incs.back(); // The header name with quotes or angle brackets. // Only record the offset of current #include if we can insert after it. if (CurInclude.R.getOffset() <= MaxInsertOffset) { diff --git a/clang/test/.gitattributes b/clang/test/.gitattributes deleted file mode 100644 index 160fc6cf56175..0000000000000 --- a/clang/test/.gitattributes +++ /dev/null @@ -1,4 +0,0 @@ -FixIt/fixit-newline-style.c text eol=crlf -Frontend/system-header-line-directive-ms-lineendings.c text eol=crlf -Frontend/rewrite-includes-mixed-eol-crlf.* text eol=crlf -clang/test/Frontend/rewrite-includes-mixed-eol-lf.h text eolf=lf diff --git a/clang/test/AST/ByteCode/complex.cpp b/clang/test/AST/ByteCode/complex.cpp index dc93c786dac7a..ee11c6214b70c 100644 --- a/clang/test/AST/ByteCode/complex.cpp +++ b/clang/test/AST/ByteCode/complex.cpp @@ -407,8 +407,7 @@ namespace ComplexConstexpr { // ref-note {{cannot access real component of null}} \ // expected-note {{read of dereferenced null pointer}} constexpr float pi = __imag *p; // both-error {{constant expr}} \ - // ref-note {{cannot access imaginary component of null}} \ - // expected-note {{cannot perform pointer arithmetic on null pointer}} + // ref-note {{cannot access imaginary component of null}} constexpr const _Complex double *q = &test3 + 1; constexpr double qr = __real *q; // ref-error {{constant expr}} \ // ref-note {{cannot access real component of pointer past the end}} diff --git a/clang/test/AST/ByteCode/cxx98.cpp b/clang/test/AST/ByteCode/cxx98.cpp index 471a58f8e0551..20f98d33c31c4 100644 --- a/clang/test/AST/ByteCode/cxx98.cpp +++ b/clang/test/AST/ByteCode/cxx98.cpp @@ -54,3 +54,8 @@ _Static_assert(a == 0, ""); // both-error {{static assertion expression is not a struct SelfReference { SelfReference &r; }; extern SelfReference self_reference_1; SelfReference self_reference_2 = {self_reference_1}; + +struct PR65784s{ + int *ptr; +} const PR65784[] = {(int *)""}; +PR65784s PR65784f() { return *PR65784; } diff --git a/clang/test/AST/ByteCode/openmp.cpp b/clang/test/AST/ByteCode/openmp.cpp new file mode 100644 index 0000000000000..e05fbe086625c --- /dev/null +++ b/clang/test/AST/ByteCode/openmp.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both -fopenmp %s +// RUN: %clang_cc1 -verify=ref,both -fopenmp %s + +int test1() { + int i; + int &j = i; // both-note {{declared here}} + float *f; + // both-note@+2 {{initializer of 'j' is not a constant expression}} + // both-error@+1 {{integral constant expression}} + #pragma omp for simd aligned(f:j) + for (int i = 0; i < 10; ++i); +} + diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp index 215f26bd5da8e..2eeaafc04c516 100644 --- a/clang/test/AST/ByteCode/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -1661,3 +1661,18 @@ namespace NullptrUpcast { constexpr A &ra = *nb; // both-error {{constant expression}} \ // both-note {{cannot access base class of null pointer}} } + +namespace NonConst { + template + struct S { + static constexpr int Size = I; + constexpr int getSize() const { return I; } + explicit S(int a) {} + }; + + void func() { + int a,b ; + const S<10> s{a}; + static_assert(s.getSize() == 10, ""); + } +} diff --git a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl index 9c1630f6f570a..030fcfc31691d 100644 --- a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl @@ -1,64 +1,64 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY %s | FileCheck -check-prefix=EMPTY %s -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s - - -// This test tests two different AST generations. The "EMPTY" test mode verifies -// the AST generated by forward declaration of the HLSL types which happens on -// initializing the HLSL external AST with an AST Context. - -// The non-empty mode has a use that requires the StructuredBuffer type be complete, -// which results in the AST being populated by the external AST source. That -// case covers the full implementation of the template declaration and the -// instantiated specialization. - -// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit StructuredBuffer -// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type -// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class StructuredBuffer -// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final - -// There should be no more occurrances of StructuredBuffer -// EMPTY-NOT: StructuredBuffer - -#ifndef EMPTY - -StructuredBuffer Buffer; - -#endif - -// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit StructuredBuffer -// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type -// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class StructuredBuffer definition - -// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] -// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] -// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer - -// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' -// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' -// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <> -// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <> -// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}} -// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <> 'const StructuredBuffer' lvalue implicit this -// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <> Implicit always_inline - -// CHECK-NEXT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &(unsigned int)' -// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' -// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <> -// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <> -// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}} -// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <> 'StructuredBuffer' lvalue implicit this -// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <> Implicit always_inline - -// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <> class StructuredBuffer definition - -// CHECK: TemplateArgument type 'float' -// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' -// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] -// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]] -// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY %s | FileCheck -check-prefix=EMPTY %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s + + +// This test tests two different AST generations. The "EMPTY" test mode verifies +// the AST generated by forward declaration of the HLSL types which happens on +// initializing the HLSL external AST with an AST Context. + +// The non-empty mode has a use that requires the StructuredBuffer type be complete, +// which results in the AST being populated by the external AST source. That +// case covers the full implementation of the template declaration and the +// instantiated specialization. + +// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit StructuredBuffer +// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class StructuredBuffer +// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final + +// There should be no more occurrances of StructuredBuffer +// EMPTY-NOT: StructuredBuffer + +#ifndef EMPTY + +StructuredBuffer Buffer; + +#endif + +// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <> implicit StructuredBuffer +// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <> class depth 0 index 0 element_type +// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class StructuredBuffer definition + +// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] +// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer + +// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' +// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' +// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <> +// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <> +// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}} +// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <> 'const StructuredBuffer' lvalue implicit this +// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <> Implicit always_inline + +// CHECK-NEXT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &(unsigned int)' +// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' +// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <> +// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <> +// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}} +// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <> 'StructuredBuffer' lvalue implicit this +// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <> Implicit always_inline + +// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <> class StructuredBuffer definition + +// CHECK: TemplateArgument type 'float' +// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' +// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]] +// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer diff --git a/clang/test/Analysis/stack-addr-ps.c b/clang/test/Analysis/stack-addr-ps.c index 7d7294455f1db..1adcb8c48d035 100644 --- a/clang/test/Analysis/stack-addr-ps.c +++ b/clang/test/Analysis/stack-addr-ps.c @@ -20,17 +20,21 @@ int* f3(int x, int *y) { void* compound_literal(int x, int y) { if (x) - return &(unsigned short){((unsigned short)0x22EF)}; // expected-warning{{Address of stack memory}} expected-warning{{address of stack memory}} + return &(unsigned short){((unsigned short)0x22EF)}; + // expected-warning-re@-1{{Address of stack memory associated with a compound literal declared on line {{[0-9]+}} returned to caller [core.StackAddressEscape]}} + // expected-warning@-2{{address of stack memory}} int* array[] = {}; struct s { int z; double y; int w; }; if (y) - return &((struct s){ 2, 0.4, 5 * 8 }); // expected-warning{{Address of stack memory}} expected-warning{{address of stack memory}} - + return &((struct s){ 2, 0.4, 5 * 8 }); + // expected-warning-re@-1{{Address of stack memory associated with a compound literal declared on line {{[0-9]+}} returned to caller [core.StackAddressEscape]}} + // expected-warning@-2{{address of stack memory}} void* p = &((struct s){ 42, 0.4, x ? 42 : 0 }); - return p; // expected-warning{{Address of stack memory}} + return p; + // expected-warning-re@-1{{Address of stack memory associated with a compound literal declared on line {{[0-9]+}} returned to caller [core.StackAddressEscape]}} } void* alloca_test(void) { diff --git a/clang/test/C/C2y/n3262.c b/clang/test/C/C2y/n3262.c index 864ab351bdbc2..3ff2062d88dde 100644 --- a/clang/test/C/C2y/n3262.c +++ b/clang/test/C/C2y/n3262.c @@ -1,20 +1,20 @@ -// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s -// expected-no-diagnostics - -/* WG14 N3262: Yes - * Usability of a byte-wise copy of va_list - * - * NB: Clang explicitly documents this as being undefined behavior. A - * diagnostic is produced for some targets but not for others for assignment or - * initialization, but no diagnostic is possible to produce for use with memcpy - * in the general case, nor with a manual bytewise copy via a for loop. - * - * Therefore, nothing is tested in this file; it serves as a reminder that we - * validated our documentation against the paper. See - * clang/docs/LanguageExtensions.rst for more details. - * - * FIXME: it would be nice to add ubsan support for recognizing when an invalid - * copy is made and diagnosing on copy (or on use of the copied va_list). - */ - -int main() {} +// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s +// expected-no-diagnostics + +/* WG14 N3262: Yes + * Usability of a byte-wise copy of va_list + * + * NB: Clang explicitly documents this as being undefined behavior. A + * diagnostic is produced for some targets but not for others for assignment or + * initialization, but no diagnostic is possible to produce for use with memcpy + * in the general case, nor with a manual bytewise copy via a for loop. + * + * Therefore, nothing is tested in this file; it serves as a reminder that we + * validated our documentation against the paper. See + * clang/docs/LanguageExtensions.rst for more details. + * + * FIXME: it would be nice to add ubsan support for recognizing when an invalid + * copy is made and diagnosing on copy (or on use of the copied va_list). + */ + +int main() {} diff --git a/clang/test/C/C2y/n3274.c b/clang/test/C/C2y/n3274.c index 6bf8d72d0f331..ccdb89f4069de 100644 --- a/clang/test/C/C2y/n3274.c +++ b/clang/test/C/C2y/n3274.c @@ -1,18 +1,18 @@ -// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s -// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s - -/* WG14 N3274: Yes - * Remove imaginary types - */ - -// Clang has never supported _Imaginary. -#ifdef __STDC_IEC_559_COMPLEX__ -#error "When did this happen?" -#endif - -_Imaginary float i; // expected-error {{imaginary types are not supported}} - -// _Imaginary is a keyword in older language modes, but doesn't need to be one -// in C2y or later. However, to improve diagnostic behavior, we retain it as a -// keyword in all language modes -- it is not available as an identifier. -static_assert(!__is_identifier(_Imaginary)); +// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s + +/* WG14 N3274: Yes + * Remove imaginary types + */ + +// Clang has never supported _Imaginary. +#ifdef __STDC_IEC_559_COMPLEX__ +#error "When did this happen?" +#endif + +_Imaginary float i; // expected-error {{imaginary types are not supported}} + +// _Imaginary is a keyword in older language modes, but doesn't need to be one +// in C2y or later. However, to improve diagnostic behavior, we retain it as a +// keyword in all language modes -- it is not available as an identifier. +static_assert(!__is_identifier(_Imaginary)); diff --git a/clang/test/CXX/drs/cwg9xx.cpp b/clang/test/CXX/drs/cwg9xx.cpp index 2700b0f5662a2..d4f54bcdad6ea 100644 --- a/clang/test/CXX/drs/cwg9xx.cpp +++ b/clang/test/CXX/drs/cwg9xx.cpp @@ -93,6 +93,56 @@ struct B : A { } // namespace example2 } // namespace cwg952 +namespace cwg960 { // cwg960: 3.0 +struct a {}; +class A { +#if __cplusplus >= 201103L + // Check lvalue ref vs rvalue ref vs pointer. + virtual a& rvalue_ref(); + virtual a&& lvalue_ref(); + virtual a& rvalue_vs_lvalue_ref(); // #cwg960-A-rvalue_vs_lvalue_ref + virtual a&& lvalue_vs_rvalue_ref(); // #cwg960-A-lvalue_vs_rvalue_ref + virtual a& rvalue_ref_vs_pointer(); // #cwg960-A-rvalue_ref_vs_pointer + virtual a* pointer_vs_rvalue_ref(); // #cwg960-A-pointer_vs_rvalue_ref + virtual a&& lvalue_ref_vs_pointer(); // #cwg960-A-lvalue_ref_vs_pointer + virtual a* pointer_vs_lvalue_ref(); // #cwg960-A-pointer_vs_lvalue_ref +#endif +}; + +class B : A { +#if __cplusplus >= 201103L + // Check lvalue ref vs rvalue ref vs pointer. + a& rvalue_ref() override; + a&& lvalue_ref() override; + + a&& rvalue_vs_lvalue_ref() override; + // since-cxx11-error@-1 {{virtual function 'rvalue_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a &')}} + // since-cxx11-note@#cwg960-A-rvalue_vs_lvalue_ref {{overridden virtual function is here}} + + a& lvalue_vs_rvalue_ref() override; + // since-cxx11-error@-1 {{virtual function 'lvalue_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a &&')}} + // since-cxx11-note@#cwg960-A-lvalue_vs_rvalue_ref {{overridden virtual function is here}} + + a* rvalue_ref_vs_pointer() override; + // since-cxx11-error@-1 {{virtual function 'rvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &')}} + // since-cxx11-note@#cwg960-A-rvalue_ref_vs_pointer {{overridden virtual function is here}} + + a& pointer_vs_rvalue_ref() override; + // since-cxx11-error@-1 {{virtual function 'pointer_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a *')}} + // since-cxx11-note@#cwg960-A-pointer_vs_rvalue_ref {{overridden virtual function is here}} + + a* lvalue_ref_vs_pointer() override; + // since-cxx11-error@-1 {{virtual function 'lvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &&')}} + // since-cxx11-note@#cwg960-A-lvalue_ref_vs_pointer {{overridden virtual function is here}} + + a&& pointer_vs_lvalue_ref() override; + // since-cxx11-error@-1 {{virtual function 'pointer_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a *')}} + // since-cxx11-note@#cwg960-A-pointer_vs_lvalue_ref {{overridden virtual function is here}} +#endif +}; + +} // namespace cwg960 + namespace cwg974 { // cwg974: yes #if __cplusplus >= 201103L void test() { diff --git a/clang/test/CodeGen/aarch64-cpu-supports-target.c b/clang/test/CodeGen/aarch64-cpu-supports-target.c index 28187bcf74533..5186cab92a921 100644 --- a/clang/test/CodeGen/aarch64-cpu-supports-target.c +++ b/clang/test/CodeGen/aarch64-cpu-supports-target.c @@ -17,7 +17,7 @@ int check_all_feature() { return 7; else if (__builtin_cpu_supports("sve2-bitperm+sve2-sha3+sve2-sm4")) return 8; - else if (__builtin_cpu_supports("sme+memtag+memtag2+memtag3+sb")) + else if (__builtin_cpu_supports("sme+memtag+memtag3+sb")) return 9; else if (__builtin_cpu_supports("predres+ssbs+ssbs2+bti+ls64+ls64_v")) return 10; diff --git a/clang/test/CodeGen/aarch64-cpu-supports.c b/clang/test/CodeGen/aarch64-cpu-supports.c index 823bf369df6fc..dc96c929fdf4c 100644 --- a/clang/test/CodeGen/aarch64-cpu-supports.c +++ b/clang/test/CodeGen/aarch64-cpu-supports.c @@ -1,9 +1,10 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --version 2 +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals --global-value-regex ".*" // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s +//. // CHECK: @__aarch64_cpu_features = external dso_local global { i64 } -// CHECK-LABEL: define dso_local i32 @main -// CHECK-SAME: () #[[ATTR0:[0-9]+]] { +//. +// CHECK-LABEL: @main( // CHECK-NEXT: entry: // CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 @@ -17,8 +18,8 @@ // CHECK-NEXT: br label [[RETURN:%.*]] // CHECK: if.end: // CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 9070970929152 -// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 9070970929152 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 17867063951360 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 17867063951360 // CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] // CHECK-NEXT: br i1 [[TMP7]], label [[IF_THEN1:%.*]], label [[IF_END2:%.*]] // CHECK: if.then1: @@ -60,3 +61,7 @@ int main(void) { return 0; } +//. +// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. diff --git a/clang/test/CodeGen/aarch64-fmv-dependencies.c b/clang/test/CodeGen/aarch64-fmv-dependencies.c index f4229a5d23397..9aca1b7a9daf6 100644 --- a/clang/test/CodeGen/aarch64-fmv-dependencies.c +++ b/clang/test/CodeGen/aarch64-fmv-dependencies.c @@ -72,13 +72,10 @@ __attribute__((target_version("ls64"))) int fmv(void) { return 0; } // CHECK: define dso_local i32 @fmv._Mlse() #[[lse:[0-9]+]] { __attribute__((target_version("lse"))) int fmv(void) { return 0; } -// CHECK: define dso_local i32 @fmv._Mmemtag() #[[ATTR0:[0-9]+]] { +// CHECK: define dso_local i32 @fmv._Mmemtag() #[[memtag:[0-9]+]] { __attribute__((target_version("memtag"))) int fmv(void) { return 0; } -// CHECK: define dso_local i32 @fmv._Mmemtag2() #[[memtag2:[0-9]+]] { -__attribute__((target_version("memtag2"))) int fmv(void) { return 0; } - -// CHECK: define dso_local i32 @fmv._Mmemtag3() #[[memtag2:[0-9]+]] { +// CHECK: define dso_local i32 @fmv._Mmemtag3() #[[memtag:[0-9]+]] { __attribute__((target_version("memtag3"))) int fmv(void) { return 0; } // CHECK: define dso_local i32 @fmv._Mmops() #[[mops:[0-9]+]] { @@ -200,7 +197,7 @@ int caller() { // CHECK: attributes #[[jscvt]] = { {{.*}} "target-features"="+fp-armv8,+jsconv,+neon,+outline-atomics,+v8a" // CHECK: attributes #[[ls64]] = { {{.*}} "target-features"="+fp-armv8,+ls64,+neon,+outline-atomics,+v8a" // CHECK: attributes #[[lse]] = { {{.*}} "target-features"="+fp-armv8,+lse,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[memtag2]] = { {{.*}} "target-features"="+fp-armv8,+mte,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[memtag]] = { {{.*}} "target-features"="+fp-armv8,+mte,+neon,+outline-atomics,+v8a" // CHECK: attributes #[[mops]] = { {{.*}} "target-features"="+fp-armv8,+mops,+neon,+outline-atomics,+v8a" // CHECK: attributes #[[pmull]] = { {{.*}} "target-features"="+aes,+fp-armv8,+neon,+outline-atomics,+v8a" // CHECK: attributes #[[predres]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+predres,+v8a" diff --git a/clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c b/clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c index f6c9e13190774..74b543b67bfba 100644 --- a/clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c +++ b/clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c @@ -34,8 +34,8 @@ typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N))); // CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to // CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <8 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[AND]], i64 0) -// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[AND]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-NEXT: ret [[TMP2]] // fixed_bool_t and_bool(fixed_bool_t a, fixed_bool_t b) { @@ -47,8 +47,8 @@ fixed_bool_t and_bool(fixed_bool_t a, fixed_bool_t b) { // CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <64 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[AND]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[AND]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int8_t and_i8(fixed_int8_t a, fixed_int8_t b) { return a & b; @@ -59,8 +59,8 @@ fixed_int8_t and_i8(fixed_int8_t a, fixed_int8_t b) { // CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <32 x i16> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[AND]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[AND]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int16_t and_i16(fixed_int16_t a, fixed_int16_t b) { return a & b; @@ -71,8 +71,8 @@ fixed_int16_t and_i16(fixed_int16_t a, fixed_int16_t b) { // CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <16 x i32> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[AND]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[AND]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int32_t and_i32(fixed_int32_t a, fixed_int32_t b) { return a & b; @@ -83,8 +83,8 @@ fixed_int32_t and_i32(fixed_int32_t a, fixed_int32_t b) { // CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <8 x i64> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[AND]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[AND]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int64_t and_i64(fixed_int64_t a, fixed_int64_t b) { return a & b; @@ -95,8 +95,8 @@ fixed_int64_t and_i64(fixed_int64_t a, fixed_int64_t b) { // CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <64 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[AND]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[AND]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint8_t and_u8(fixed_uint8_t a, fixed_uint8_t b) { return a & b; @@ -107,8 +107,8 @@ fixed_uint8_t and_u8(fixed_uint8_t a, fixed_uint8_t b) { // CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <32 x i16> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[AND]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[AND]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint16_t and_u16(fixed_uint16_t a, fixed_uint16_t b) { return a & b; @@ -119,8 +119,8 @@ fixed_uint16_t and_u16(fixed_uint16_t a, fixed_uint16_t b) { // CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <16 x i32> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[AND]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[AND]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint32_t and_u32(fixed_uint32_t a, fixed_uint32_t b) { return a & b; @@ -131,8 +131,8 @@ fixed_uint32_t and_u32(fixed_uint32_t a, fixed_uint32_t b) { // CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[AND:%.*]] = and <8 x i64> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[AND]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[AND]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint64_t and_u64(fixed_uint64_t a, fixed_uint64_t b) { return a & b; @@ -147,8 +147,8 @@ fixed_uint64_t and_u64(fixed_uint64_t a, fixed_uint64_t b) { // CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to // CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <8 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[OR]], i64 0) -// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[OR]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-NEXT: ret [[TMP2]] // fixed_bool_t or_bool(fixed_bool_t a, fixed_bool_t b) { @@ -160,8 +160,8 @@ fixed_bool_t or_bool(fixed_bool_t a, fixed_bool_t b) { // CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <64 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[OR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[OR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int8_t or_i8(fixed_int8_t a, fixed_int8_t b) { return a | b; @@ -172,8 +172,8 @@ fixed_int8_t or_i8(fixed_int8_t a, fixed_int8_t b) { // CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <32 x i16> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[OR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[OR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int16_t or_i16(fixed_int16_t a, fixed_int16_t b) { return a | b; @@ -184,8 +184,8 @@ fixed_int16_t or_i16(fixed_int16_t a, fixed_int16_t b) { // CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <16 x i32> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[OR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[OR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int32_t or_i32(fixed_int32_t a, fixed_int32_t b) { return a | b; @@ -196,8 +196,8 @@ fixed_int32_t or_i32(fixed_int32_t a, fixed_int32_t b) { // CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <8 x i64> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[OR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[OR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int64_t or_i64(fixed_int64_t a, fixed_int64_t b) { return a | b; @@ -208,8 +208,8 @@ fixed_int64_t or_i64(fixed_int64_t a, fixed_int64_t b) { // CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <64 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[OR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[OR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint8_t or_u8(fixed_uint8_t a, fixed_uint8_t b) { return a | b; @@ -220,8 +220,8 @@ fixed_uint8_t or_u8(fixed_uint8_t a, fixed_uint8_t b) { // CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <32 x i16> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[OR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[OR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint16_t or_u16(fixed_uint16_t a, fixed_uint16_t b) { return a | b; @@ -232,8 +232,8 @@ fixed_uint16_t or_u16(fixed_uint16_t a, fixed_uint16_t b) { // CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <16 x i32> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[OR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[OR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint32_t or_u32(fixed_uint32_t a, fixed_uint32_t b) { return a | b; @@ -244,8 +244,8 @@ fixed_uint32_t or_u32(fixed_uint32_t a, fixed_uint32_t b) { // CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[OR:%.*]] = or <8 x i64> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[OR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[OR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint64_t or_u64(fixed_uint64_t a, fixed_uint64_t b) { return a | b; @@ -260,8 +260,8 @@ fixed_uint64_t or_u64(fixed_uint64_t a, fixed_uint64_t b) { // CHECK-NEXT: [[B_COERCE:%.*]] = bitcast [[TMP1:%.*]] to // CHECK-NEXT: [[B:%.*]] = call <8 x i8> @llvm.vector.extract.v8i8.nxv2i8( [[B_COERCE]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <8 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[XOR]], i64 0) -// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[XOR]], i64 0) +// CHECK-NEXT: [[TMP2:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-NEXT: ret [[TMP2]] // fixed_bool_t xor_bool(fixed_bool_t a, fixed_bool_t b) { @@ -273,8 +273,8 @@ fixed_bool_t xor_bool(fixed_bool_t a, fixed_bool_t b) { // CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <64 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[XOR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int8_t xor_i8(fixed_int8_t a, fixed_int8_t b) { return a ^ b; @@ -285,8 +285,8 @@ fixed_int8_t xor_i8(fixed_int8_t a, fixed_int8_t b) { // CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <32 x i16> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[XOR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int16_t xor_i16(fixed_int16_t a, fixed_int16_t b) { return a ^ b; @@ -297,8 +297,8 @@ fixed_int16_t xor_i16(fixed_int16_t a, fixed_int16_t b) { // CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <16 x i32> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[XOR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int32_t xor_i32(fixed_int32_t a, fixed_int32_t b) { return a ^ b; @@ -309,8 +309,8 @@ fixed_int32_t xor_i32(fixed_int32_t a, fixed_int32_t b) { // CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <8 x i64> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[XOR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int64_t xor_i64(fixed_int64_t a, fixed_int64_t b) { return a ^ b; @@ -321,8 +321,8 @@ fixed_int64_t xor_i64(fixed_int64_t a, fixed_int64_t b) { // CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <64 x i8> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[XOR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint8_t xor_u8(fixed_uint8_t a, fixed_uint8_t b) { return a ^ b; @@ -333,8 +333,8 @@ fixed_uint8_t xor_u8(fixed_uint8_t a, fixed_uint8_t b) { // CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <32 x i16> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[XOR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint16_t xor_u16(fixed_uint16_t a, fixed_uint16_t b) { return a ^ b; @@ -345,8 +345,8 @@ fixed_uint16_t xor_u16(fixed_uint16_t a, fixed_uint16_t b) { // CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <16 x i32> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[XOR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint32_t xor_u32(fixed_uint32_t a, fixed_uint32_t b) { return a ^ b; @@ -357,8 +357,8 @@ fixed_uint32_t xor_u32(fixed_uint32_t a, fixed_uint32_t b) { // CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) // CHECK-NEXT: [[B:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[B_COERCE:%.*]], i64 0) // CHECK-NEXT: [[XOR:%.*]] = xor <8 x i64> [[A]], [[B]] -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[XOR]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[XOR]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint64_t xor_u64(fixed_uint64_t a, fixed_uint64_t b) { return a ^ b; @@ -370,9 +370,9 @@ fixed_uint64_t xor_u64(fixed_uint64_t a, fixed_uint64_t b) { // CHECK-NEXT: entry: // CHECK-NEXT: [[A_COERCE:%.*]] = bitcast [[TMP0:%.*]] to // CHECK-NEXT: [[A:%.*]] = call <8 x i8> @llvm.vector.extract.v8i8.nxv2i8( [[A_COERCE]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <8 x i8> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[NEG]], i64 0) -// CHECK-NEXT: [[TMP1:%.*]] = bitcast [[CASTSCALABLESVE]] to +// CHECK-NEXT: [[NOT:%.*]] = xor <8 x i8> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i8.v8i8( undef, <8 x i8> [[NOT]], i64 0) +// CHECK-NEXT: [[TMP1:%.*]] = bitcast [[CAST_SCALABLE]] to // CHECK-NEXT: ret [[TMP1]] // fixed_bool_t neg_bool(fixed_bool_t a) { @@ -382,9 +382,9 @@ fixed_bool_t neg_bool(fixed_bool_t a) { // CHECK-LABEL: @neg_i8( // CHECK-NEXT: entry: // CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <64 x i8> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[NEG]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[NOT:%.*]] = xor <64 x i8> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[NOT]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int8_t neg_i8(fixed_int8_t a) { return ~a; @@ -393,9 +393,9 @@ fixed_int8_t neg_i8(fixed_int8_t a) { // CHECK-LABEL: @neg_i16( // CHECK-NEXT: entry: // CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <32 x i16> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[NEG]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[NOT:%.*]] = xor <32 x i16> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[NOT]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int16_t neg_i16(fixed_int16_t a) { return ~a; @@ -404,9 +404,9 @@ fixed_int16_t neg_i16(fixed_int16_t a) { // CHECK-LABEL: @neg_i32( // CHECK-NEXT: entry: // CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <16 x i32> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[NEG]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[NOT:%.*]] = xor <16 x i32> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[NOT]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int32_t neg_i32(fixed_int32_t a) { return ~a; @@ -415,9 +415,9 @@ fixed_int32_t neg_i32(fixed_int32_t a) { // CHECK-LABEL: @neg_i64( // CHECK-NEXT: entry: // CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <8 x i64> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[NEG]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[NOT:%.*]] = xor <8 x i64> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[NOT]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_int64_t neg_i64(fixed_int64_t a) { return ~a; @@ -426,9 +426,9 @@ fixed_int64_t neg_i64(fixed_int64_t a) { // CHECK-LABEL: @neg_u8( // CHECK-NEXT: entry: // CHECK-NEXT: [[A:%.*]] = call <64 x i8> @llvm.vector.extract.v64i8.nxv16i8( [[A_COERCE:%.*]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <64 x i8> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[NEG]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[NOT:%.*]] = xor <64 x i8> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv16i8.v64i8( undef, <64 x i8> [[NOT]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint8_t neg_u8(fixed_uint8_t a) { return ~a; @@ -437,9 +437,9 @@ fixed_uint8_t neg_u8(fixed_uint8_t a) { // CHECK-LABEL: @neg_u16( // CHECK-NEXT: entry: // CHECK-NEXT: [[A:%.*]] = call <32 x i16> @llvm.vector.extract.v32i16.nxv8i16( [[A_COERCE:%.*]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <32 x i16> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[NEG]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[NOT:%.*]] = xor <32 x i16> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv8i16.v32i16( undef, <32 x i16> [[NOT]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint16_t neg_u16(fixed_uint16_t a) { return ~a; @@ -448,9 +448,9 @@ fixed_uint16_t neg_u16(fixed_uint16_t a) { // CHECK-LABEL: @neg_u32( // CHECK-NEXT: entry: // CHECK-NEXT: [[A:%.*]] = call <16 x i32> @llvm.vector.extract.v16i32.nxv4i32( [[A_COERCE:%.*]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <16 x i32> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[NEG]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[NOT:%.*]] = xor <16 x i32> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv4i32.v16i32( undef, <16 x i32> [[NOT]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint32_t neg_u32(fixed_uint32_t a) { return ~a; @@ -459,9 +459,9 @@ fixed_uint32_t neg_u32(fixed_uint32_t a) { // CHECK-LABEL: @neg_u64( // CHECK-NEXT: entry: // CHECK-NEXT: [[A:%.*]] = call <8 x i64> @llvm.vector.extract.v8i64.nxv2i64( [[A_COERCE:%.*]], i64 0) -// CHECK-NEXT: [[NEG:%.*]] = xor <8 x i64> [[A]], -// CHECK-NEXT: [[CASTSCALABLESVE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[NEG]], i64 0) -// CHECK-NEXT: ret [[CASTSCALABLESVE]] +// CHECK-NEXT: [[NOT:%.*]] = xor <8 x i64> [[A]], +// CHECK-NEXT: [[CAST_SCALABLE:%.*]] = call @llvm.vector.insert.nxv2i64.v8i64( undef, <8 x i64> [[NOT]], i64 0) +// CHECK-NEXT: ret [[CAST_SCALABLE]] // fixed_uint64_t neg_u64(fixed_uint64_t a) { return ~a; diff --git a/clang/test/CodeGen/arm-bf16-convert-intrinsics.c b/clang/test/CodeGen/arm-bf16-convert-intrinsics.c index 0f2c5b2546fa3..9477ebdb8285a 100644 --- a/clang/test/CodeGen/arm-bf16-convert-intrinsics.c +++ b/clang/test/CodeGen/arm-bf16-convert-intrinsics.c @@ -24,51 +24,51 @@ // CHECK-A64-LABEL: @test_vcvt_f32_bf16( // CHECK-A64-NEXT: entry: -// CHECK-A64-NEXT: [[__REINT_150_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A64-NEXT: [[__REINT1_150_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-A64-NEXT: store <4 x bfloat> [[A:%.*]], ptr [[__REINT_150_I]], align 8 -// CHECK-A64-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_150_I]], align 8 -// CHECK-A64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to <8 x i8> -// CHECK-A64-NEXT: [[TMP3:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32> -// CHECK-A64-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP3]], -// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_150_I]], align 16 -// CHECK-A64-NEXT: [[TMP5:%.*]] = load <4 x float>, ptr [[__REINT1_150_I]], align 16 -// CHECK-A64-NEXT: ret <4 x float> [[TMP5]] +// CHECK-A64-NEXT: [[__REINT_836_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A64-NEXT: [[__REINT1_836_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-A64-NEXT: store <4 x bfloat> [[A:%.*]], ptr [[__REINT_836_I]], align 8 +// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I]], align 8 +// CHECK-A64-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> +// CHECK-A64-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A64-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP2]], +// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_836_I]], align 16 +// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I]], align 16 +// CHECK-A64-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-HARDFP-LABEL: @test_vcvt_f32_bf16( // CHECK-A32-HARDFP-NEXT: entry: -// CHECK-A32-HARDFP-NEXT: [[__REINT_150_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-HARDFP-NEXT: [[__REINT1_150_I:%.*]] = alloca <4 x i32>, align 8 -// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[A:%.*]], ptr [[__REINT_150_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_150_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to <8 x i8> -// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32> -// CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP3]], -// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_150_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP5:%.*]] = load <4 x float>, ptr [[__REINT1_150_I]], align 8 -// CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP5]] +// CHECK-A32-HARDFP-NEXT: [[__REINT_836_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT1_836_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[A:%.*]], ptr [[__REINT_836_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> +// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP2]], +// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_836_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I]], align 8 +// CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-SOFTFP-LABEL: @test_vcvt_f32_bf16( // CHECK-A32-SOFTFP-NEXT: entry: -// CHECK-A32-SOFTFP-NEXT: [[__P0_150_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT_150_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT1_150_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_836_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT_836_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT1_836_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-SOFTFP-NEXT: [[A:%.*]] = alloca <4 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE:%.*]] = alloca <4 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[A_COERCE:%.*]], ptr [[A]], align 8 // CHECK-A32-SOFTFP-NEXT: [[A1:%.*]] = load <4 x bfloat>, ptr [[A]], align 8 // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[A1]], ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP2]], ptr [[__P0_150_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_1501_I:%.*]] = load <4 x bfloat>, ptr [[__P0_150_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_1501_I]], ptr [[__REINT_150_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i16>, ptr [[__REINT_150_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = sext <4 x i16> [[TMP5]] to <4 x i32> -// CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP7]], -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_150_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP9:%.*]] = load <4 x float>, ptr [[__REINT1_150_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP9]] +// CHECK-A32-SOFTFP-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[COERCE]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP0]], ptr [[__P0_836_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_8361_I:%.*]] = load <4 x bfloat>, ptr [[__P0_836_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8361_I]], ptr [[__REINT_836_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_836_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to <8 x i8> +// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32> +// CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP3]], +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_836_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <4 x float>, ptr [[__REINT1_836_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP4]] // float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) { return vcvt_f32_bf16(a); @@ -76,39 +76,39 @@ float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) { // CHECK-A64-LABEL: @test_vcvtq_low_f32_bf16( // CHECK-A64-NEXT: entry: -// CHECK-A64-NEXT: [[__REINT_150_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A64-NEXT: [[__REINT1_150_I_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-A64-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A64-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 16 // CHECK-A64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[A:%.*]], <8 x bfloat> [[A]], <4 x i32> -// CHECK-A64-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_150_I_I]], align 8 -// CHECK-A64-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_150_I_I]], align 8 -// CHECK-A64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to <8 x i8> -// CHECK-A64-NEXT: [[TMP3:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32> -// CHECK-A64-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP3]], -// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_150_I_I]], align 16 -// CHECK-A64-NEXT: [[TMP5:%.*]] = load <4 x float>, ptr [[__REINT1_150_I_I]], align 16 -// CHECK-A64-NEXT: ret <4 x float> [[TMP5]] +// CHECK-A64-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_836_I_I]], align 8 +// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A64-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> +// CHECK-A64-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A64-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP2]], +// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 16 +// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 16 +// CHECK-A64-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-HARDFP-LABEL: @test_vcvtq_low_f32_bf16( // CHECK-A32-HARDFP-NEXT: entry: -// CHECK-A32-HARDFP-NEXT: [[__REINT_150_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-HARDFP-NEXT: [[__REINT1_150_I_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-HARDFP-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[A:%.*]], <8 x bfloat> [[A]], <4 x i32> -// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_150_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_150_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to <8 x i8> -// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32> -// CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP3]], -// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_150_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP5:%.*]] = load <4 x float>, ptr [[__REINT1_150_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP5]] +// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> +// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP2]], +// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-SOFTFP-LABEL: @test_vcvtq_low_f32_bf16( // CHECK-A32-SOFTFP-NEXT: entry: // CHECK-A32-SOFTFP-NEXT: [[RETVAL_I:%.*]] = alloca <4 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[__P0_I2:%.*]] = alloca <8 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_150_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT_150_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT1_150_I_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-SOFTFP-NEXT: [[__P0_I:%.*]] = alloca <8 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE_I:%.*]] = alloca <8 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE2_I:%.*]] = alloca <4 x bfloat>, align 8 @@ -118,30 +118,30 @@ float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) { // CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[A_COERCE:%.*]], ptr [[A]], align 8 // CHECK-A32-SOFTFP-NEXT: [[A1:%.*]] = load <8 x bfloat>, ptr [[A]], align 8 // CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[A1]], ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP2]], ptr [[__P0_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr [[COERCE]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP0]], ptr [[__P0_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P01_I:%.*]] = load <8 x bfloat>, ptr [[__P0_I]], align 8 // CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[__P01_I]], ptr [[COERCE_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i32>, ptr [[COERCE_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP5]], ptr [[__P0_I2]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[COERCE_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP1]], ptr [[__P0_I2]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P01_I5:%.*]] = load <8 x bfloat>, ptr [[__P0_I2]], align 8 // CHECK-A32-SOFTFP-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[__P01_I5]], <8 x bfloat> [[__P01_I5]], <4 x i32> // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <2 x i32>, ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP8]], ptr [[COERCE2_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP10:%.*]] = load <4 x bfloat>, ptr [[COERCE2_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP10]], ptr [[COERCE3_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP12:%.*]] = load <2 x i32>, ptr [[COERCE3_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP12]], ptr [[__P0_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_1501_I_I:%.*]] = load <4 x bfloat>, ptr [[__P0_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_1501_I_I]], ptr [[__REINT_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP15:%.*]] = load <4 x i16>, ptr [[__REINT_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP16:%.*]] = bitcast <4 x i16> [[TMP15]] to <8 x i8> -// CHECK-A32-SOFTFP-NEXT: [[TMP17:%.*]] = sext <4 x i16> [[TMP15]] to <4 x i32> -// CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP17]], -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP19:%.*]] = load <4 x float>, ptr [[__REINT1_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP19]] +// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[RETVAL_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP2]], ptr [[COERCE2_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <4 x bfloat>, ptr [[COERCE2_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP3]], ptr [[COERCE3_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <2 x i32>, ptr [[COERCE3_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP4]], ptr [[__P0_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_8361_I_I:%.*]] = load <4 x bfloat>, ptr [[__P0_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8361_I_I]], ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = sext <4 x i16> [[TMP5]] to <4 x i32> +// CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP7]], +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP8]] // float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) { return vcvtq_low_f32_bf16(a); @@ -149,39 +149,39 @@ float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) { // CHECK-A64-LABEL: @test_vcvtq_high_f32_bf16( // CHECK-A64-NEXT: entry: -// CHECK-A64-NEXT: [[__REINT_150_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A64-NEXT: [[__REINT1_150_I_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-A64-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A64-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 16 // CHECK-A64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[A:%.*]], <8 x bfloat> [[A]], <4 x i32> -// CHECK-A64-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_150_I_I]], align 8 -// CHECK-A64-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_150_I_I]], align 8 -// CHECK-A64-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to <8 x i8> -// CHECK-A64-NEXT: [[TMP3:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32> -// CHECK-A64-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP3]], -// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_150_I_I]], align 16 -// CHECK-A64-NEXT: [[TMP5:%.*]] = load <4 x float>, ptr [[__REINT1_150_I_I]], align 16 -// CHECK-A64-NEXT: ret <4 x float> [[TMP5]] +// CHECK-A64-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_836_I_I]], align 8 +// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A64-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> +// CHECK-A64-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A64-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP2]], +// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 16 +// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 16 +// CHECK-A64-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-HARDFP-LABEL: @test_vcvtq_high_f32_bf16( // CHECK-A32-HARDFP-NEXT: entry: -// CHECK-A32-HARDFP-NEXT: [[__REINT_150_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-HARDFP-NEXT: [[__REINT1_150_I_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-HARDFP-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[A:%.*]], <8 x bfloat> [[A]], <4 x i32> -// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_150_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_150_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to <8 x i8> -// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32> -// CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP3]], -// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_150_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP5:%.*]] = load <4 x float>, ptr [[__REINT1_150_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP5]] +// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> +// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP2]], +// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-SOFTFP-LABEL: @test_vcvtq_high_f32_bf16( // CHECK-A32-SOFTFP-NEXT: entry: // CHECK-A32-SOFTFP-NEXT: [[RETVAL_I:%.*]] = alloca <4 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[__P0_I2:%.*]] = alloca <8 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_150_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT_150_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT1_150_I_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-SOFTFP-NEXT: [[__P0_I:%.*]] = alloca <8 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE_I:%.*]] = alloca <8 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE2_I:%.*]] = alloca <4 x bfloat>, align 8 @@ -191,30 +191,30 @@ float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) { // CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[A_COERCE:%.*]], ptr [[A]], align 8 // CHECK-A32-SOFTFP-NEXT: [[A1:%.*]] = load <8 x bfloat>, ptr [[A]], align 8 // CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[A1]], ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP2]], ptr [[__P0_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr [[COERCE]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP0]], ptr [[__P0_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P01_I:%.*]] = load <8 x bfloat>, ptr [[__P0_I]], align 8 // CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[__P01_I]], ptr [[COERCE_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i32>, ptr [[COERCE_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP5]], ptr [[__P0_I2]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[COERCE_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP1]], ptr [[__P0_I2]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P01_I5:%.*]] = load <8 x bfloat>, ptr [[__P0_I2]], align 8 // CHECK-A32-SOFTFP-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[__P01_I5]], <8 x bfloat> [[__P01_I5]], <4 x i32> // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <2 x i32>, ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP8]], ptr [[COERCE2_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP10:%.*]] = load <4 x bfloat>, ptr [[COERCE2_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP10]], ptr [[COERCE3_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP12:%.*]] = load <2 x i32>, ptr [[COERCE3_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP12]], ptr [[__P0_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_1501_I_I:%.*]] = load <4 x bfloat>, ptr [[__P0_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_1501_I_I]], ptr [[__REINT_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP15:%.*]] = load <4 x i16>, ptr [[__REINT_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP16:%.*]] = bitcast <4 x i16> [[TMP15]] to <8 x i8> -// CHECK-A32-SOFTFP-NEXT: [[TMP17:%.*]] = sext <4 x i16> [[TMP15]] to <4 x i32> -// CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP17]], -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP19:%.*]] = load <4 x float>, ptr [[__REINT1_150_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP19]] +// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[RETVAL_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP2]], ptr [[COERCE2_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <4 x bfloat>, ptr [[COERCE2_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP3]], ptr [[COERCE3_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <2 x i32>, ptr [[COERCE3_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP4]], ptr [[__P0_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_8361_I_I:%.*]] = load <4 x bfloat>, ptr [[__P0_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8361_I_I]], ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> +// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = sext <4 x i16> [[TMP5]] to <4 x i32> +// CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP7]], +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP8]] // float32x4_t test_vcvtq_high_f32_bf16(bfloat16x8_t a) { return vcvtq_high_f32_bf16(a); @@ -223,9 +223,9 @@ float32x4_t test_vcvtq_high_f32_bf16(bfloat16x8_t a) { // CHECK-A64-LABEL: @test_vcvt_bf16_f32( // CHECK-A64-NEXT: entry: // CHECK-A64-NEXT: [[TMP0:%.*]] = bitcast <4 x float> [[A:%.*]] to <16 x i8> -// CHECK-A64-NEXT: [[__A64_VCVTQ_LOW_BF16_V1_I:%.*]] = call <8 x bfloat> @llvm.aarch64.neon.bfcvtn(<4 x float> [[A]]) -// CHECK-A64-NEXT: [[__A64_VCVTQ_LOW_BF16_V2_I:%.*]] = bitcast <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_V1_I]] to <16 x i8> -// CHECK-A64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_V1_I]], <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_V1_I]], <4 x i32> +// CHECK-A64-NEXT: [[__A64_VCVTQ_LOW_BF16_F321_I:%.*]] = call <8 x bfloat> @llvm.aarch64.neon.bfcvtn(<4 x float> [[A]]) +// CHECK-A64-NEXT: [[__A64_VCVTQ_LOW_BF16_F322_I:%.*]] = bitcast <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_F321_I]] to <16 x i8> +// CHECK-A64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_F321_I]], <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_F321_I]], <4 x i32> // CHECK-A64-NEXT: ret <4 x bfloat> [[SHUFFLE_I]] // // CHECK-A32-HARDFP-LABEL: @test_vcvt_bf16_f32( @@ -245,16 +245,16 @@ float32x4_t test_vcvtq_high_f32_bf16(bfloat16x8_t a) { // CHECK-A32-SOFTFP-NEXT: [[VCVTFP2BF1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2bf.v4i16(<4 x float> [[A]]) // CHECK-A32-SOFTFP-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[VCVTFP2BF1_I]] to <4 x bfloat> // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP1]], ptr [[RETVAL_I1]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <2 x i32>, ptr [[RETVAL_I1]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP3]], ptr [[COERCE_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x bfloat>, ptr [[COERCE_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP5]], ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = load <2 x i32>, ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP7]], ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP9:%.*]] = load <4 x bfloat>, ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP9]], ptr [[RETVAL]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP11:%.*]] = load <2 x i32>, ptr [[RETVAL]], align 8 -// CHECK-A32-SOFTFP-NEXT: ret <2 x i32> [[TMP11]] +// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[RETVAL_I1]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP2]], ptr [[COERCE_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <4 x bfloat>, ptr [[COERCE_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP3]], ptr [[RETVAL_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <2 x i32>, ptr [[RETVAL_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP4]], ptr [[COERCE]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x bfloat>, ptr [[COERCE]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP5]], ptr [[RETVAL]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP6:%.*]] = load <2 x i32>, ptr [[RETVAL]], align 8 +// CHECK-A32-SOFTFP-NEXT: ret <2 x i32> [[TMP6]] // bfloat16x4_t test_vcvt_bf16_f32(float32x4_t a) { return vcvt_bf16_f32(a); @@ -263,9 +263,9 @@ bfloat16x4_t test_vcvt_bf16_f32(float32x4_t a) { // CHECK-A64-LABEL: @test_vcvtq_low_bf16_f32( // CHECK-A64-NEXT: entry: // CHECK-A64-NEXT: [[TMP0:%.*]] = bitcast <4 x float> [[A:%.*]] to <16 x i8> -// CHECK-A64-NEXT: [[__A64_VCVTQ_LOW_BF16_V1_I:%.*]] = call <8 x bfloat> @llvm.aarch64.neon.bfcvtn(<4 x float> [[A]]) -// CHECK-A64-NEXT: [[__A64_VCVTQ_LOW_BF16_V2_I:%.*]] = bitcast <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_V1_I]] to <16 x i8> -// CHECK-A64-NEXT: ret <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_V1_I]] +// CHECK-A64-NEXT: [[__A64_VCVTQ_LOW_BF16_F321_I:%.*]] = call <8 x bfloat> @llvm.aarch64.neon.bfcvtn(<4 x float> [[A]]) +// CHECK-A64-NEXT: [[__A64_VCVTQ_LOW_BF16_F322_I:%.*]] = bitcast <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_F321_I]] to <16 x i8> +// CHECK-A64-NEXT: ret <8 x bfloat> [[__A64_VCVTQ_LOW_BF16_F321_I]] // // CHECK-A32-HARDFP-LABEL: @test_vcvtq_low_bf16_f32( // CHECK-A32-HARDFP-NEXT: entry: @@ -291,29 +291,29 @@ bfloat16x4_t test_vcvt_bf16_f32(float32x4_t a) { // CHECK-A32-SOFTFP-NEXT: [[VCVTFP2BF1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2bf.v4i16(<4 x float> [[A]]) // CHECK-A32-SOFTFP-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[VCVTFP2BF1_I]] to <4 x bfloat> // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP1]], ptr [[RETVAL_I1]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <2 x i32>, ptr [[RETVAL_I1]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP3]], ptr [[COERCE_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x bfloat>, ptr [[COERCE_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[RETVAL_I1]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP2]], ptr [[COERCE_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <4 x bfloat>, ptr [[COERCE_I]], align 8 // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> zeroinitializer, ptr [[COERCE1_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = load <2 x i32>, ptr [[COERCE1_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP5]], ptr [[COERCE2_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP9:%.*]] = load <2 x i32>, ptr [[COERCE2_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP7]], ptr [[__P0_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <2 x i32>, ptr [[COERCE1_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP3]], ptr [[COERCE2_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <2 x i32>, ptr [[COERCE2_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP4]], ptr [[__P0_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P01_I:%.*]] = load <4 x bfloat>, ptr [[__P0_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP9]], ptr [[__P1_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP5]], ptr [[__P1_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P12_I:%.*]] = load <4 x bfloat>, ptr [[__P1_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x bfloat> [[__P01_I]], <4 x bfloat> [[__P12_I]], <8 x i32> // CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[SHUFFLE_I]], ptr [[RETVAL_I4]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP13:%.*]] = load <4 x i32>, ptr [[RETVAL_I4]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP13]], ptr [[COERCE4_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP15:%.*]] = load <8 x bfloat>, ptr [[COERCE4_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[TMP15]], ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP17:%.*]] = load <4 x i32>, ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP17]], ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP19:%.*]] = load <8 x bfloat>, ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[TMP19]], ptr [[RETVAL]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP21:%.*]] = load <4 x i32>, ptr [[RETVAL]], align 8 -// CHECK-A32-SOFTFP-NEXT: ret <4 x i32> [[TMP21]] +// CHECK-A32-SOFTFP-NEXT: [[TMP6:%.*]] = load <4 x i32>, ptr [[RETVAL_I4]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP6]], ptr [[COERCE4_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = load <8 x bfloat>, ptr [[COERCE4_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[TMP7]], ptr [[RETVAL_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <4 x i32>, ptr [[RETVAL_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP8]], ptr [[COERCE]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP9:%.*]] = load <8 x bfloat>, ptr [[COERCE]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[TMP9]], ptr [[RETVAL]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP10:%.*]] = load <4 x i32>, ptr [[RETVAL]], align 8 +// CHECK-A32-SOFTFP-NEXT: ret <4 x i32> [[TMP10]] // bfloat16x8_t test_vcvtq_low_bf16_f32(float32x4_t a) { return vcvtq_low_bf16_f32(a); @@ -323,9 +323,9 @@ bfloat16x8_t test_vcvtq_low_bf16_f32(float32x4_t a) { // CHECK-A64-NEXT: entry: // CHECK-A64-NEXT: [[TMP0:%.*]] = bitcast <8 x bfloat> [[INACTIVE:%.*]] to <16 x i8> // CHECK-A64-NEXT: [[TMP1:%.*]] = bitcast <4 x float> [[A:%.*]] to <16 x i8> -// CHECK-A64-NEXT: [[VCVTQ_HIGH_BF16_V2_I:%.*]] = call <8 x bfloat> @llvm.aarch64.neon.bfcvtn2(<8 x bfloat> [[INACTIVE]], <4 x float> [[A]]) -// CHECK-A64-NEXT: [[VCVTQ_HIGH_BF16_V3_I:%.*]] = bitcast <8 x bfloat> [[VCVTQ_HIGH_BF16_V2_I]] to <16 x i8> -// CHECK-A64-NEXT: ret <8 x bfloat> [[VCVTQ_HIGH_BF16_V2_I]] +// CHECK-A64-NEXT: [[VCVTQ_HIGH_BF16_F322_I:%.*]] = call <8 x bfloat> @llvm.aarch64.neon.bfcvtn2(<8 x bfloat> [[INACTIVE]], <4 x float> [[A]]) +// CHECK-A64-NEXT: [[VCVTQ_HIGH_BF16_F323_I:%.*]] = bitcast <8 x bfloat> [[VCVTQ_HIGH_BF16_F322_I]] to <16 x i8> +// CHECK-A64-NEXT: ret <8 x bfloat> [[VCVTQ_HIGH_BF16_F322_I]] // // CHECK-A32-HARDFP-LABEL: @test_vcvtq_high_bf16_f32( // CHECK-A32-HARDFP-NEXT: entry: @@ -358,45 +358,45 @@ bfloat16x8_t test_vcvtq_low_bf16_f32(float32x4_t a) { // CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[INACTIVE_COERCE:%.*]], ptr [[INACTIVE]], align 8 // CHECK-A32-SOFTFP-NEXT: [[INACTIVE1:%.*]] = load <8 x bfloat>, ptr [[INACTIVE]], align 8 // CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[INACTIVE1]], ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = load <4 x i32>, ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP2]], ptr [[__P0_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr [[COERCE]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP0]], ptr [[__P0_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P01_I:%.*]] = load <8 x bfloat>, ptr [[__P0_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = bitcast <4 x float> [[A:%.*]] to <16 x i8> +// CHECK-A32-SOFTFP-NEXT: [[TMP1:%.*]] = bitcast <4 x float> [[A:%.*]] to <16 x i8> // CHECK-A32-SOFTFP-NEXT: [[VCVTFP2BF1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2bf.v4i16(<4 x float> [[A]]) -// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = bitcast <4 x i16> [[VCVTFP2BF1_I]] to <4 x bfloat> -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP5]], ptr [[RETVAL_I8]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = load <2 x i32>, ptr [[RETVAL_I8]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP7]], ptr [[COERCE_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP9:%.*]] = load <4 x bfloat>, ptr [[COERCE_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[VCVTFP2BF1_I]] to <4 x bfloat> +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP2]], ptr [[RETVAL_I8]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <2 x i32>, ptr [[RETVAL_I8]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP3]], ptr [[COERCE_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <4 x bfloat>, ptr [[COERCE_I]], align 8 // CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[__P01_I]], ptr [[COERCE2_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP11:%.*]] = load <4 x i32>, ptr [[COERCE2_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP11]], ptr [[__P0_I4]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i32>, ptr [[COERCE2_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP5]], ptr [[__P0_I4]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P01_I7:%.*]] = load <8 x bfloat>, ptr [[__P0_I4]], align 8 // CHECK-A32-SOFTFP-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[__P01_I7]], <8 x bfloat> [[__P01_I7]], <4 x i32> // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[RETVAL_I3]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP14:%.*]] = load <2 x i32>, ptr [[RETVAL_I3]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP14]], ptr [[COERCE4_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP16:%.*]] = load <4 x bfloat>, ptr [[COERCE4_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP9]], ptr [[COERCE5_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP18:%.*]] = load <2 x i32>, ptr [[COERCE5_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP16]], ptr [[COERCE6_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP20:%.*]] = load <2 x i32>, ptr [[COERCE6_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP18]], ptr [[__P0_I12]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP6:%.*]] = load <2 x i32>, ptr [[RETVAL_I3]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP6]], ptr [[COERCE4_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = load <4 x bfloat>, ptr [[COERCE4_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP4]], ptr [[COERCE5_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <2 x i32>, ptr [[COERCE5_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP7]], ptr [[COERCE6_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP9:%.*]] = load <2 x i32>, ptr [[COERCE6_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP8]], ptr [[__P0_I12]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P01_I16:%.*]] = load <4 x bfloat>, ptr [[__P0_I12]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP20]], ptr [[__P1_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP9]], ptr [[__P1_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[__P12_I:%.*]] = load <4 x bfloat>, ptr [[__P1_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[SHUFFLE_I17:%.*]] = shufflevector <4 x bfloat> [[__P01_I16]], <4 x bfloat> [[__P12_I]], <8 x i32> // CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[SHUFFLE_I17]], ptr [[RETVAL_I11]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP24:%.*]] = load <4 x i32>, ptr [[RETVAL_I11]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP24]], ptr [[COERCE8_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP26:%.*]] = load <8 x bfloat>, ptr [[COERCE8_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[TMP26]], ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP28:%.*]] = load <4 x i32>, ptr [[RETVAL_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP28]], ptr [[COERCE2]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP30:%.*]] = load <8 x bfloat>, ptr [[COERCE2]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[TMP30]], ptr [[RETVAL]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP32:%.*]] = load <4 x i32>, ptr [[RETVAL]], align 8 -// CHECK-A32-SOFTFP-NEXT: ret <4 x i32> [[TMP32]] +// CHECK-A32-SOFTFP-NEXT: [[TMP10:%.*]] = load <4 x i32>, ptr [[RETVAL_I11]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP10]], ptr [[COERCE8_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP11:%.*]] = load <8 x bfloat>, ptr [[COERCE8_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[TMP11]], ptr [[RETVAL_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP12:%.*]] = load <4 x i32>, ptr [[RETVAL_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[TMP12]], ptr [[COERCE2]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP13:%.*]] = load <8 x bfloat>, ptr [[COERCE2]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <8 x bfloat> [[TMP13]], ptr [[RETVAL]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP14:%.*]] = load <4 x i32>, ptr [[RETVAL]], align 8 +// CHECK-A32-SOFTFP-NEXT: ret <4 x i32> [[TMP14]] // bfloat16x8_t test_vcvtq_high_bf16_f32(bfloat16x8_t inactive, float32x4_t a) { return vcvtq_high_bf16_f32(inactive, a); diff --git a/clang/test/CodeGen/attr-target-clones-aarch64.c b/clang/test/CodeGen/attr-target-clones-aarch64.c index 292e544139e3f..c490682e310af 100644 --- a/clang/test/CodeGen/attr-target-clones-aarch64.c +++ b/clang/test/CodeGen/attr-target-clones-aarch64.c @@ -4,10 +4,10 @@ // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +mte -target-feature +bti -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-MTE-BTI int __attribute__((target_clones("lse+aes", "sve2"))) ftc(void) { return 0; } -int __attribute__((target_clones("sha2", "sha2+memtag2", " default "))) ftc_def(void) { return 1; } +int __attribute__((target_clones("sha2", "sha2+memtag", " default "))) ftc_def(void) { return 1; } int __attribute__((target_clones("sha2", "default"))) ftc_dup1(void) { return 2; } int __attribute__((target_clones("fp", "crc+dotprod"))) ftc_dup2(void) { return 3; } -int __attribute__((target_clones("memtag2", "bti"))) ftc_dup3(void) { return 4; } +int __attribute__((target_clones("memtag", "bti"))) ftc_dup3(void) { return 4; } int foo() { return ftc() + ftc_def() + ftc_dup1() + ftc_dup2() + ftc_dup3(); } @@ -90,7 +90,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@ftc_def._Mmemtag2Msha2 +// CHECK-LABEL: define {{[^@]+}}@ftc_def._MmemtagMsha2 // CHECK-SAME: () #[[ATTR3:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 @@ -105,7 +105,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] // CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: -// CHECK-NEXT: ret ptr @ftc_def._Mmemtag2Msha2 +// CHECK-NEXT: ret ptr @ftc_def._MmemtagMsha2 // CHECK: resolver_else: // CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 // CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 4096 @@ -176,7 +176,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@ftc_dup3._Mmemtag2 +// CHECK-LABEL: define {{[^@]+}}@ftc_dup3._Mmemtag // CHECK-SAME: () #[[ATTR6:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 @@ -206,7 +206,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] // CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] // CHECK: resolver_return1: -// CHECK-NEXT: ret ptr @ftc_dup3._Mmemtag2 +// CHECK-NEXT: ret ptr @ftc_dup3._Mmemtag // CHECK: resolver_else2: // CHECK-NEXT: ret ptr @ftc_dup3.default // @@ -547,7 +547,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone -// CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_def._Mmemtag2Msha2 +// CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_def._MmemtagMsha2 // CHECK-MTE-BTI-SAME: () #[[ATTR2]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 1 @@ -562,7 +562,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-MTE-BTI-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] // CHECK-MTE-BTI-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK-MTE-BTI: resolver_return: -// CHECK-MTE-BTI-NEXT: ret ptr @ftc_def._Mmemtag2Msha2 +// CHECK-MTE-BTI-NEXT: ret ptr @ftc_def._MmemtagMsha2 // CHECK-MTE-BTI: resolver_else: // CHECK-MTE-BTI-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 // CHECK-MTE-BTI-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 4096 @@ -633,7 +633,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone -// CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_dup3._Mmemtag2 +// CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_dup3._Mmemtag // CHECK-MTE-BTI-SAME: () #[[ATTR5:[0-9]+]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 4 @@ -663,7 +663,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-MTE-BTI-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] // CHECK-MTE-BTI-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] // CHECK-MTE-BTI: resolver_return1: -// CHECK-MTE-BTI-NEXT: ret ptr @ftc_dup3._Mmemtag2 +// CHECK-MTE-BTI-NEXT: ret ptr @ftc_dup3._Mmemtag // CHECK-MTE-BTI: resolver_else2: // CHECK-MTE-BTI-NEXT: ret ptr @ftc_dup3.default // diff --git a/clang/test/CodeGen/attr-target-clones-riscv.c b/clang/test/CodeGen/attr-target-clones-riscv.c index 4a5dea91e2276..2e8018c707d96 100644 --- a/clang/test/CodeGen/attr-target-clones-riscv.c +++ b/clang/test/CodeGen/attr-target-clones-riscv.c @@ -16,10 +16,9 @@ __attribute__((target_clones("default", "arch=+zvkt"))) int foo6(void) { return __attribute__((target_clones("default", "arch=+zbb", "arch=+zba", "arch=+zbb,+zba"))) int foo7(void) { return 2; } __attribute__((target_clones("default", "arch=+zbb;priority=2", "arch=+zba;priority=1", "arch=+zbb,+zba;priority=3"))) int foo8(void) { return 2; } __attribute__((target_clones("default", "arch=+zbb;priority=1", "priority=2;arch=+zba", "priority=3;arch=+zbb,+zba"))) int foo9(void) { return 2; } -__attribute__((target_clones("default", "arch=+zbb;priority=-1", "priority=-2;arch=+zba", "priority=3;arch=+zbb,+zba"))) int foo10(void) { return 2; } -int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() + foo8() + foo9() + foo10(); } +int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() + foo8() + foo9(); } //. // CHECK: @__riscv_feature_bits = external dso_local global { i32, [2 x i64] } @@ -32,7 +31,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() // CHECK: @foo7.ifunc = weak_odr alias i32 (), ptr @foo7 // CHECK: @foo8.ifunc = weak_odr alias i32 (), ptr @foo8 // CHECK: @foo9.ifunc = weak_odr alias i32 (), ptr @foo9 -// CHECK: @foo10.ifunc = weak_odr alias i32 (), ptr @foo10 // CHECK: @foo1 = weak_odr ifunc i32 (), ptr @foo1.resolver // CHECK: @foo2 = weak_odr ifunc i32 (), ptr @foo2.resolver // CHECK: @foo3 = weak_odr ifunc i32 (), ptr @foo3.resolver @@ -42,7 +40,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() // CHECK: @foo7 = weak_odr ifunc i32 (), ptr @foo7.resolver // CHECK: @foo8 = weak_odr ifunc i32 (), ptr @foo8.resolver // CHECK: @foo9 = weak_odr ifunc i32 (), ptr @foo9.resolver -// CHECK: @foo10 = weak_odr ifunc i32 (), ptr @foo10.resolver //. // CHECK-LABEL: define dso_local signext i32 @foo1.default( // CHECK-SAME: ) #[[ATTR0:[0-9]+]] { @@ -347,57 +344,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() // CHECK-NEXT: ret ptr @foo9.default // // -// CHECK-LABEL: define dso_local signext i32 @foo10.default( -// CHECK-SAME: ) #[[ATTR0]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: define dso_local signext i32 @foo10._zbb( -// CHECK-SAME: ) #[[ATTR2]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: define dso_local signext i32 @foo10._zba( -// CHECK-SAME: ) #[[ATTR6]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: define dso_local signext i32 @foo10._zba_zbb( -// CHECK-SAME: ) #[[ATTR7]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: define weak_odr ptr @foo10.resolver() comdat { -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: call void @__init_riscv_feature_bits(ptr null) -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 402653184 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184 -// CHECK-NEXT: br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] -// CHECK: resolver_return: -// CHECK-NEXT: ret ptr @foo10._zba_zbb -// CHECK: resolver_else: -// CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP4:%.*]] = and i64 [[TMP3]], 268435456 -// CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 268435456 -// CHECK-NEXT: br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] -// CHECK: resolver_return1: -// CHECK-NEXT: ret ptr @foo10._zbb -// CHECK: resolver_else2: -// CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], 134217728 -// CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 134217728 -// CHECK-NEXT: br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] -// CHECK: resolver_return3: -// CHECK-NEXT: ret ptr @foo10._zba -// CHECK: resolver_else4: -// CHECK-NEXT: ret ptr @foo10.default -// -// // CHECK-LABEL: define dso_local signext i32 @bar( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -418,9 +364,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() // CHECK-NEXT: [[ADD13:%.*]] = add nsw i32 [[ADD11]], [[CALL12]] // CHECK-NEXT: [[CALL14:%.*]] = call signext i32 @foo9() // CHECK-NEXT: [[ADD15:%.*]] = add nsw i32 [[ADD13]], [[CALL14]] -// CHECK-NEXT: [[CALL16:%.*]] = call signext i32 @foo10() -// CHECK-NEXT: [[ADD17:%.*]] = add nsw i32 [[ADD15]], [[CALL16]] -// CHECK-NEXT: ret i32 [[ADD17]] +// CHECK-NEXT: ret i32 [[ADD15]] // //. // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i" } diff --git a/clang/test/CodeGen/attr-target-version-riscv.c b/clang/test/CodeGen/attr-target-version-riscv.c index 7d0e61e61542f..362b9ad323652 100644 --- a/clang/test/CodeGen/attr-target-version-riscv.c +++ b/clang/test/CodeGen/attr-target-version-riscv.c @@ -32,12 +32,7 @@ __attribute__((target_version("arch=+zbb;priority=9"))) int foo7(void) { return __attribute__((target_version("arch=+zbb,+zba;priority=10"))) int foo7(void) { return 1; } __attribute__((target_version("default"))) int foo7(void) { return 1; } -__attribute__((target_version("priority=-1;arch=+zba"))) int foo8(void) { return 1; } -__attribute__((target_version("arch=+zbb;priority=-2"))) int foo8(void) { return 1; } -__attribute__((target_version("arch=+zbb,+zba;priority=3"))) int foo8(void) { return 1; } -__attribute__((target_version("default"))) int foo8(void) { return 1; } - -int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() + foo8(); } +int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7(); } //. // CHECK: @__riscv_feature_bits = external dso_local global { i32, [2 x i64] } // CHECK: @foo1 = weak_odr ifunc i32 (), ptr @foo1.resolver @@ -47,7 +42,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() // CHECK: @foo5 = weak_odr ifunc i32 (), ptr @foo5.resolver // CHECK: @foo6 = weak_odr ifunc i32 (), ptr @foo6.resolver // CHECK: @foo7 = weak_odr ifunc i32 (), ptr @foo7.resolver -// CHECK: @foo8 = weak_odr ifunc i32 (), ptr @foo8.resolver //. // CHECK-LABEL: define dso_local signext i32 @foo1._v( // CHECK-SAME: ) #[[ATTR0:[0-9]+]] { @@ -193,30 +187,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() // CHECK-NEXT: ret i32 1 // // -// CHECK-LABEL: define dso_local signext i32 @foo8._zba( -// CHECK-SAME: ) #[[ATTR5]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// -// CHECK-LABEL: define dso_local signext i32 @foo8._zbb( -// CHECK-SAME: ) #[[ATTR2]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// -// CHECK-LABEL: define dso_local signext i32 @foo8._zba_zbb( -// CHECK-SAME: ) #[[ATTR6]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// -// CHECK-LABEL: define dso_local signext i32 @foo8.default( -// CHECK-SAME: ) #[[ATTR1]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// // CHECK-LABEL: define dso_local signext i32 @bar( // CHECK-SAME: ) #[[ATTR1]] { // CHECK-NEXT: entry: @@ -233,9 +203,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() // CHECK-NEXT: [[ADD9:%.*]] = add nsw i32 [[ADD7]], [[CALL8]] // CHECK-NEXT: [[CALL10:%.*]] = call signext i32 @foo7() // CHECK-NEXT: [[ADD11:%.*]] = add nsw i32 [[ADD9]], [[CALL10]] -// CHECK-NEXT: [[CALL12:%.*]] = call signext i32 @foo8() -// CHECK-NEXT: [[ADD13:%.*]] = add nsw i32 [[ADD11]], [[CALL12]] -// CHECK-NEXT: ret i32 [[ADD13]] +// CHECK-NEXT: ret i32 [[ADD11]] // // // CHECK-LABEL: define weak_odr ptr @foo1.resolver() comdat { @@ -398,33 +366,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5() + foo6() + foo7() // CHECK: resolver_else4: // CHECK-NEXT: ret ptr @foo7.default // -// -// CHECK-LABEL: define weak_odr ptr @foo8.resolver() comdat { -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: call void @__init_riscv_feature_bits(ptr null) -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 402653184 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184 -// CHECK-NEXT: br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] -// CHECK: resolver_return: -// CHECK-NEXT: ret ptr @foo8._zba_zbb -// CHECK: resolver_else: -// CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP4:%.*]] = and i64 [[TMP3]], 134217728 -// CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 134217728 -// CHECK-NEXT: br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] -// CHECK: resolver_return1: -// CHECK-NEXT: ret ptr @foo8._zba -// CHECK: resolver_else2: -// CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], 268435456 -// CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 268435456 -// CHECK-NEXT: br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] -// CHECK: resolver_return3: -// CHECK-NEXT: ret ptr @foo8._zbb -// CHECK: resolver_else4: -// CHECK-NEXT: ret ptr @foo8.default -// //. // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+d,+f,+i,+v,+zicsr,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } // CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i" } diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index 22a53c82bfbf9..0e2c7ad99d81b 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -34,7 +34,7 @@ inline int __attribute__((target_version("rcpc+frintts"))) fmv_inline(void) { re inline int __attribute__((target_version("sve+sve-bf16"))) fmv_inline(void) { return 4; } inline int __attribute__((target_version("sve2-aes+sve2-sha3"))) fmv_inline(void) { return 5; } inline int __attribute__((target_version("sve2+sve2-pmull128+sve2-bitperm"))) fmv_inline(void) { return 9; } -inline int __attribute__((target_version("sve2-sm4+memtag2"))) fmv_inline(void) { return 10; } +inline int __attribute__((target_version("sve2-sm4+memtag"))) fmv_inline(void) { return 10; } inline int __attribute__((target_version("memtag3+rcpc3+mops"))) fmv_inline(void) { return 11; } inline int __attribute__((target_version("aes+dotprod"))) fmv_inline(void) { return 13; } inline int __attribute__((target_version("simd+fp16fml"))) fmv_inline(void) { return 14; } @@ -500,8 +500,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // CHECK-NEXT: ret ptr @fmv._McrcMls64 // CHECK: resolver_else6: // CHECK-NEXT: [[TMP16:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP17:%.*]] = and i64 [[TMP16]], 8796093022216 -// CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 8796093022216 +// CHECK-NEXT: [[TMP17:%.*]] = and i64 [[TMP16]], 17592186044424 +// CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 17592186044424 // CHECK-NEXT: [[TMP19:%.*]] = and i1 true, [[TMP18]] // CHECK-NEXT: br i1 [[TMP19]], label [[RESOLVER_RETURN7:%.*]], label [[RESOLVER_ELSE8:%.*]] // CHECK: resolver_return7: @@ -729,7 +729,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag2Msve2-sm4 +// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MmemtagMsve2-sm4 // CHECK-SAME: () #[[ATTR34:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 10 @@ -751,21 +751,21 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mfp16fmlMsimd -// CHECK-SAME: () #[[ATTR4]] { +// CHECK-SAME: () #[[ATTR36:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 14 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfpMsm4 -// CHECK-SAME: () #[[ATTR36:[0-9]+]] { +// CHECK-SAME: () #[[ATTR37:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 15 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MlseMrdm -// CHECK-SAME: () #[[ATTR37:[0-9]+]] { +// CHECK-SAME: () #[[ATTR38:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 16 // @@ -826,7 +826,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // CHECK-NEXT: [[TMP23:%.*]] = and i1 true, [[TMP22]] // CHECK-NEXT: br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]] // CHECK: resolver_return9: -// CHECK-NEXT: ret ptr @fmv_inline._Mmemtag2Msve2-sm4 +// CHECK-NEXT: ret ptr @fmv_inline._MmemtagMsve2-sm4 // CHECK: resolver_else10: // CHECK-NEXT: [[TMP24:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 // CHECK-NEXT: [[TMP25:%.*]] = and i64 [[TMP24]], 1236950581248 diff --git a/clang/test/CodeGen/builtins-array-rank.cpp b/clang/test/CodeGen/builtins-array-rank.cpp new file mode 100644 index 0000000000000..e6f0a55245aad --- /dev/null +++ b/clang/test/CodeGen/builtins-array-rank.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple aarch64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +unsigned long array_rank_binary_operator(void) { + // CHECK: ret i64 3 + return __array_rank(int[10]) | 2; +} diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c index d83d4d02ac199..b2259031d7563 100644 --- a/clang/test/CodeGen/cx-complex-range.c +++ b/clang/test/CodeGen/cx-complex-range.c @@ -1264,24 +1264,24 @@ _Complex float mulf(_Complex float a, _Complex float b) { // AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { // AVRFP32-NEXT: entry: // AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 -// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 4 -// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 1 // AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0 -// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 4 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 // AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 -// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 4 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 // AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 0 -// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 4 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 // AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1 -// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 4 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 // AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0 -// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 // AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 -// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 // AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 0 -// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 // AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1 -// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 // AVRFP32-NEXT: [[TMP4:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_REAL]]) // AVRFP32-NEXT: [[TMP5:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_IMAG]]) // AVRFP32-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP4]], [[TMP5]] @@ -1321,24 +1321,24 @@ _Complex float mulf(_Complex float a, _Complex float b) { // AVRFP64-LABEL: define dso_local void @divd( // AVRFP64-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 1 [[AGG_RESULT:%.*]], double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { // AVRFP64-NEXT: entry: -// AVRFP64-NEXT: [[A:%.*]] = alloca { double, double }, align 8 -// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// AVRFP64-NEXT: [[A:%.*]] = alloca { double, double }, align 1 +// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 1 // AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 -// AVRFP64-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// AVRFP64-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 1 // AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 -// AVRFP64-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// AVRFP64-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 1 // AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 -// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 1 // AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1 -// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 1 // AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 -// AVRFP64-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 1 // AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 -// AVRFP64-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 1 // AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 -// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 1 // AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1 -// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 1 // AVRFP64-NEXT: [[TMP4:%.*]] = call addrspace(1) double @llvm.fabs.f64(double [[B_REAL]]) // AVRFP64-NEXT: [[TMP5:%.*]] = call addrspace(1) double @llvm.fabs.f64(double [[B_IMAG]]) // AVRFP64-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP4]], [[TMP5]] @@ -1862,24 +1862,24 @@ _Complex double divd(_Complex double a, _Complex double b) { // AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { // AVRFP32-NEXT: entry: // AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 -// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 4 -// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 1 // AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0 -// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 4 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 // AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 -// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 4 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 // AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 0 -// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 4 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 // AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1 -// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 4 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 // AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 0 -// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 // AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[A]], i32 0, i32 1 -// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 // AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 0 -// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 // AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[B]], i32 0, i32 1 -// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 // AVRFP32-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] // AVRFP32-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] // AVRFP32-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] @@ -1896,24 +1896,24 @@ _Complex double divd(_Complex double a, _Complex double b) { // AVRFP64-LABEL: define dso_local void @muld( // AVRFP64-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 1 [[AGG_RESULT:%.*]], double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { // AVRFP64-NEXT: entry: -// AVRFP64-NEXT: [[A:%.*]] = alloca { double, double }, align 8 -// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// AVRFP64-NEXT: [[A:%.*]] = alloca { double, double }, align 1 +// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 1 // AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 -// AVRFP64-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// AVRFP64-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 1 // AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 -// AVRFP64-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// AVRFP64-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 1 // AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 -// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 1 // AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1 -// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 1 // AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 0 -// AVRFP64-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 1 // AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[A]], i32 0, i32 1 -// AVRFP64-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 1 // AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 0 -// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 1 // AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[B]], i32 0, i32 1 -// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 1 // AVRFP64-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] // AVRFP64-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] // AVRFP64-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] diff --git a/clang/test/CodeGen/mdouble.c b/clang/test/CodeGen/mdouble.c index 6c73bd7b15901..dab0c5f834bc3 100644 --- a/clang/test/CodeGen/mdouble.c +++ b/clang/test/CodeGen/mdouble.c @@ -6,8 +6,7 @@ double x = 0; int size = sizeof(x); -// FIXME: the double should have an alignment of 1 on AVR, not 4 or 8. -// AVR-FP64: @x ={{.*}} global double {{.*}}, align 8 +// AVR-FP64: @x ={{.*}} global double {{.*}}, align 1 // AVR-FP64: @size ={{.*}} global i16 8 -// AVR-FP32: @x ={{.*}} global float {{.*}}, align 4 +// AVR-FP32: @x ={{.*}} global float {{.*}}, align 1 // AVR-FP32: @size ={{.*}} global i16 4 diff --git a/clang/test/CodeGen/tbaa-pointers.c b/clang/test/CodeGen/tbaa-pointers.c index 8860b7042d0a2..f33281ada9903 100644 --- a/clang/test/CodeGen/tbaa-pointers.c +++ b/clang/test/CodeGen/tbaa-pointers.c @@ -116,10 +116,12 @@ void p2struct(struct S1 **ptr) { // COMMON-LABEL: define void @p2struct( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR:!.+]] + // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2S1_TAG:!.+]] // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // COMMON-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // COMMON-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] + // ENABLED-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P2S1_TAG]] + // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // ENABLED-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_TAG:!.+]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // *ptr = 0; @@ -129,9 +131,10 @@ void p2struct_const(struct S1 const **ptr) { // COMMON-LABEL: define void @p2struct_const( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // COMMON-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // COMMON-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR:!.+]] // COMMON-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // COMMON-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] + // ENABLED-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_TAG]] + // DEFAULT-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANYPTR]] // COMMON-NEXT: ret void // *ptr = 0; @@ -145,14 +148,44 @@ void p2struct2(struct S2 *ptr) { // COMMON-LABEL: define void @p2struct2( // COMMON-SAME: ptr noundef [[PTR:%.+]]) // COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 - // COMMON-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // COMMON-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] - // COMMON-NEXT: [[S:%.+]] = getelementptr inbounds nuw %struct.S2, ptr [[BASE]], i32 0, i32 0 - // COMMON-NEXT: store ptr null, ptr [[S]], align 8, !tbaa [[S2_S_TAG:!.+]] + // ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1S2_TAG:!.+]] + // ENABLED-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1S2_TAG]] + // ENABLED-NEXT: [[S:%.+]] = getelementptr inbounds nuw %struct.S2, ptr [[BASE]], i32 0, i32 0 + // ENABLED-NEXT: store ptr null, ptr [[S]], align 8, !tbaa [[S2_S_TAG:!.+]] + // DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: [[BASE:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] + // DEFAULT-NEXT: [[S:%.+]] = getelementptr inbounds nuw %struct.S2, ptr [[BASE]], i32 0, i32 0 + // DEFAULT-NEXT: store ptr null, ptr [[S]], align 8, !tbaa [[S2_S_TAG:!.+]] // COMMON-NEXT: ret void ptr->s = 0; } + +void vla1(int n, int ptr[][n], int idx) { +// COMMON-LABEL: define void @vla1( +// COMMON-SAME: i32 noundef [[N:%.+]], ptr noundef [[PTR:%.+]], i32 noundef [[IDX:%.+]]) +// COMMON: [[N_ADDR:%.+]] = alloca i32, align 4 +// COMMON-NEXT: [[PTR_ADDR:%.+]] = alloca ptr, align 8 +// COMMON-NEXT: [[IDX_ADDR:%.+]] = alloca i32, align 4 +// COMMON-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4, !tbaa [[INT_TY:!.+]] +// ENABLED-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1INT0:!.+]] +// DEFAULT-NEXT: store ptr [[PTR]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// COMMON-NEXT: store i32 [[IDX]], ptr [[IDX_ADDR]], align 4, !tbaa [[INT_TY]] +// COMMON-NEXT: [[L:%.+]] = load i32, ptr [[N_ADDR]], align 4, !tbaa [[INT_TY]] +// COMMON-NEXT: [[L_EXT:%.+]] = zext i32 [[L]] to i64 +// ENABLED-NEXT: [[L_PTR:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1INT0]] +// DEFAULT-NEXT: [[L_PTR:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// COMMON-NEXT: [[L_IDX:%.+]] = load i32, ptr [[IDX_ADDR]], align 4, !tbaa [[INT_TY]] +// COMMON-NEXT: [[IDX_EXT:%.+]] = sext i32 [[L_IDX]] to i64 +// COMMON-NEXT: [[MUL:%.+]] = mul nsw i64 [[IDX_EXT]], [[L_EXT]] +// COMMON-NEXT: [[GEP1:%.+]] = getelementptr inbounds i32, ptr [[L_PTR]], i64 [[MUL]] +// COMMON-NEXT: [[GEP2:%.+]] = getelementptr inbounds i32, ptr [[GEP1]], i64 0 +// COMMON-NEXT: store i32 0, ptr [[GEP2]], align 4, !tbaa [[INT_TAG:!.+]] +// ENABLED-NEXT: ret void + + ptr[idx][0] = 0; +} + // ENABLED: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0} // ENABLED: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0} // DEFAULT: [[ANYPTR]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0} @@ -171,5 +204,16 @@ void p2struct2(struct S2 *ptr) { // ENABLED: [[P2CHAR]] = !{!"p2 omnipotent char", [[ANY_POINTER]], i64 0} // ENABLED: [[P1CHAR_0]] = !{[[P1CHAR:!.+]], [[P1CHAR]], i64 0} // ENABLED: [[P1CHAR]] = !{!"p1 omnipotent char", [[ANY_POINTER]], i64 0} -// COMMON: [[S2_S_TAG]] = !{[[S2_TY:!.+]], [[ANY_POINTER]], i64 0} -// COMMON: [[S2_TY]] = !{!"S2", [[ANY_POINTER]], i64 0} +// ENABLED: [[P2S1_TAG]] = !{[[P2S1:!.+]], [[P2S1]], i64 0} +// ENABLED: [[P2S1]] = !{!"p2 _ZTS2S1", [[ANY_POINTER]], i64 0} +// ENABLED: [[P1S1_TAG:!.+]] = !{[[P1S1:!.+]], [[P1S1]], i64 0} +// ENABLED: [[P1S1]] = !{!"p1 _ZTS2S1", [[ANY_POINTER]], i64 0} +// ENABLED: [[P1S2_TAG]] = !{[[P1S2:!.+]], [[P1S2]], i64 0} +// ENABLED: [[P1S2]] = !{!"p1 _ZTS2S2", [[ANY_POINTER]], i64 0} + +// ENABLED: [[S2_S_TAG]] = !{[[S2_TY:!.+]], [[P1S1]], i64 0} +// ENABLED: [[S2_TY]] = !{!"S2", [[P1S1]], i64 0} +// DEFAULT: [[S2_S_TAG]] = !{[[S2_TY:!.+]], [[ANY_POINTER]], i64 0} +// DEFAULT: [[S2_TY]] = !{!"S2", [[ANY_POINTER]], i64 0} +// COMMON: [[INT_TAG]] = !{[[INT_TY:!.+]], [[INT_TY]], i64 0} +// COMMON: [[INT_TY]] = !{!"int", [[CHAR]], i64 0} diff --git a/clang/test/CodeGen/tbaa-reference.cpp b/clang/test/CodeGen/tbaa-reference.cpp index d22cd90b43ae9..8395badf35ded 100644 --- a/clang/test/CodeGen/tbaa-reference.cpp +++ b/clang/test/CodeGen/tbaa-reference.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH -// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes -pointer-tbaa %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH +// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes -pointer-tbaa %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,OLD-PATH-POINTER // RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH -// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -pointer-tbaa -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH +// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s -pointer-tbaa -emit-llvm -new-struct-path-tbaa -o - | FileCheck %s -check-prefixes=CHECK,NEW-PATH-POINTER // // Check that we generate correct TBAA information for reference accesses. @@ -16,13 +16,13 @@ struct B { B::B(S &s) : s(s) { // CHECK-LABEL: _ZN1BC2ER1S // Check initialization of the reference parameter. -// CHECK: store ptr {{.*}}, ptr {{.*}}, !tbaa [[TAG_pointer:!.*]] +// CHECK: store ptr {{.*}}, ptr %s.addr, align 8, !tbaa [[TAG_S_PTR:!.*]] // Check loading of the reference parameter. -// CHECK: load ptr, ptr {{.*}}, !tbaa [[TAG_pointer]] +// CHECK: load ptr, ptr {{.*}}, !tbaa [[TAG_S_PTR:!.*]] // Check initialization of the reference member. -// CHECK: store ptr {{.*}}, ptr {{.*}}, !tbaa [[TAG_pointer]] +// CHECK: store ptr {{.*}}, ptr {{.*}}, !tbaa [[TAG_S_PTR]] } S &B::get() { @@ -32,16 +32,32 @@ S &B::get() { return s; } -// OLD-PATH-DAG: [[TAG_pointer]] = !{[[TYPE_pointer:!.*]], [[TYPE_pointer]], i64 0} +// OLD-PATH-DAG: [[TAG_S_PTR]] = !{[[TYPE_pointer:!.*]], [[TYPE_pointer]], i64 0} // OLD-PATH-DAG: [[TAG_B_s]] = !{[[TYPE_B:!.*]], [[TYPE_pointer]], i64 0} // // OLD-PATH-DAG: [[TYPE_B]] = !{!"_ZTS1B", [[TYPE_pointer]], i64 0} // OLD-PATH-DAG: [[TYPE_pointer]] = !{!"any pointer", [[TYPE_char:!.*]], i64 0} // OLD-PATH-DAG: [[TYPE_char]] = !{!"omnipotent char", {{!.*}}, i64 0} -// NEW-PATH-DAG: [[TAG_pointer]] = !{[[TYPE_pointer:!.*]], [[TYPE_pointer]], i64 0, i64 8} +// OLD-PATH-POINTER-DAG: [[TAG_S_PTR]] = !{[[TYPE_S_PTR:!.*]], [[TYPE_S_PTR]], i64 0} +// OLD-PATH-POINTER-DAG: [[TAG_B_s]] = !{[[TYPE_B:!.*]], [[TYPE_S_PTR:!.*]], i64 0} +// +// OLD-PATH-POINTER-DAG: [[TYPE_B]] = !{!"_ZTS1B", [[TYPE_S_PTR:!.*]], i64 0} +// OLD-PATH-POINTER-DAG: [[TYPE_pointer:!.*]] = !{!"any pointer", [[TYPE_char:!.*]], i64 0} +// OLD-PATH-POINTER-DAG: [[TYPE_char]] = !{!"omnipotent char", {{!.*}}, i64 0} +// OLD-PATH-POINTER-DAG: [[TYPE_S_PTR]] = !{!"p1 _ZTS1S", [[TYPE_pointer]], i64 0} + +// NEW-PATH-DAG: [[TAG_S_PTR]] = !{[[TYPE_pointer:!.*]], [[TYPE_pointer]], i64 0, i64 8} // NEW-PATH-DAG: [[TAG_B_s]] = !{[[TYPE_B:!.*]], [[TYPE_pointer]], i64 0, i64 8} // // NEW-PATH-DAG: [[TYPE_B]] = !{[[TYPE_char:!.*]], i64 8, !"_ZTS1B", [[TYPE_pointer]], i64 0, i64 8} // NEW-PATH-DAG: [[TYPE_pointer]] = !{[[TYPE_char:!.*]], i64 8, !"any pointer"} // NEW-PATH-DAG: [[TYPE_char]] = !{{{!.*}}, i64 1, !"omnipotent char"} + +// NEW-PATH-POINTER-DAG: [[TAG_S_PTR]] = !{[[TYPE_S_PTR:!.*]], [[TYPE_S_PTR]], i64 0, i64 8} +// NEW-PATH-POINTER-DAG: [[TAG_B_s]] = !{[[TYPE_B:!.*]], [[TYPE_S_PTR]], i64 0, i64 8} +// +// NEW-PATH-POINTER-DAG: [[TYPE_B]] = !{[[TYPE_char:!.*]], i64 8, !"_ZTS1B", [[TYPE_S_PTR]], i64 0, i64 8} +// NEW-PATH-POINTER-DAG: [[TYPE_S_PTR]] = !{[[TYPE_pointer:!.+]], i64 8, !"p1 _ZTS1S"} +// NEW-PATH-POINTER-DAG: [[TYPE_pointer]] = !{[[TYPE_char:!.*]], i64 8, !"any pointer"} +// NEW-PATH-POINTER-DAG: [[TYPE_char]] = !{{{!.*}}, i64 1, !"omnipotent char"} diff --git a/clang/test/CodeGen/variadic-nvptx.c b/clang/test/CodeGen/variadic-nvptx.c index dd7cba552580f..4e4fc5ecdef65 100644 --- a/clang/test/CodeGen/variadic-nvptx.c +++ b/clang/test/CodeGen/variadic-nvptx.c @@ -30,7 +30,7 @@ extern void varargs_simple(int, ...); // CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[F]], align 4 // CHECK-NEXT: [[CONV2:%.*]] = fpext float [[TMP4]] to double // CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[D]], align 8 -// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i32 noundef [[CONV]], i32 noundef [[CONV1]], i32 noundef [[TMP2]], i64 noundef [[TMP3]], double noundef [[CONV2]], double noundef [[TMP5]]) +// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i32 noundef [[CONV]], i32 noundef [[CONV1]], i32 noundef [[TMP2]], i64 noundef [[TMP3]], double noundef [[CONV2]], double noundef [[TMP5]]) #[[ATTR3:[0-9]+]] // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A]], ptr align 4 @__const.foo.a, i64 12, i1 false) // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_ANON]], ptr [[A]], i32 0, i32 0 // CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 4 @@ -38,10 +38,10 @@ extern void varargs_simple(int, ...); // CHECK-NEXT: [[TMP9:%.*]] = load i8, ptr [[TMP8]], align 4 // CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT_ANON]], ptr [[A]], i32 0, i32 2 // CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[TMP10]], align 4 -// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i32 [[TMP7]], i8 [[TMP9]], i32 [[TMP11]]) +// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i32 [[TMP7]], i8 [[TMP9]], i32 [[TMP11]]) #[[ATTR3]] // CHECK-NEXT: store <4 x i32> , ptr [[V]], align 16 // CHECK-NEXT: [[TMP12:%.*]] = load <4 x i32>, ptr [[V]], align 16 -// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, <4 x i32> noundef [[TMP12]]) +// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, <4 x i32> noundef [[TMP12]]) #[[ATTR3]] // CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 0 // CHECK-NEXT: [[TMP14:%.*]] = load i8, ptr [[TMP13]], align 1 // CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 1 @@ -54,7 +54,7 @@ extern void varargs_simple(int, ...); // CHECK-NEXT: [[TMP22:%.*]] = load i8, ptr [[TMP21]], align 1 // CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds nuw [[STRUCT_ANON_0]], ptr [[T]], i32 0, i32 1 // CHECK-NEXT: [[TMP24:%.*]] = load i8, ptr [[TMP23]], align 1 -// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i8 [[TMP14]], i8 [[TMP16]], i8 [[TMP18]], i8 [[TMP20]], i32 noundef 0, i8 [[TMP22]], i8 [[TMP24]]) +// CHECK-NEXT: call void (i32, ...) @varargs_simple(i32 noundef 0, i8 [[TMP14]], i8 [[TMP16]], i8 [[TMP18]], i8 [[TMP20]], i32 noundef 0, i8 [[TMP22]], i8 [[TMP24]]) #[[ATTR3]] // CHECK-NEXT: ret void // void foo() { @@ -85,7 +85,7 @@ extern void varargs_complex(S, S, ...); // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S:%.*]], align 8 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[S]], ptr align 8 @__const.bar.s, i64 16, i1 false) -// CHECK-NEXT: call void (ptr, ptr, ...) @varargs_complex(ptr noundef byval([[STRUCT_S]]) align 8 [[S]], ptr noundef byval([[STRUCT_S]]) align 8 [[S]], i32 noundef 1, i64 noundef 1, double noundef 1.000000e+00) +// CHECK-NEXT: call void (ptr, ptr, ...) @varargs_complex(ptr noundef byval([[STRUCT_S]]) align 8 [[S]], ptr noundef byval([[STRUCT_S]]) align 8 [[S]], i32 noundef 1, i64 noundef 1, double noundef 1.000000e+00) #[[ATTR3]] // CHECK-NEXT: ret void // void bar() { diff --git a/clang/test/CodeGenCUDA/bf16.cu b/clang/test/CodeGenCUDA/bf16.cu index 3c443420dbd36..f794b83239f14 100644 --- a/clang/test/CodeGenCUDA/bf16.cu +++ b/clang/test/CodeGenCUDA/bf16.cu @@ -25,7 +25,7 @@ __device__ void test_arg(__bf16 *out, __bf16 in) { __device__ __bf16 test_ret( __bf16 in) { // CHECK: ld.param.b16 %[[R:rs[0-9]+]], [_Z8test_retDF16b_param_0]; return in; -// CHECK: st.param.b16 [func_retval0+0], %[[R]] +// CHECK: st.param.b16 [func_retval0], %[[R]] // CHECK: ret; } @@ -35,15 +35,15 @@ __device__ __bf16 external_func( __bf16 in); // CHECK: .param .align 2 .b8 _Z9test_callDF16b_param_0[2] __device__ __bf16 test_call( __bf16 in) { // CHECK: ld.param.b16 %[[R:rs[0-9]+]], [_Z9test_callDF16b_param_0]; -// CHECK: st.param.b16 [param0+0], %[[R]]; +// CHECK: st.param.b16 [param0], %[[R]]; // CHECK: .param .align 2 .b8 retval0[2]; // CHECK: call.uni (retval0), // CHECK-NEXT: _Z13external_funcDF16b, // CHECK-NEXT: ( // CHECK-NEXT: param0 // CHECK-NEXT ); -// CHECK: ld.param.b16 %[[RET:rs[0-9]+]], [retval0+0]; +// CHECK: ld.param.b16 %[[RET:rs[0-9]+]], [retval0]; return external_func(in); -// CHECK: st.param.b16 [func_retval0+0], %[[RET]] +// CHECK: st.param.b16 [func_retval0], %[[RET]] // CHECK: ret; } diff --git a/clang/test/CodeGenCUDA/device-init-fun.cu b/clang/test/CodeGenCUDA/device-init-fun.cu index 4f3119a2269c6..aaf5b1be72b84 100644 --- a/clang/test/CodeGenCUDA/device-init-fun.cu +++ b/clang/test/CodeGenCUDA/device-init-fun.cu @@ -4,11 +4,17 @@ // RUN: -fgpu-allow-device-init -x hip \ // RUN: -fno-threadsafe-statics -emit-llvm -o - %s \ // RUN: | FileCheck %s +// RUN: %clang_cc1 -triple spirv64-amd-amdhsa -fcuda-is-device -std=c++11 \ +// RUN: -fgpu-allow-device-init -x hip \ +// RUN: -fno-threadsafe-statics -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-SPIRV #include "Inputs/cuda.h" // CHECK: define internal amdgpu_kernel void @_GLOBAL__sub_I_device_init_fun.cu() #[[ATTR:[0-9]*]] // CHECK: attributes #[[ATTR]] = {{.*}}"device-init" +// CHECK-SPIRV: define internal spir_kernel void @_GLOBAL__sub_I_device_init_fun.cu(){{.*}} #[[ATTR:[0-9]*]] +// CHECK-SPIRV: attributes #[[ATTR]] = {{.*}}"device-init" __device__ void f(); diff --git a/clang/test/CodeGenCUDA/kernel-amdgcn.cu b/clang/test/CodeGenCUDA/kernel-amdgcn.cu index 48473b92ccff3..8b97166699099 100644 --- a/clang/test/CodeGenCUDA/kernel-amdgcn.cu +++ b/clang/test/CodeGenCUDA/kernel-amdgcn.cu @@ -1,31 +1,37 @@ // RUN: %clang_cc1 -triple amdgcn -fcuda-is-device -emit-llvm -x hip %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple spirv64-amd-amdhsa -fcuda-is-device -emit-llvm -x hip %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV #include "Inputs/cuda.h" // CHECK: define{{.*}} amdgpu_kernel void @_ZN1A6kernelEv +// CHECK-SPIRV: define{{.*}} spir_kernel void @_ZN1A6kernelEv class A { public: static __global__ void kernel(){} }; // CHECK: define{{.*}} void @_Z10non_kernelv +// CHECK-SPIRV: define{{.*}} void @_Z10non_kernelv __device__ void non_kernel(){} // CHECK: define{{.*}} amdgpu_kernel void @_Z6kerneli +// CHECK-SPIRV: define{{.*}} spir_kernel void @_Z6kerneli __global__ void kernel(int x) { non_kernel(); } // CHECK: define{{.*}} amdgpu_kernel void @_Z11EmptyKernelIvEvv +// CHECK-SPIRV: define{{.*}} spir_kernel void @_Z11EmptyKernelIvEvv template __global__ void EmptyKernel(void) {} struct Dummy { /// Type definition of the EmptyKernel kernel entry point typedef void (*EmptyKernelPtr)(); - EmptyKernelPtr Empty() { return EmptyKernel; } + EmptyKernelPtr Empty() { return EmptyKernel; } }; // CHECK: define{{.*}} amdgpu_kernel void @_Z15template_kernelI1AEvT_{{.*}} #[[ATTR:[0-9][0-9]*]] +// CHECK-SPIRV: define{{.*}} spir_kernel void @_Z15template_kernelI1AEvT_{{.*}} #[[ATTR:[0-9][0-9]*]] template __global__ void template_kernel(T x) {} diff --git a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp index d53e5c0520e6c..13a0226ce5415 100644 --- a/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp +++ b/clang/test/CodeGenCXX/attr-target-clones-riscv.cpp @@ -16,9 +16,8 @@ __attribute__((target_clones("default", "arch=+zvkt"))) int foo6(void) { return __attribute__((target_clones("default", "arch=+zbb", "arch=+zba", "arch=+zbb,+zba"))) int foo7(void) { return 2; } __attribute__((target_clones("default", "arch=+zbb;priority=2", "arch=+zba;priority=1", "arch=+zbb,+zba;priority=3"))) int foo8(void) { return 2; } __attribute__((target_clones("default", "arch=+zbb;priority=1", "priority=2;arch=+zba", "priority=3;arch=+zbb,+zba"))) int foo9(void) { return 2; } -__attribute__((target_clones("default", "arch=+zbb;priority=-1", "priority=-2;arch=+zba", "priority=3;arch=+zbb,+zba"))) int foo10(void) { return 2; } -int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() + foo8() + foo9() + foo10(); } +int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() + foo8() + foo9(); } //. // CHECK: @__riscv_feature_bits = external dso_local global { i32, [2 x i64] } @@ -31,7 +30,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() + // CHECK: @_Z4foo7v.ifunc = weak_odr alias i32 (), ptr @_Z4foo7v // CHECK: @_Z4foo8v.ifunc = weak_odr alias i32 (), ptr @_Z4foo8v // CHECK: @_Z4foo9v.ifunc = weak_odr alias i32 (), ptr @_Z4foo9v -// CHECK: @_Z5foo10v.ifunc = weak_odr alias i32 (), ptr @_Z5foo10v // CHECK: @_Z4foo1v = weak_odr ifunc i32 (), ptr @_Z4foo1v.resolver // CHECK: @_Z4foo2v = weak_odr ifunc i32 (), ptr @_Z4foo2v.resolver // CHECK: @_Z4foo3v = weak_odr ifunc i32 (), ptr @_Z4foo3v.resolver @@ -41,7 +39,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() + // CHECK: @_Z4foo7v = weak_odr ifunc i32 (), ptr @_Z4foo7v.resolver // CHECK: @_Z4foo8v = weak_odr ifunc i32 (), ptr @_Z4foo8v.resolver // CHECK: @_Z4foo9v = weak_odr ifunc i32 (), ptr @_Z4foo9v.resolver -// CHECK: @_Z5foo10v = weak_odr ifunc i32 (), ptr @_Z5foo10v.resolver //. // CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo1v.default( // CHECK-SAME: ) #[[ATTR0:[0-9]+]] { @@ -346,57 +343,6 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() + // CHECK-NEXT: ret ptr @_Z4foo9v.default // // -// CHECK-LABEL: define dso_local noundef signext i32 @_Z5foo10v.default( -// CHECK-SAME: ) #[[ATTR0]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: define dso_local noundef signext i32 @_Z5foo10v._zbb( -// CHECK-SAME: ) #[[ATTR1]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: define dso_local noundef signext i32 @_Z5foo10v._zba( -// CHECK-SAME: ) #[[ATTR5]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: define dso_local noundef signext i32 @_Z5foo10v._zba_zbb( -// CHECK-SAME: ) #[[ATTR6]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: define weak_odr ptr @_Z5foo10v.resolver() comdat { -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: call void @__init_riscv_feature_bits(ptr null) -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 402653184 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184 -// CHECK-NEXT: br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] -// CHECK: resolver_return: -// CHECK-NEXT: ret ptr @_Z5foo10v._zba_zbb -// CHECK: resolver_else: -// CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP4:%.*]] = and i64 [[TMP3]], 268435456 -// CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 268435456 -// CHECK-NEXT: br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] -// CHECK: resolver_return1: -// CHECK-NEXT: ret ptr @_Z5foo10v._zbb -// CHECK: resolver_else2: -// CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], 134217728 -// CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 134217728 -// CHECK-NEXT: br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] -// CHECK: resolver_return3: -// CHECK-NEXT: ret ptr @_Z5foo10v._zba -// CHECK: resolver_else4: -// CHECK-NEXT: ret ptr @_Z5foo10v.default -// -// // CHECK-LABEL: define dso_local noundef signext i32 @_Z3barv( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: entry: @@ -417,9 +363,7 @@ int bar() { return foo1() + foo2() + foo3() + foo4() + foo5()+ foo6() + foo7() + // CHECK-NEXT: [[ADD13:%.*]] = add nsw i32 [[ADD11]], [[CALL12]] // CHECK-NEXT: [[CALL14:%.*]] = call noundef signext i32 @_Z4foo9v() // CHECK-NEXT: [[ADD15:%.*]] = add nsw i32 [[ADD13]], [[CALL14]] -// CHECK-NEXT: [[CALL16:%.*]] = call noundef signext i32 @_Z5foo10v() -// CHECK-NEXT: [[ADD17:%.*]] = add nsw i32 [[ADD15]], [[CALL16]] -// CHECK-NEXT: ret i32 [[ADD17]] +// CHECK-NEXT: ret i32 [[ADD15]] // //. // CHECK: attributes #[[ATTR0]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+m,+zmmul" } diff --git a/clang/test/CodeGenCXX/attr-target-version-riscv.cpp b/clang/test/CodeGenCXX/attr-target-version-riscv.cpp index 9078f6541b3dc..51fae0902ab76 100644 --- a/clang/test/CodeGenCXX/attr-target-version-riscv.cpp +++ b/clang/test/CodeGenCXX/attr-target-version-riscv.cpp @@ -32,11 +32,6 @@ __attribute__((target_version("arch=+zbb;priority=9"))) int foo7(void) { return __attribute__((target_version("arch=+zbb,+zba;priority=10"))) int foo7(void) { return 1; } __attribute__((target_version("default"))) int foo7(void) { return 1; } -__attribute__((target_version("priority=-1;arch=+zba"))) int foo8(void) { return 1; } -__attribute__((target_version("arch=+zbb;priority=-2"))) int foo8(void) { return 1; } -__attribute__((target_version("arch=+zbb,+zba;priority=3"))) int foo8(void) { return 1; } -__attribute__((target_version("default"))) int foo8(void) { return 1; } - int bar() { return foo1() + foo2() + foo3(); } //. // CHECK: @__riscv_feature_bits = external dso_local global { i32, [2 x i64] } @@ -47,7 +42,6 @@ int bar() { return foo1() + foo2() + foo3(); } // CHECK: @_Z4foo5v = weak_odr ifunc i32 (), ptr @_Z4foo5v.resolver // CHECK: @_Z4foo6v = weak_odr ifunc i32 (), ptr @_Z4foo6v.resolver // CHECK: @_Z4foo7v = weak_odr ifunc i32 (), ptr @_Z4foo7v.resolver -// CHECK: @_Z4foo8v = weak_odr ifunc i32 (), ptr @_Z4foo8v.resolver //. // CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo1v._v( // CHECK-SAME: ) #[[ATTR0:[0-9]+]] { @@ -193,30 +187,6 @@ int bar() { return foo1() + foo2() + foo3(); } // CHECK-NEXT: ret i32 1 // // -// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo8v._zba( -// CHECK-SAME: ) #[[ATTR4]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// -// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo8v._zbb( -// CHECK-SAME: ) #[[ATTR2]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// -// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo8v._zba_zbb( -// CHECK-SAME: ) #[[ATTR5]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// -// CHECK-LABEL: define dso_local noundef signext i32 @_Z4foo8v.default( -// CHECK-SAME: ) #[[ATTR1]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// // CHECK-LABEL: define dso_local noundef signext i32 @_Z3barv( // CHECK-SAME: ) #[[ATTR1]] { // CHECK-NEXT: entry: @@ -388,33 +358,6 @@ int bar() { return foo1() + foo2() + foo3(); } // CHECK: resolver_else4: // CHECK-NEXT: ret ptr @_Z4foo7v.default // -// -// CHECK-LABEL: define weak_odr ptr @_Z4foo8v.resolver() comdat { -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: call void @__init_riscv_feature_bits(ptr null) -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 402653184 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 402653184 -// CHECK-NEXT: br i1 [[TMP2]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] -// CHECK: resolver_return: -// CHECK-NEXT: ret ptr @_Z4foo8v._zba_zbb -// CHECK: resolver_else: -// CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP4:%.*]] = and i64 [[TMP3]], 134217728 -// CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[TMP4]], 134217728 -// CHECK-NEXT: br i1 [[TMP5]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] -// CHECK: resolver_return1: -// CHECK-NEXT: ret ptr @_Z4foo8v._zba -// CHECK: resolver_else2: -// CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [2 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8 -// CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], 268435456 -// CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 268435456 -// CHECK-NEXT: br i1 [[TMP8]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] -// CHECK: resolver_return3: -// CHECK-NEXT: ret ptr @_Z4foo8v._zbb -// CHECK: resolver_else4: -// CHECK-NEXT: ret ptr @_Z4foo8v.default -// //. // CHECK: attributes #[[ATTR0]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+d,+f,+i,+m,+v,+zicsr,+zmmul,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b" } // CHECK: attributes #[[ATTR1]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+64bit,+i,+m,+zmmul" } diff --git a/clang/test/CodeGenCXX/flexible-array-init.cpp b/clang/test/CodeGenCXX/flexible-array-init.cpp index 26854b1723c4c..a711e7102989e 100644 --- a/clang/test/CodeGenCXX/flexible-array-init.cpp +++ b/clang/test/CodeGenCXX/flexible-array-init.cpp @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-only -verify -DFAIL1 %s // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-only -verify -DFAIL2 %s // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-only -verify -DFAIL3 %s +// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-only -verify -DFAIL4 %s struct A { int x; int y[]; }; A a = { 1, 7, 11 }; @@ -23,6 +24,11 @@ void g() { struct B { int x; char y; char z[]; }; B e = {f(), f(), f(), f()}; // expected-error {{cannot compile this flexible array initializer yet}} #endif +#ifdef FAIL4 +union { char a[]; } z = {}; +union { char a[]; } z0 = {z.a[0]}; // expected-error {{cannot compile this flexible array initializer yet}} +char keep() { return z0.a[0]; } +#endif namespace zero_initializer { A a0{0, 0}, a1{0, {0, 0}}; diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffer-annotations.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffer-annotations.hlsl index 81c5837d8f207..4d3d4908c396e 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffer-annotations.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffer-annotations.hlsl @@ -1,22 +1,22 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s - -StructuredBuffer Buffer1; -StructuredBuffer > BufferArray[4]; - -StructuredBuffer Buffer2 : register(u3); -StructuredBuffer > BufferArray2[4] : register(u4); - -StructuredBuffer Buffer3 : register(u3, space1); -StructuredBuffer > BufferArray3[4] : register(u4, space1); - -[numthreads(1,1,1)] -void main() { -} - -// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]} -// CHECK-DAG: ![[Single]] = !{ptr @Buffer1, i32 10, i32 9, i1 false, i32 -1, i32 0} -// CHECK-DAG: ![[Array]] = !{ptr @BufferArray, i32 10, i32 9, i1 false, i32 -1, i32 0} -// CHECK-DAG: ![[SingleAllocated]] = !{ptr @Buffer2, i32 10, i32 9, i1 false, i32 3, i32 0} -// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @BufferArray2, i32 10, i32 9, i1 false, i32 4, i32 0} -// CHECK-DAG: ![[SingleSpace]] = !{ptr @Buffer3, i32 10, i32 9, i1 false, i32 3, i32 1} -// CHECK-DAG: ![[ArraySpace]] = !{ptr @BufferArray3, i32 10, i32 9, i1 false, i32 4, i32 1} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +StructuredBuffer Buffer1; +StructuredBuffer > BufferArray[4]; + +StructuredBuffer Buffer2 : register(u3); +StructuredBuffer > BufferArray2[4] : register(u4); + +StructuredBuffer Buffer3 : register(u3, space1); +StructuredBuffer > BufferArray3[4] : register(u4, space1); + +[numthreads(1,1,1)] +void main() { +} + +// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]} +// CHECK-DAG: ![[Single]] = !{ptr @Buffer1, i32 10, i32 9, i1 false, i32 -1, i32 0} +// CHECK-DAG: ![[Array]] = !{ptr @BufferArray, i32 10, i32 9, i1 false, i32 -1, i32 0} +// CHECK-DAG: ![[SingleAllocated]] = !{ptr @Buffer2, i32 10, i32 9, i1 false, i32 3, i32 0} +// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @BufferArray2, i32 10, i32 9, i1 false, i32 4, i32 0} +// CHECK-DAG: ![[SingleSpace]] = !{ptr @Buffer3, i32 10, i32 9, i1 false, i32 3, i32 1} +// CHECK-DAG: ![[ArraySpace]] = !{ptr @BufferArray3, i32 10, i32 9, i1 false, i32 4, i32 1} diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffer-elementtype.hlsl index 435a904327a26..a99c7f98a1afb 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffer-elementtype.hlsl @@ -1,70 +1,70 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s - -// NOTE: The number in type name and whether the struct is packed or not will mostly -// likely change once subscript operators are properly implemented (llvm/llvm-project#95956) -// and theinterim field of the contained type is removed. - -// CHECK: %"class.hlsl::StructuredBuffer" = type <{ target("dx.RawBuffer", i16, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.0" = type <{ target("dx.RawBuffer", i16, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.3" = type { target("dx.RawBuffer", i32, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.5" = type { target("dx.RawBuffer", i64, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.6" = type <{ target("dx.RawBuffer", half, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.8" = type { target("dx.RawBuffer", float, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.9" = type { target("dx.RawBuffer", double, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.10" = type { target("dx.RawBuffer", <4 x i16>, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.11" = type { target("dx.RawBuffer", <3 x i32>, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.12" = type { target("dx.RawBuffer", <2 x half>, 1, 0) -// CHECK: %"class.hlsl::StructuredBuffer.13" = type { target("dx.RawBuffer", <3 x float>, 1, 0) - -StructuredBuffer BufI16; -StructuredBuffer BufU16; -StructuredBuffer BufI32; -StructuredBuffer BufU32; -StructuredBuffer BufI64; -StructuredBuffer BufU64; -StructuredBuffer BufF16; -StructuredBuffer BufF32; -StructuredBuffer BufF64; -StructuredBuffer< vector > BufI16x4; -StructuredBuffer< vector > BufU32x3; -StructuredBuffer BufF16x2; -StructuredBuffer BufF32x3; -// TODO: StructuredBuffer BufSNormF16; -> 11 -// TODO: StructuredBuffer BufUNormF16; -> 12 -// TODO: StructuredBuffer BufSNormF32; -> 13 -// TODO: StructuredBuffer BufUNormF32; -> 14 -// TODO: StructuredBuffer BufSNormF64; -> 15 -// TODO: StructuredBuffer BufUNormF64; -> 16 - -[numthreads(1,1,1)] -void main(int GI : SV_GroupIndex) { - BufI16[GI] = 0; - BufU16[GI] = 0; - BufI32[GI] = 0; - BufU32[GI] = 0; - BufI64[GI] = 0; - BufU64[GI] = 0; - BufF16[GI] = 0; - BufF32[GI] = 0; - BufF64[GI] = 0; - BufI16x4[GI] = 0; - BufU32x3[GI] = 0; - BufF16x2[GI] = 0; - BufF32x3[GI] = 0; -} - -// CHECK: !{{[0-9]+}} = !{ptr @BufI16, i32 10, i32 2, -// CHECK: !{{[0-9]+}} = !{ptr @BufU16, i32 10, i32 3, -// CHECK: !{{[0-9]+}} = !{ptr @BufI32, i32 10, i32 4, -// CHECK: !{{[0-9]+}} = !{ptr @BufU32, i32 10, i32 5, -// CHECK: !{{[0-9]+}} = !{ptr @BufI64, i32 10, i32 6, -// CHECK: !{{[0-9]+}} = !{ptr @BufU64, i32 10, i32 7, -// CHECK: !{{[0-9]+}} = !{ptr @BufF16, i32 10, i32 8, -// CHECK: !{{[0-9]+}} = !{ptr @BufF32, i32 10, i32 9, -// CHECK: !{{[0-9]+}} = !{ptr @BufF64, i32 10, i32 10, -// CHECK: !{{[0-9]+}} = !{ptr @BufI16x4, i32 10, i32 2, -// CHECK: !{{[0-9]+}} = !{ptr @BufU32x3, i32 10, i32 5, -// CHECK: !{{[0-9]+}} = !{ptr @BufF16x2, i32 10, i32 8, -// CHECK: !{{[0-9]+}} = !{ptr @BufF32x3, i32 10, i32 9, +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s + +// NOTE: The number in type name and whether the struct is packed or not will mostly +// likely change once subscript operators are properly implemented (llvm/llvm-project#95956) +// and theinterim field of the contained type is removed. + +// CHECK: %"class.hlsl::StructuredBuffer" = type <{ target("dx.RawBuffer", i16, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.0" = type <{ target("dx.RawBuffer", i16, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.3" = type { target("dx.RawBuffer", i32, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.5" = type { target("dx.RawBuffer", i64, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.6" = type <{ target("dx.RawBuffer", half, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.8" = type { target("dx.RawBuffer", float, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.9" = type { target("dx.RawBuffer", double, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.10" = type { target("dx.RawBuffer", <4 x i16>, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.11" = type { target("dx.RawBuffer", <3 x i32>, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.12" = type { target("dx.RawBuffer", <2 x half>, 1, 0) +// CHECK: %"class.hlsl::StructuredBuffer.13" = type { target("dx.RawBuffer", <3 x float>, 1, 0) + +StructuredBuffer BufI16; +StructuredBuffer BufU16; +StructuredBuffer BufI32; +StructuredBuffer BufU32; +StructuredBuffer BufI64; +StructuredBuffer BufU64; +StructuredBuffer BufF16; +StructuredBuffer BufF32; +StructuredBuffer BufF64; +StructuredBuffer< vector > BufI16x4; +StructuredBuffer< vector > BufU32x3; +StructuredBuffer BufF16x2; +StructuredBuffer BufF32x3; +// TODO: StructuredBuffer BufSNormF16; -> 11 +// TODO: StructuredBuffer BufUNormF16; -> 12 +// TODO: StructuredBuffer BufSNormF32; -> 13 +// TODO: StructuredBuffer BufUNormF32; -> 14 +// TODO: StructuredBuffer BufSNormF64; -> 15 +// TODO: StructuredBuffer BufUNormF64; -> 16 + +[numthreads(1,1,1)] +void main(int GI : SV_GroupIndex) { + BufI16[GI] = 0; + BufU16[GI] = 0; + BufI32[GI] = 0; + BufU32[GI] = 0; + BufI64[GI] = 0; + BufU64[GI] = 0; + BufF16[GI] = 0; + BufF32[GI] = 0; + BufF64[GI] = 0; + BufI16x4[GI] = 0; + BufU32x3[GI] = 0; + BufF16x2[GI] = 0; + BufF32x3[GI] = 0; +} + +// CHECK: !{{[0-9]+}} = !{ptr @BufI16, i32 10, i32 2, +// CHECK: !{{[0-9]+}} = !{ptr @BufU16, i32 10, i32 3, +// CHECK: !{{[0-9]+}} = !{ptr @BufI32, i32 10, i32 4, +// CHECK: !{{[0-9]+}} = !{ptr @BufU32, i32 10, i32 5, +// CHECK: !{{[0-9]+}} = !{ptr @BufI64, i32 10, i32 6, +// CHECK: !{{[0-9]+}} = !{ptr @BufU64, i32 10, i32 7, +// CHECK: !{{[0-9]+}} = !{ptr @BufF16, i32 10, i32 8, +// CHECK: !{{[0-9]+}} = !{ptr @BufF32, i32 10, i32 9, +// CHECK: !{{[0-9]+}} = !{ptr @BufF64, i32 10, i32 10, +// CHECK: !{{[0-9]+}} = !{ptr @BufI16x4, i32 10, i32 2, +// CHECK: !{{[0-9]+}} = !{ptr @BufU32x3, i32 10, i32 5, +// CHECK: !{{[0-9]+}} = !{ptr @BufF16x2, i32 10, i32 8, +// CHECK: !{{[0-9]+}} = !{ptr @BufF32x3, i32 10, i32 9, diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl index 89bde9236288f..155749ec4f94a 100644 --- a/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl +++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl @@ -1,17 +1,17 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s - -StructuredBuffer In; -StructuredBuffer Out; - -[numthreads(1,1,1)] -void main(unsigned GI : SV_GroupIndex) { - Out[GI] = In[GI]; -} - -// Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy -// and confusing to follow so the match here is pretty weak. - -// CHECK: define void @main() -// Verify inlining leaves only calls to "llvm." intrinsics -// CHECK-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}} -// CHECK: ret void +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s + +StructuredBuffer In; +StructuredBuffer Out; + +[numthreads(1,1,1)] +void main(unsigned GI : SV_GroupIndex) { + Out[GI] = In[GI]; +} + +// Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy +// and confusing to follow so the match here is pretty weak. + +// CHECK: define void @main() +// Verify inlining leaves only calls to "llvm." intrinsics +// CHECK-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}} +// CHECK: ret void diff --git a/clang/test/CodeGenHLSL/builtins/atan2.hlsl b/clang/test/CodeGenHLSL/builtins/atan2.hlsl index ada269db2f00d..40796052e608f 100644 --- a/clang/test/CodeGenHLSL/builtins/atan2.hlsl +++ b/clang/test/CodeGenHLSL/builtins/atan2.hlsl @@ -1,59 +1,59 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF - -// CHECK-LABEL: test_atan2_half -// NATIVE_HALF: call half @llvm.atan2.f16 -// NO_HALF: call float @llvm.atan2.f32 -half test_atan2_half (half p0, half p1) { - return atan2(p0, p1); -} - -// CHECK-LABEL: test_atan2_half2 -// NATIVE_HALF: call <2 x half> @llvm.atan2.v2f16 -// NO_HALF: call <2 x float> @llvm.atan2.v2f32 -half2 test_atan2_half2 (half2 p0, half2 p1) { - return atan2(p0, p1); -} - -// CHECK-LABEL: test_atan2_half3 -// NATIVE_HALF: call <3 x half> @llvm.atan2.v3f16 -// NO_HALF: call <3 x float> @llvm.atan2.v3f32 -half3 test_atan2_half3 (half3 p0, half3 p1) { - return atan2(p0, p1); -} - -// CHECK-LABEL: test_atan2_half4 -// NATIVE_HALF: call <4 x half> @llvm.atan2.v4f16 -// NO_HALF: call <4 x float> @llvm.atan2.v4f32 -half4 test_atan2_half4 (half4 p0, half4 p1) { - return atan2(p0, p1); -} - -// CHECK-LABEL: test_atan2_float -// CHECK: call float @llvm.atan2.f32 -float test_atan2_float (float p0, float p1) { - return atan2(p0, p1); -} - -// CHECK-LABEL: test_atan2_float2 -// CHECK: call <2 x float> @llvm.atan2.v2f32 -float2 test_atan2_float2 (float2 p0, float2 p1) { - return atan2(p0, p1); -} - -// CHECK-LABEL: test_atan2_float3 -// CHECK: call <3 x float> @llvm.atan2.v3f32 -float3 test_atan2_float3 (float3 p0, float3 p1) { - return atan2(p0, p1); -} - -// CHECK-LABEL: test_atan2_float4 -// CHECK: call <4 x float> @llvm.atan2.v4f32 -float4 test_atan2_float4 (float4 p0, float4 p1) { - return atan2(p0, p1); -} +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF + +// CHECK-LABEL: test_atan2_half +// NATIVE_HALF: call half @llvm.atan2.f16 +// NO_HALF: call float @llvm.atan2.f32 +half test_atan2_half (half p0, half p1) { + return atan2(p0, p1); +} + +// CHECK-LABEL: test_atan2_half2 +// NATIVE_HALF: call <2 x half> @llvm.atan2.v2f16 +// NO_HALF: call <2 x float> @llvm.atan2.v2f32 +half2 test_atan2_half2 (half2 p0, half2 p1) { + return atan2(p0, p1); +} + +// CHECK-LABEL: test_atan2_half3 +// NATIVE_HALF: call <3 x half> @llvm.atan2.v3f16 +// NO_HALF: call <3 x float> @llvm.atan2.v3f32 +half3 test_atan2_half3 (half3 p0, half3 p1) { + return atan2(p0, p1); +} + +// CHECK-LABEL: test_atan2_half4 +// NATIVE_HALF: call <4 x half> @llvm.atan2.v4f16 +// NO_HALF: call <4 x float> @llvm.atan2.v4f32 +half4 test_atan2_half4 (half4 p0, half4 p1) { + return atan2(p0, p1); +} + +// CHECK-LABEL: test_atan2_float +// CHECK: call float @llvm.atan2.f32 +float test_atan2_float (float p0, float p1) { + return atan2(p0, p1); +} + +// CHECK-LABEL: test_atan2_float2 +// CHECK: call <2 x float> @llvm.atan2.v2f32 +float2 test_atan2_float2 (float2 p0, float2 p1) { + return atan2(p0, p1); +} + +// CHECK-LABEL: test_atan2_float3 +// CHECK: call <3 x float> @llvm.atan2.v3f32 +float3 test_atan2_float3 (float3 p0, float3 p1) { + return atan2(p0, p1); +} + +// CHECK-LABEL: test_atan2_float4 +// CHECK: call <4 x float> @llvm.atan2.v4f32 +float4 test_atan2_float4 (float4 p0, float4 p1) { + return atan2(p0, p1); +} diff --git a/clang/test/CodeGenHLSL/builtins/cross.hlsl b/clang/test/CodeGenHLSL/builtins/cross.hlsl index eba710c905bf4..514e57d36b201 100644 --- a/clang/test/CodeGenHLSL/builtins/cross.hlsl +++ b/clang/test/CodeGenHLSL/builtins/cross.hlsl @@ -1,37 +1,37 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF \ -// RUN: -DFNATTRS=noundef -DTARGET=dx -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ -// RUN: -DFNATTRS=noundef -DTARGET=dx -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF \ -// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ -// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv - -// NATIVE_HALF: define [[FNATTRS]] <3 x half> @ -// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].cross.v3f16(<3 x half> -// NATIVE_HALF: ret <3 x half> %hlsl.cross -// NO_HALF: define [[FNATTRS]] <3 x float> @ -// NO_HALF: call <3 x float> @llvm.[[TARGET]].cross.v3f32(<3 x float> -// NO_HALF: ret <3 x float> %hlsl.cross -half3 test_cross_half3(half3 p0, half3 p1) -{ - return cross(p0, p1); -} - -// CHECK: define [[FNATTRS]] <3 x float> @ -// CHECK: %hlsl.cross = call <3 x float> @llvm.[[TARGET]].cross.v3f32( -// CHECK: ret <3 x float> %hlsl.cross -float3 test_cross_float3(float3 p0, float3 p1) -{ - return cross(p0, p1); -} +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF \ +// RUN: -DFNATTRS=noundef -DTARGET=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ +// RUN: -DFNATTRS=noundef -DTARGET=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF \ +// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ +// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv + +// NATIVE_HALF: define [[FNATTRS]] <3 x half> @ +// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].cross.v3f16(<3 x half> +// NATIVE_HALF: ret <3 x half> %hlsl.cross +// NO_HALF: define [[FNATTRS]] <3 x float> @ +// NO_HALF: call <3 x float> @llvm.[[TARGET]].cross.v3f32(<3 x float> +// NO_HALF: ret <3 x float> %hlsl.cross +half3 test_cross_half3(half3 p0, half3 p1) +{ + return cross(p0, p1); +} + +// CHECK: define [[FNATTRS]] <3 x float> @ +// CHECK: %hlsl.cross = call <3 x float> @llvm.[[TARGET]].cross.v3f32( +// CHECK: ret <3 x float> %hlsl.cross +float3 test_cross_float3(float3 p0, float3 p1) +{ + return cross(p0, p1); +} diff --git a/clang/test/CodeGenHLSL/builtins/length.hlsl b/clang/test/CodeGenHLSL/builtins/length.hlsl index 9b0293c218a5d..1c23b0df04df9 100644 --- a/clang/test/CodeGenHLSL/builtins/length.hlsl +++ b/clang/test/CodeGenHLSL/builtins/length.hlsl @@ -1,73 +1,73 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF - -// NATIVE_HALF: define noundef half @ -// NATIVE_HALF: call half @llvm.fabs.f16(half -// NO_HALF: call float @llvm.fabs.f32(float -// NATIVE_HALF: ret half -// NO_HALF: ret float -half test_length_half(half p0) -{ - return length(p0); -} -// NATIVE_HALF: define noundef half @ -// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v2f16 -// NO_HALF: %hlsl.length = call float @llvm.dx.length.v2f32( -// NATIVE_HALF: ret half %hlsl.length -// NO_HALF: ret float %hlsl.length -half test_length_half2(half2 p0) -{ - return length(p0); -} -// NATIVE_HALF: define noundef half @ -// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v3f16 -// NO_HALF: %hlsl.length = call float @llvm.dx.length.v3f32( -// NATIVE_HALF: ret half %hlsl.length -// NO_HALF: ret float %hlsl.length -half test_length_half3(half3 p0) -{ - return length(p0); -} -// NATIVE_HALF: define noundef half @ -// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v4f16 -// NO_HALF: %hlsl.length = call float @llvm.dx.length.v4f32( -// NATIVE_HALF: ret half %hlsl.length -// NO_HALF: ret float %hlsl.length -half test_length_half4(half4 p0) -{ - return length(p0); -} - -// CHECK: define noundef float @ -// CHECK: call float @llvm.fabs.f32(float -// CHECK: ret float -float test_length_float(float p0) -{ - return length(p0); -} -// CHECK: define noundef float @ -// CHECK: %hlsl.length = call float @llvm.dx.length.v2f32( -// CHECK: ret float %hlsl.length -float test_length_float2(float2 p0) -{ - return length(p0); -} -// CHECK: define noundef float @ -// CHECK: %hlsl.length = call float @llvm.dx.length.v3f32( -// CHECK: ret float %hlsl.length -float test_length_float3(float3 p0) -{ - return length(p0); -} -// CHECK: define noundef float @ -// CHECK: %hlsl.length = call float @llvm.dx.length.v4f32( -// CHECK: ret float %hlsl.length -float test_length_float4(float4 p0) -{ - return length(p0); -} +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF + +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: call half @llvm.fabs.f16(half +// NO_HALF: call float @llvm.fabs.f32(float +// NATIVE_HALF: ret half +// NO_HALF: ret float +half test_length_half(half p0) +{ + return length(p0); +} +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v2f16 +// NO_HALF: %hlsl.length = call float @llvm.dx.length.v2f32( +// NATIVE_HALF: ret half %hlsl.length +// NO_HALF: ret float %hlsl.length +half test_length_half2(half2 p0) +{ + return length(p0); +} +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v3f16 +// NO_HALF: %hlsl.length = call float @llvm.dx.length.v3f32( +// NATIVE_HALF: ret half %hlsl.length +// NO_HALF: ret float %hlsl.length +half test_length_half3(half3 p0) +{ + return length(p0); +} +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v4f16 +// NO_HALF: %hlsl.length = call float @llvm.dx.length.v4f32( +// NATIVE_HALF: ret half %hlsl.length +// NO_HALF: ret float %hlsl.length +half test_length_half4(half4 p0) +{ + return length(p0); +} + +// CHECK: define noundef float @ +// CHECK: call float @llvm.fabs.f32(float +// CHECK: ret float +float test_length_float(float p0) +{ + return length(p0); +} +// CHECK: define noundef float @ +// CHECK: %hlsl.length = call float @llvm.dx.length.v2f32( +// CHECK: ret float %hlsl.length +float test_length_float2(float2 p0) +{ + return length(p0); +} +// CHECK: define noundef float @ +// CHECK: %hlsl.length = call float @llvm.dx.length.v3f32( +// CHECK: ret float %hlsl.length +float test_length_float3(float3 p0) +{ + return length(p0); +} +// CHECK: define noundef float @ +// CHECK: %hlsl.length = call float @llvm.dx.length.v4f32( +// CHECK: ret float %hlsl.length +float test_length_float4(float4 p0) +{ + return length(p0); +} diff --git a/clang/test/CodeGenHLSL/builtins/normalize.hlsl b/clang/test/CodeGenHLSL/builtins/normalize.hlsl index d14e7c70ce065..83ad607c14a60 100644 --- a/clang/test/CodeGenHLSL/builtins/normalize.hlsl +++ b/clang/test/CodeGenHLSL/builtins/normalize.hlsl @@ -1,85 +1,85 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF \ -// RUN: -DFNATTRS=noundef -DTARGET=dx -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ -// RUN: -DFNATTRS=noundef -DTARGET=dx -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF \ -// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ -// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv - -// NATIVE_HALF: define [[FNATTRS]] half @ -// NATIVE_HALF: call half @llvm.[[TARGET]].normalize.f16(half -// NO_HALF: call float @llvm.[[TARGET]].normalize.f32(float -// NATIVE_HALF: ret half -// NO_HALF: ret float -half test_normalize_half(half p0) -{ - return normalize(p0); -} -// NATIVE_HALF: define [[FNATTRS]] <2 x half> @ -// NATIVE_HALF: call <2 x half> @llvm.[[TARGET]].normalize.v2f16(<2 x half> -// NO_HALF: call <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> -// NATIVE_HALF: ret <2 x half> %hlsl.normalize -// NO_HALF: ret <2 x float> %hlsl.normalize -half2 test_normalize_half2(half2 p0) -{ - return normalize(p0); -} -// NATIVE_HALF: define [[FNATTRS]] <3 x half> @ -// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].normalize.v3f16(<3 x half> -// NO_HALF: call <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float> -// NATIVE_HALF: ret <3 x half> %hlsl.normalize -// NO_HALF: ret <3 x float> %hlsl.normalize -half3 test_normalize_half3(half3 p0) -{ - return normalize(p0); -} -// NATIVE_HALF: define [[FNATTRS]] <4 x half> @ -// NATIVE_HALF: call <4 x half> @llvm.[[TARGET]].normalize.v4f16(<4 x half> -// NO_HALF: call <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float> -// NATIVE_HALF: ret <4 x half> %hlsl.normalize -// NO_HALF: ret <4 x float> %hlsl.normalize -half4 test_normalize_half4(half4 p0) -{ - return normalize(p0); -} - -// CHECK: define [[FNATTRS]] float @ -// CHECK: call float @llvm.[[TARGET]].normalize.f32(float -// CHECK: ret float -float test_normalize_float(float p0) -{ - return normalize(p0); -} -// CHECK: define [[FNATTRS]] <2 x float> @ -// CHECK: %hlsl.normalize = call <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> - -// CHECK: ret <2 x float> %hlsl.normalize -float2 test_normalize_float2(float2 p0) -{ - return normalize(p0); -} -// CHECK: define [[FNATTRS]] <3 x float> @ -// CHECK: %hlsl.normalize = call <3 x float> @llvm.[[TARGET]].normalize.v3f32( -// CHECK: ret <3 x float> %hlsl.normalize -float3 test_normalize_float3(float3 p0) -{ - return normalize(p0); -} -// CHECK: define [[FNATTRS]] <4 x float> @ -// CHECK: %hlsl.normalize = call <4 x float> @llvm.[[TARGET]].normalize.v4f32( -// CHECK: ret <4 x float> %hlsl.normalize -float4 test_length_float4(float4 p0) -{ - return normalize(p0); -} +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF \ +// RUN: -DFNATTRS=noundef -DTARGET=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ +// RUN: -DFNATTRS=noundef -DTARGET=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF \ +// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ +// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv + +// NATIVE_HALF: define [[FNATTRS]] half @ +// NATIVE_HALF: call half @llvm.[[TARGET]].normalize.f16(half +// NO_HALF: call float @llvm.[[TARGET]].normalize.f32(float +// NATIVE_HALF: ret half +// NO_HALF: ret float +half test_normalize_half(half p0) +{ + return normalize(p0); +} +// NATIVE_HALF: define [[FNATTRS]] <2 x half> @ +// NATIVE_HALF: call <2 x half> @llvm.[[TARGET]].normalize.v2f16(<2 x half> +// NO_HALF: call <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> +// NATIVE_HALF: ret <2 x half> %hlsl.normalize +// NO_HALF: ret <2 x float> %hlsl.normalize +half2 test_normalize_half2(half2 p0) +{ + return normalize(p0); +} +// NATIVE_HALF: define [[FNATTRS]] <3 x half> @ +// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].normalize.v3f16(<3 x half> +// NO_HALF: call <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float> +// NATIVE_HALF: ret <3 x half> %hlsl.normalize +// NO_HALF: ret <3 x float> %hlsl.normalize +half3 test_normalize_half3(half3 p0) +{ + return normalize(p0); +} +// NATIVE_HALF: define [[FNATTRS]] <4 x half> @ +// NATIVE_HALF: call <4 x half> @llvm.[[TARGET]].normalize.v4f16(<4 x half> +// NO_HALF: call <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float> +// NATIVE_HALF: ret <4 x half> %hlsl.normalize +// NO_HALF: ret <4 x float> %hlsl.normalize +half4 test_normalize_half4(half4 p0) +{ + return normalize(p0); +} + +// CHECK: define [[FNATTRS]] float @ +// CHECK: call float @llvm.[[TARGET]].normalize.f32(float +// CHECK: ret float +float test_normalize_float(float p0) +{ + return normalize(p0); +} +// CHECK: define [[FNATTRS]] <2 x float> @ +// CHECK: %hlsl.normalize = call <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float> + +// CHECK: ret <2 x float> %hlsl.normalize +float2 test_normalize_float2(float2 p0) +{ + return normalize(p0); +} +// CHECK: define [[FNATTRS]] <3 x float> @ +// CHECK: %hlsl.normalize = call <3 x float> @llvm.[[TARGET]].normalize.v3f32( +// CHECK: ret <3 x float> %hlsl.normalize +float3 test_normalize_float3(float3 p0) +{ + return normalize(p0); +} +// CHECK: define [[FNATTRS]] <4 x float> @ +// CHECK: %hlsl.normalize = call <4 x float> @llvm.[[TARGET]].normalize.v4f32( +// CHECK: ret <4 x float> %hlsl.normalize +float4 test_length_float4(float4 p0) +{ + return normalize(p0); +} diff --git a/clang/test/CodeGenHLSL/builtins/step.hlsl b/clang/test/CodeGenHLSL/builtins/step.hlsl index 8ef52794a3be5..442f4930ca579 100644 --- a/clang/test/CodeGenHLSL/builtins/step.hlsl +++ b/clang/test/CodeGenHLSL/builtins/step.hlsl @@ -1,84 +1,84 @@ -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF \ -// RUN: -DFNATTRS=noundef -DTARGET=dx -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ -// RUN: -DFNATTRS=noundef -DTARGET=dx -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ -// RUN: --check-prefixes=CHECK,NATIVE_HALF \ -// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv -// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ -// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv - -// NATIVE_HALF: define [[FNATTRS]] half @ -// NATIVE_HALF: call half @llvm.[[TARGET]].step.f16(half -// NO_HALF: call float @llvm.[[TARGET]].step.f32(float -// NATIVE_HALF: ret half -// NO_HALF: ret float -half test_step_half(half p0, half p1) -{ - return step(p0, p1); -} -// NATIVE_HALF: define [[FNATTRS]] <2 x half> @ -// NATIVE_HALF: call <2 x half> @llvm.[[TARGET]].step.v2f16(<2 x half> -// NO_HALF: call <2 x float> @llvm.[[TARGET]].step.v2f32(<2 x float> -// NATIVE_HALF: ret <2 x half> %hlsl.step -// NO_HALF: ret <2 x float> %hlsl.step -half2 test_step_half2(half2 p0, half2 p1) -{ - return step(p0, p1); -} -// NATIVE_HALF: define [[FNATTRS]] <3 x half> @ -// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].step.v3f16(<3 x half> -// NO_HALF: call <3 x float> @llvm.[[TARGET]].step.v3f32(<3 x float> -// NATIVE_HALF: ret <3 x half> %hlsl.step -// NO_HALF: ret <3 x float> %hlsl.step -half3 test_step_half3(half3 p0, half3 p1) -{ - return step(p0, p1); -} -// NATIVE_HALF: define [[FNATTRS]] <4 x half> @ -// NATIVE_HALF: call <4 x half> @llvm.[[TARGET]].step.v4f16(<4 x half> -// NO_HALF: call <4 x float> @llvm.[[TARGET]].step.v4f32(<4 x float> -// NATIVE_HALF: ret <4 x half> %hlsl.step -// NO_HALF: ret <4 x float> %hlsl.step -half4 test_step_half4(half4 p0, half4 p1) -{ - return step(p0, p1); -} - -// CHECK: define [[FNATTRS]] float @ -// CHECK: call float @llvm.[[TARGET]].step.f32(float -// CHECK: ret float -float test_step_float(float p0, float p1) -{ - return step(p0, p1); -} -// CHECK: define [[FNATTRS]] <2 x float> @ -// CHECK: %hlsl.step = call <2 x float> @llvm.[[TARGET]].step.v2f32( -// CHECK: ret <2 x float> %hlsl.step -float2 test_step_float2(float2 p0, float2 p1) -{ - return step(p0, p1); -} -// CHECK: define [[FNATTRS]] <3 x float> @ -// CHECK: %hlsl.step = call <3 x float> @llvm.[[TARGET]].step.v3f32( -// CHECK: ret <3 x float> %hlsl.step -float3 test_step_float3(float3 p0, float3 p1) -{ - return step(p0, p1); -} -// CHECK: define [[FNATTRS]] <4 x float> @ -// CHECK: %hlsl.step = call <4 x float> @llvm.[[TARGET]].step.v4f32( -// CHECK: ret <4 x float> %hlsl.step -float4 test_step_float4(float4 p0, float4 p1) -{ - return step(p0, p1); -} +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF \ +// RUN: -DFNATTRS=noundef -DTARGET=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ +// RUN: -DFNATTRS=noundef -DTARGET=dx +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF \ +// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \ +// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv + +// NATIVE_HALF: define [[FNATTRS]] half @ +// NATIVE_HALF: call half @llvm.[[TARGET]].step.f16(half +// NO_HALF: call float @llvm.[[TARGET]].step.f32(float +// NATIVE_HALF: ret half +// NO_HALF: ret float +half test_step_half(half p0, half p1) +{ + return step(p0, p1); +} +// NATIVE_HALF: define [[FNATTRS]] <2 x half> @ +// NATIVE_HALF: call <2 x half> @llvm.[[TARGET]].step.v2f16(<2 x half> +// NO_HALF: call <2 x float> @llvm.[[TARGET]].step.v2f32(<2 x float> +// NATIVE_HALF: ret <2 x half> %hlsl.step +// NO_HALF: ret <2 x float> %hlsl.step +half2 test_step_half2(half2 p0, half2 p1) +{ + return step(p0, p1); +} +// NATIVE_HALF: define [[FNATTRS]] <3 x half> @ +// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].step.v3f16(<3 x half> +// NO_HALF: call <3 x float> @llvm.[[TARGET]].step.v3f32(<3 x float> +// NATIVE_HALF: ret <3 x half> %hlsl.step +// NO_HALF: ret <3 x float> %hlsl.step +half3 test_step_half3(half3 p0, half3 p1) +{ + return step(p0, p1); +} +// NATIVE_HALF: define [[FNATTRS]] <4 x half> @ +// NATIVE_HALF: call <4 x half> @llvm.[[TARGET]].step.v4f16(<4 x half> +// NO_HALF: call <4 x float> @llvm.[[TARGET]].step.v4f32(<4 x float> +// NATIVE_HALF: ret <4 x half> %hlsl.step +// NO_HALF: ret <4 x float> %hlsl.step +half4 test_step_half4(half4 p0, half4 p1) +{ + return step(p0, p1); +} + +// CHECK: define [[FNATTRS]] float @ +// CHECK: call float @llvm.[[TARGET]].step.f32(float +// CHECK: ret float +float test_step_float(float p0, float p1) +{ + return step(p0, p1); +} +// CHECK: define [[FNATTRS]] <2 x float> @ +// CHECK: %hlsl.step = call <2 x float> @llvm.[[TARGET]].step.v2f32( +// CHECK: ret <2 x float> %hlsl.step +float2 test_step_float2(float2 p0, float2 p1) +{ + return step(p0, p1); +} +// CHECK: define [[FNATTRS]] <3 x float> @ +// CHECK: %hlsl.step = call <3 x float> @llvm.[[TARGET]].step.v3f32( +// CHECK: ret <3 x float> %hlsl.step +float3 test_step_float3(float3 p0, float3 p1) +{ + return step(p0, p1); +} +// CHECK: define [[FNATTRS]] <4 x float> @ +// CHECK: %hlsl.step = call <4 x float> @llvm.[[TARGET]].step.v4f32( +// CHECK: ret <4 x float> %hlsl.step +float4 test_step_float4(float4 p0, float4 p1) +{ + return step(p0, p1); +} diff --git a/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl b/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl index 7377b5bcbc347..57d056b0ff9d5 100644 --- a/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl +++ b/clang/test/CodeGenOpenCL/addr-space-struct-arg.cl @@ -69,9 +69,11 @@ struct LargeStructOneMember g_s; // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_MAT4X4:%.*]], align 4, addrspace(5) // AMDGCN20-NEXT: [[IN:%.*]] = alloca [[STRUCT_MAT3X3:%.*]], align 4, addrspace(5) -// AMDGCN20-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT3X3]], ptr addrspace(5) [[IN]], i32 0, i32 0 -// AMDGCN20-NEXT: store [9 x i32] [[IN_COERCE]], ptr addrspace(5) [[COERCE_DIVE]], align 4 -// AMDGCN20-NEXT: [[TMP0:%.*]] = load [[STRUCT_MAT4X4]], ptr addrspace(5) [[RETVAL]], align 4 +// AMDGCN20-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr +// AMDGCN20-NEXT: [[IN1:%.*]] = addrspacecast ptr addrspace(5) [[IN]] to ptr +// AMDGCN20-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT3X3]], ptr [[IN1]], i32 0, i32 0 +// AMDGCN20-NEXT: store [9 x i32] [[IN_COERCE]], ptr [[COERCE_DIVE]], align 4 +// AMDGCN20-NEXT: [[TMP0:%.*]] = load [[STRUCT_MAT4X4]], ptr [[RETVAL_ASCAST]], align 4 // AMDGCN20-NEXT: ret [[STRUCT_MAT4X4]] [[TMP0]] // // SPIR-LABEL: define dso_local spir_func void @foo( @@ -150,19 +152,22 @@ Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) { // AMDGCN20-NEXT: [[IN_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // AMDGCN20-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // AMDGCN20-NEXT: [[TMP:%.*]] = alloca [[STRUCT_MAT4X4:%.*]], align 4, addrspace(5) -// AMDGCN20-NEXT: store ptr addrspace(1) [[IN]], ptr addrspace(5) [[IN_ADDR]], align 8 -// AMDGCN20-NEXT: store ptr addrspace(1) [[OUT]], ptr addrspace(5) [[OUT_ADDR]], align 8 -// AMDGCN20-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 +// AMDGCN20-NEXT: [[IN_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[IN_ADDR]] to ptr +// AMDGCN20-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// AMDGCN20-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr +// AMDGCN20-NEXT: store ptr addrspace(1) [[IN]], ptr [[IN_ADDR_ASCAST]], align 8 +// AMDGCN20-NEXT: store ptr addrspace(1) [[OUT]], ptr [[OUT_ADDR_ASCAST]], align 8 +// AMDGCN20-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 // AMDGCN20-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_MAT4X4]], ptr addrspace(1) [[TMP0]], i64 0 -// AMDGCN20-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[IN_ADDR]], align 8 +// AMDGCN20-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[IN_ADDR_ASCAST]], align 8 // AMDGCN20-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [[STRUCT_MAT3X3:%.*]], ptr addrspace(1) [[TMP1]], i64 1 // AMDGCN20-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT3X3]], ptr addrspace(1) [[ARRAYIDX1]], i32 0, i32 0 // AMDGCN20-NEXT: [[TMP3:%.*]] = load [9 x i32], ptr addrspace(1) [[TMP2]], align 4 // AMDGCN20-NEXT: [[CALL:%.*]] = call [[STRUCT_MAT4X4]] @[[FOO:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]]([9 x i32] [[TMP3]]) #[[ATTR3:[0-9]+]] -// AMDGCN20-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT4X4]], ptr addrspace(5) [[TMP]], i32 0, i32 0 +// AMDGCN20-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT4X4]], ptr [[TMP_ASCAST]], i32 0, i32 0 // AMDGCN20-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_MAT4X4]] [[CALL]], 0 -// AMDGCN20-NEXT: store [16 x i32] [[TMP5]], ptr addrspace(5) [[TMP4]], align 4 -// AMDGCN20-NEXT: call void @llvm.memcpy.p1.p5.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr addrspace(5) align 4 [[TMP]], i64 64, i1 false) +// AMDGCN20-NEXT: store [16 x i32] [[TMP5]], ptr [[TMP4]], align 4 +// AMDGCN20-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr align 4 [[TMP_ASCAST]], i64 64, i1 false) // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_kernel void @ker( @@ -245,10 +250,11 @@ kernel void ker(global Mat3X3 *in, global Mat4X4 *out) { // AMDGCN-NEXT: ret void // // AMDGCN20-LABEL: define dso_local void @foo_large( -// AMDGCN20-SAME: ptr addrspace(5) dead_on_unwind noalias writable sret([[STRUCT_MAT64X64:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32:%.*]]) align 4 [[TMP0:%.*]]) #[[ATTR0]] { +// AMDGCN20-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_MAT64X64:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32:%.*]]) align 4 [[TMP0:%.*]]) #[[ATTR0]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] -// AMDGCN20-NEXT: [[IN:%.*]] = alloca [[STRUCT_MAT32X32]], align 4, addrspace(5) -// AMDGCN20-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[IN]], ptr addrspace(5) align 4 [[TMP0]], i64 4096, i1 false) +// AMDGCN20-NEXT: [[COERCE:%.*]] = alloca [[STRUCT_MAT32X32]], align 4, addrspace(5) +// AMDGCN20-NEXT: [[IN:%.*]] = addrspacecast ptr addrspace(5) [[COERCE]] to ptr +// AMDGCN20-NEXT: call void @llvm.memcpy.p0.p5.i64(ptr align 4 [[IN]], ptr addrspace(5) align 4 [[TMP0]], i64 4096, i1 false) // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_func void @foo_large( @@ -319,15 +325,18 @@ Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) { // AMDGCN20-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // AMDGCN20-NEXT: [[TMP:%.*]] = alloca [[STRUCT_MAT64X64:%.*]], align 4, addrspace(5) // AMDGCN20-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_MAT32X32:%.*]], align 4, addrspace(5) -// AMDGCN20-NEXT: store ptr addrspace(1) [[IN]], ptr addrspace(5) [[IN_ADDR]], align 8 -// AMDGCN20-NEXT: store ptr addrspace(1) [[OUT]], ptr addrspace(5) [[OUT_ADDR]], align 8 -// AMDGCN20-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 +// AMDGCN20-NEXT: [[IN_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[IN_ADDR]] to ptr +// AMDGCN20-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// AMDGCN20-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr +// AMDGCN20-NEXT: store ptr addrspace(1) [[IN]], ptr [[IN_ADDR_ASCAST]], align 8 +// AMDGCN20-NEXT: store ptr addrspace(1) [[OUT]], ptr [[OUT_ADDR_ASCAST]], align 8 +// AMDGCN20-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 // AMDGCN20-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_MAT64X64]], ptr addrspace(1) [[TMP0]], i64 0 -// AMDGCN20-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[IN_ADDR]], align 8 +// AMDGCN20-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[IN_ADDR_ASCAST]], align 8 // AMDGCN20-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [[STRUCT_MAT32X32]], ptr addrspace(1) [[TMP1]], i64 1 // AMDGCN20-NEXT: call void @llvm.memcpy.p5.p1.i64(ptr addrspace(5) align 4 [[BYVAL_TEMP]], ptr addrspace(1) align 4 [[ARRAYIDX1]], i64 4096, i1 false) -// AMDGCN20-NEXT: call void @foo_large(ptr addrspace(5) dead_on_unwind writable sret([[STRUCT_MAT64X64]]) align 4 [[TMP]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32]]) align 4 [[BYVAL_TEMP]]) #[[ATTR3]] -// AMDGCN20-NEXT: call void @llvm.memcpy.p1.p5.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr addrspace(5) align 4 [[TMP]], i64 16384, i1 false) +// AMDGCN20-NEXT: call void @foo_large(ptr dead_on_unwind writable sret([[STRUCT_MAT64X64]]) align 4 [[TMP_ASCAST]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32]]) align 4 [[BYVAL_TEMP]]) #[[ATTR3]] +// AMDGCN20-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr align 4 [[TMP_ASCAST]], i64 16384, i1 false) // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_kernel void @ker_large( @@ -419,12 +428,14 @@ kernel void ker_large(global Mat32X32 *in, global Mat64X64 *out) { // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[U:%.*]] = alloca [[STRUCT_STRUCTONEMEMBER:%.*]], align 8, addrspace(5) // AMDGCN20-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca <2 x i32>, align 8, addrspace(5) -// AMDGCN20-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN20-NEXT: store <2 x i32> [[U_COERCE]], ptr addrspace(5) [[COERCE_DIVE]], align 8 -// AMDGCN20-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN20-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN20-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN20-NEXT: store <2 x i32> [[TMP0]], ptr addrspace(5) [[X]], align 8 +// AMDGCN20-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN20-NEXT: [[DOTCOMPOUNDLITERAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTCOMPOUNDLITERAL]] to ptr +// AMDGCN20-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN20-NEXT: store <2 x i32> [[U_COERCE]], ptr [[COERCE_DIVE]], align 8 +// AMDGCN20-NEXT: store <2 x i32> zeroinitializer, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN20-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN20-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN20-NEXT: store <2 x i32> [[TMP0]], ptr [[X]], align 8 // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_func void @FuncOneMember( @@ -497,14 +508,16 @@ void FuncOneMember(struct StructOneMember u) { // AMDGCN20-LABEL: define dso_local void @FuncOneLargeMember( // AMDGCN20-SAME: ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER:%.*]]) align 8 [[TMP0:%.*]]) #[[ATTR0]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] -// AMDGCN20-NEXT: [[U:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) +// AMDGCN20-NEXT: [[COERCE:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) // AMDGCN20-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca <2 x i32>, align 8, addrspace(5) -// AMDGCN20-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 8 [[U]], ptr addrspace(5) align 8 [[TMP0]], i64 800, i1 false) -// AMDGCN20-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN20-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN20-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN20-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x <2 x i32>], ptr addrspace(5) [[X]], i64 0, i64 0 -// AMDGCN20-NEXT: store <2 x i32> [[TMP1]], ptr addrspace(5) [[ARRAYIDX]], align 8 +// AMDGCN20-NEXT: [[U:%.*]] = addrspacecast ptr addrspace(5) [[COERCE]] to ptr +// AMDGCN20-NEXT: [[DOTCOMPOUNDLITERAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTCOMPOUNDLITERAL]] to ptr +// AMDGCN20-NEXT: call void @llvm.memcpy.p0.p5.i64(ptr align 8 [[U]], ptr addrspace(5) align 8 [[TMP0]], i64 800, i1 false) +// AMDGCN20-NEXT: store <2 x i32> zeroinitializer, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN20-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN20-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTONEMEMBER]], ptr [[U]], i32 0, i32 0 +// AMDGCN20-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x <2 x i32>], ptr [[X]], i64 0, i64 0 +// AMDGCN20-NEXT: store <2 x i32> [[TMP1]], ptr [[ARRAYIDX]], align 8 // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_func void @FuncOneLargeMember( @@ -643,7 +656,10 @@ kernel void test_indirect_arg_local(void) { // AMDGCN20-SAME: ) #[[ATTR0]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[P_S:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER:%.*]], align 8, addrspace(5) -// AMDGCN20-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[P_S]]) #[[ATTR3]] +// AMDGCN20-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) +// AMDGCN20-NEXT: [[P_S_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_S]] to ptr +// AMDGCN20-NEXT: call void @llvm.memcpy.p5.p0.i64(ptr addrspace(5) align 8 [[BYVAL_TEMP]], ptr align 8 [[P_S_ASCAST]], i64 800, i1 false) +// AMDGCN20-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_func void @test_indirect_arg_private( @@ -694,10 +710,11 @@ void test_indirect_arg_private(void) { // AMDGCN20-SAME: <2 x i32> [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10:![0-9]+]] !kernel_arg_access_qual [[META11:![0-9]+]] !kernel_arg_type [[META12:![0-9]+]] !kernel_arg_base_type [[META12]] !kernel_arg_type_qual [[META13:![0-9]+]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[U:%.*]] = alloca [[STRUCT_STRUCTONEMEMBER:%.*]], align 8, addrspace(5) -// AMDGCN20-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN20-NEXT: store <2 x i32> [[U_COERCE]], ptr addrspace(5) [[COERCE_DIVE]], align 8 -// AMDGCN20-NEXT: [[COERCE_DIVE1:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN20-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr addrspace(5) [[COERCE_DIVE1]], align 8 +// AMDGCN20-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN20-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN20-NEXT: store <2 x i32> [[U_COERCE]], ptr [[COERCE_DIVE]], align 8 +// AMDGCN20-NEXT: [[COERCE_DIVE2:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN20-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[COERCE_DIVE2]], align 8 // AMDGCN20-NEXT: call void @FuncOneMember(<2 x i32> [[TMP0]]) #[[ATTR3]] // AMDGCN20-NEXT: ret void // @@ -760,8 +777,9 @@ kernel void KernelOneMember(struct StructOneMember u) { // AMDGCN20-SAME: ptr addrspace(1) noundef align 8 [[U:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META14:![0-9]+]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META15:![0-9]+]] !kernel_arg_base_type [[META15]] !kernel_arg_type_qual [[META13]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[U_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) -// AMDGCN20-NEXT: store ptr addrspace(1) [[U]], ptr addrspace(5) [[U_ADDR]], align 8 -// AMDGCN20-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[U_ADDR]], align 8 +// AMDGCN20-NEXT: [[U_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[U_ADDR]] to ptr +// AMDGCN20-NEXT: store ptr addrspace(1) [[U]], ptr [[U_ADDR_ASCAST]], align 8 +// AMDGCN20-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[U_ADDR_ASCAST]], align 8 // AMDGCN20-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER:%.*]], ptr addrspace(1) [[TMP0]], i32 0, i32 0 // AMDGCN20-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr addrspace(1) [[COERCE_DIVE]], align 8 // AMDGCN20-NEXT: call void @FuncOneMember(<2 x i32> [[TMP1]]) #[[ATTR3]] @@ -825,10 +843,13 @@ kernel void KernelOneMemberSpir(global struct StructOneMember* u) { // AMDGCN20-SAME: [[STRUCT_LARGESTRUCTONEMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META16:![0-9]+]] !kernel_arg_base_type [[META16]] !kernel_arg_type_qual [[META13]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[U:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) -// AMDGCN20-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 +// AMDGCN20-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) +// AMDGCN20-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN20-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 // AMDGCN20-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_LARGESTRUCTONEMEMBER]] [[U_COERCE]], 0 -// AMDGCN20-NEXT: store [100 x <2 x i32>] [[TMP1]], ptr addrspace(5) [[TMP0]], align 8 -// AMDGCN20-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[U]]) #[[ATTR3]] +// AMDGCN20-NEXT: store [100 x <2 x i32>] [[TMP1]], ptr [[TMP0]], align 8 +// AMDGCN20-NEXT: call void @llvm.memcpy.p5.p0.i64(ptr addrspace(5) align 8 [[BYVAL_TEMP]], ptr align 8 [[U1]], i64 800, i1 false) +// AMDGCN20-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_kernel void @KernelLargeOneMember( @@ -894,14 +915,16 @@ kernel void KernelLargeOneMember(struct LargeStructOneMember u) { // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[U:%.*]] = alloca [[STRUCT_STRUCTTWOMEMBER:%.*]], align 8, addrspace(5) // AMDGCN20-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca <2 x i32>, align 8, addrspace(5) -// AMDGCN20-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN20-NEXT: store <2 x i32> [[U_COERCE0]], ptr addrspace(5) [[TMP0]], align 8 -// AMDGCN20-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 -// AMDGCN20-NEXT: store <2 x i32> [[U_COERCE1]], ptr addrspace(5) [[TMP1]], align 8 -// AMDGCN20-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN20-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN20-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 -// AMDGCN20-NEXT: store <2 x i32> [[TMP2]], ptr addrspace(5) [[Y]], align 8 +// AMDGCN20-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN20-NEXT: [[DOTCOMPOUNDLITERAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTCOMPOUNDLITERAL]] to ptr +// AMDGCN20-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN20-NEXT: store <2 x i32> [[U_COERCE0]], ptr [[TMP0]], align 8 +// AMDGCN20-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 +// AMDGCN20-NEXT: store <2 x i32> [[U_COERCE1]], ptr [[TMP1]], align 8 +// AMDGCN20-NEXT: store <2 x i32> zeroinitializer, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN20-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN20-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 +// AMDGCN20-NEXT: store <2 x i32> [[TMP2]], ptr [[Y]], align 8 // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_func void @FuncTwoMember( @@ -978,14 +1001,16 @@ void FuncTwoMember(struct StructTwoMember u) { // AMDGCN20-LABEL: define dso_local void @FuncLargeTwoMember( // AMDGCN20-SAME: ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTTWOMEMBER:%.*]]) align 8 [[TMP0:%.*]]) #[[ATTR0]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] -// AMDGCN20-NEXT: [[U:%.*]] = alloca [[STRUCT_LARGESTRUCTTWOMEMBER]], align 8, addrspace(5) +// AMDGCN20-NEXT: [[COERCE:%.*]] = alloca [[STRUCT_LARGESTRUCTTWOMEMBER]], align 8, addrspace(5) // AMDGCN20-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca <2 x i32>, align 8, addrspace(5) -// AMDGCN20-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 8 [[U]], ptr addrspace(5) align 8 [[TMP0]], i64 480, i1 false) -// AMDGCN20-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN20-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN20-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 -// AMDGCN20-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [20 x <2 x i32>], ptr addrspace(5) [[Y]], i64 0, i64 0 -// AMDGCN20-NEXT: store <2 x i32> [[TMP1]], ptr addrspace(5) [[ARRAYIDX]], align 8 +// AMDGCN20-NEXT: [[U:%.*]] = addrspacecast ptr addrspace(5) [[COERCE]] to ptr +// AMDGCN20-NEXT: [[DOTCOMPOUNDLITERAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTCOMPOUNDLITERAL]] to ptr +// AMDGCN20-NEXT: call void @llvm.memcpy.p0.p5.i64(ptr align 8 [[U]], ptr addrspace(5) align 8 [[TMP0]], i64 480, i1 false) +// AMDGCN20-NEXT: store <2 x i32> zeroinitializer, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN20-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN20-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr [[U]], i32 0, i32 1 +// AMDGCN20-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [20 x <2 x i32>], ptr [[Y]], i64 0, i64 0 +// AMDGCN20-NEXT: store <2 x i32> [[TMP1]], ptr [[ARRAYIDX]], align 8 // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_func void @FuncLargeTwoMember( @@ -1057,16 +1082,17 @@ void FuncLargeTwoMember(struct LargeStructTwoMember u) { // AMDGCN20-SAME: [[STRUCT_STRUCTTWOMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META17:![0-9]+]] !kernel_arg_base_type [[META17]] !kernel_arg_type_qual [[META13]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[U:%.*]] = alloca [[STRUCT_STRUCTTWOMEMBER]], align 8, addrspace(5) -// AMDGCN20-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 +// AMDGCN20-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN20-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 0 // AMDGCN20-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_STRUCTTWOMEMBER]] [[U_COERCE]], 0 -// AMDGCN20-NEXT: store <2 x i32> [[TMP1]], ptr addrspace(5) [[TMP0]], align 8 -// AMDGCN20-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 +// AMDGCN20-NEXT: store <2 x i32> [[TMP1]], ptr [[TMP0]], align 8 +// AMDGCN20-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 // AMDGCN20-NEXT: [[TMP3:%.*]] = extractvalue [[STRUCT_STRUCTTWOMEMBER]] [[U_COERCE]], 1 -// AMDGCN20-NEXT: store <2 x i32> [[TMP3]], ptr addrspace(5) [[TMP2]], align 8 -// AMDGCN20-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN20-NEXT: [[TMP5:%.*]] = load <2 x i32>, ptr addrspace(5) [[TMP4]], align 8 -// AMDGCN20-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 -// AMDGCN20-NEXT: [[TMP7:%.*]] = load <2 x i32>, ptr addrspace(5) [[TMP6]], align 8 +// AMDGCN20-NEXT: store <2 x i32> [[TMP3]], ptr [[TMP2]], align 8 +// AMDGCN20-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN20-NEXT: [[TMP5:%.*]] = load <2 x i32>, ptr [[TMP4]], align 8 +// AMDGCN20-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 +// AMDGCN20-NEXT: [[TMP7:%.*]] = load <2 x i32>, ptr [[TMP6]], align 8 // AMDGCN20-NEXT: call void @FuncTwoMember(<2 x i32> [[TMP5]], <2 x i32> [[TMP7]]) #[[ATTR3]] // AMDGCN20-NEXT: ret void // @@ -1138,13 +1164,16 @@ kernel void KernelTwoMember(struct StructTwoMember u) { // AMDGCN20-SAME: [[STRUCT_LARGESTRUCTTWOMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META18:![0-9]+]] !kernel_arg_base_type [[META18]] !kernel_arg_type_qual [[META13]] { // AMDGCN20-NEXT: [[ENTRY:.*:]] // AMDGCN20-NEXT: [[U:%.*]] = alloca [[STRUCT_LARGESTRUCTTWOMEMBER]], align 8, addrspace(5) -// AMDGCN20-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 +// AMDGCN20-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGESTRUCTTWOMEMBER]], align 8, addrspace(5) +// AMDGCN20-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN20-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 0 // AMDGCN20-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_LARGESTRUCTTWOMEMBER]] [[U_COERCE]], 0 -// AMDGCN20-NEXT: store [40 x <2 x i32>] [[TMP1]], ptr addrspace(5) [[TMP0]], align 8 -// AMDGCN20-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 +// AMDGCN20-NEXT: store [40 x <2 x i32>] [[TMP1]], ptr [[TMP0]], align 8 +// AMDGCN20-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 // AMDGCN20-NEXT: [[TMP3:%.*]] = extractvalue [[STRUCT_LARGESTRUCTTWOMEMBER]] [[U_COERCE]], 1 -// AMDGCN20-NEXT: store [20 x <2 x i32>] [[TMP3]], ptr addrspace(5) [[TMP2]], align 8 -// AMDGCN20-NEXT: call void @FuncLargeTwoMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTTWOMEMBER]]) align 8 [[U]]) #[[ATTR3]] +// AMDGCN20-NEXT: store [20 x <2 x i32>] [[TMP3]], ptr [[TMP2]], align 8 +// AMDGCN20-NEXT: call void @llvm.memcpy.p5.p0.i64(ptr addrspace(5) align 8 [[BYVAL_TEMP]], ptr align 8 [[U1]], i64 480, i1 false) +// AMDGCN20-NEXT: call void @FuncLargeTwoMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTTWOMEMBER]]) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] // AMDGCN20-NEXT: ret void // // SPIR-LABEL: define dso_local spir_kernel void @KernelLargeTwoMember( diff --git a/clang/test/CodeGenOpenCL/amdgcn-automatic-variable.cl b/clang/test/CodeGenOpenCL/amdgcn-automatic-variable.cl index c847f5850b223..dba6519966eb5 100644 --- a/clang/test/CodeGenOpenCL/amdgcn-automatic-variable.cl +++ b/clang/test/CodeGenOpenCL/amdgcn-automatic-variable.cl @@ -15,8 +15,9 @@ // CL20-SAME: ptr noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] { // CL20-NEXT: [[ENTRY:.*:]] // CL20-NEXT: [[X_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// CL20-NEXT: store ptr [[X]], ptr addrspace(5) [[X_ADDR]], align 8 -// CL20-NEXT: [[TMP0:%.*]] = load ptr, ptr addrspace(5) [[X_ADDR]], align 8 +// CL20-NEXT: [[X_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[X_ADDR]] to ptr +// CL20-NEXT: store ptr [[X]], ptr [[X_ADDR_ASCAST]], align 8 +// CL20-NEXT: [[TMP0:%.*]] = load ptr, ptr [[X_ADDR_ASCAST]], align 8 // CL20-NEXT: store i32 1, ptr [[TMP0]], align 4 // CL20-NEXT: ret void // @@ -54,25 +55,27 @@ void func1(int *x) { // CL20-NEXT: [[LP1:%.*]] = alloca ptr, align 8, addrspace(5) // CL20-NEXT: [[LP2:%.*]] = alloca ptr, align 8, addrspace(5) // CL20-NEXT: [[LVC:%.*]] = alloca i32, align 4, addrspace(5) -// CL20-NEXT: store i32 1, ptr addrspace(5) [[LV1]], align 4 -// CL20-NEXT: store i32 2, ptr addrspace(5) [[LV2]], align 4 -// CL20-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x i32], ptr addrspace(5) [[LA]], i64 0, i64 0 -// CL20-NEXT: store i32 3, ptr addrspace(5) [[ARRAYIDX]], align 4 // CL20-NEXT: [[LV1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LV1]] to ptr -// CL20-NEXT: store ptr [[LV1_ASCAST]], ptr addrspace(5) [[LP1]], align 8 -// CL20-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [100 x i32], ptr addrspace(5) [[LA]], i64 0, i64 0 -// CL20-NEXT: [[ARRAYDECAY_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ARRAYDECAY]] to ptr -// CL20-NEXT: store ptr [[ARRAYDECAY_ASCAST]], ptr addrspace(5) [[LP2]], align 8 -// CL20-NEXT: [[LV1_ASCAST1:%.*]] = addrspacecast ptr addrspace(5) [[LV1]] to ptr -// CL20-NEXT: call void @func1(ptr noundef [[LV1_ASCAST1]]) #[[ATTR2:[0-9]+]] -// CL20-NEXT: store i32 4, ptr addrspace(5) [[LVC]], align 4 -// CL20-NEXT: store i32 4, ptr addrspace(5) [[LV1]], align 4 +// CL20-NEXT: [[LV2_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LV2]] to ptr +// CL20-NEXT: [[LA_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LA]] to ptr +// CL20-NEXT: [[LP1_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LP1]] to ptr +// CL20-NEXT: [[LP2_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LP2]] to ptr +// CL20-NEXT: [[LVC_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LVC]] to ptr +// CL20-NEXT: store i32 1, ptr [[LV1_ASCAST]], align 4 +// CL20-NEXT: store i32 2, ptr [[LV2_ASCAST]], align 4 +// CL20-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x i32], ptr [[LA_ASCAST]], i64 0, i64 0 +// CL20-NEXT: store i32 3, ptr [[ARRAYIDX]], align 4 +// CL20-NEXT: store ptr [[LV1_ASCAST]], ptr [[LP1_ASCAST]], align 8 +// CL20-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [100 x i32], ptr [[LA_ASCAST]], i64 0, i64 0 +// CL20-NEXT: store ptr [[ARRAYDECAY]], ptr [[LP2_ASCAST]], align 8 +// CL20-NEXT: call void @func1(ptr noundef [[LV1_ASCAST]]) #[[ATTR2:[0-9]+]] +// CL20-NEXT: store i32 4, ptr [[LVC_ASCAST]], align 4 +// CL20-NEXT: store i32 4, ptr [[LV1_ASCAST]], align 4 // CL20-NEXT: ret void // void func2(void) { int lv1; lv1 = 1; - int lv2 = 2; int la[100]; @@ -99,7 +102,8 @@ void func2(void) { // CL20-SAME: ) #[[ATTR0]] { // CL20-NEXT: [[ENTRY:.*:]] // CL20-NEXT: [[A:%.*]] = alloca [16 x [1 x float]], align 4, addrspace(5) -// CL20-NEXT: call void @llvm.memset.p5.i64(ptr addrspace(5) align 4 [[A]], i8 0, i64 64, i1 false) +// CL20-NEXT: [[A_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A]] to ptr +// CL20-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[A_ASCAST]], i8 0, i64 64, i1 false) // CL20-NEXT: ret void // void func3(void) { diff --git a/clang/test/CodeGenOpenCL/amdgpu-abi-struct-arg-byref.cl b/clang/test/CodeGenOpenCL/amdgpu-abi-struct-arg-byref.cl index a5f682646d338..084281a8cada4 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-abi-struct-arg-byref.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-abi-struct-arg-byref.cl @@ -1,4 +1,4 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL2.0 -O0 -triple amdgcn | FileCheck -check-prefix=AMDGCN %s typedef int int2 __attribute__((ext_vector_type(2))); @@ -42,14 +42,16 @@ struct LargeStructOneMember g_s; #endif -// AMDGCN-LABEL: define dso_local %struct.Mat4X4 @foo -// AMDGCN-SAME: ([9 x i32] [[IN_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local %struct.Mat4X4 @foo( +// AMDGCN-SAME: [9 x i32] [[IN_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_MAT4X4:%.*]], align 4, addrspace(5) // AMDGCN-NEXT: [[IN:%.*]] = alloca [[STRUCT_MAT3X3:%.*]], align 4, addrspace(5) -// AMDGCN-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT3X3]], ptr addrspace(5) [[IN]], i32 0, i32 0 -// AMDGCN-NEXT: store [9 x i32] [[IN_COERCE]], ptr addrspace(5) [[COERCE_DIVE]], align 4 -// AMDGCN-NEXT: [[TMP0:%.*]] = load [[STRUCT_MAT4X4]], ptr addrspace(5) [[RETVAL]], align 4 +// AMDGCN-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr +// AMDGCN-NEXT: [[IN1:%.*]] = addrspacecast ptr addrspace(5) [[IN]] to ptr +// AMDGCN-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT3X3]], ptr [[IN1]], i32 0, i32 0 +// AMDGCN-NEXT: store [9 x i32] [[IN_COERCE]], ptr [[COERCE_DIVE]], align 4 +// AMDGCN-NEXT: [[TMP0:%.*]] = load [[STRUCT_MAT4X4]], ptr [[RETVAL_ASCAST]], align 4 // AMDGCN-NEXT: ret [[STRUCT_MAT4X4]] [[TMP0]] // Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) { @@ -60,36 +62,40 @@ Mat4X4 __attribute__((noinline)) foo(Mat3X3 in) { // Expect two mem copies: one for the argument "in", and one for // the return value. -// AMDGCN-LABEL: define dso_local amdgpu_kernel void @ker -// AMDGCN-SAME: (ptr addrspace(1) noundef align 4 [[IN:%.*]], ptr addrspace(1) noundef align 4 [[OUT:%.*]]) #[[ATTR1:[0-9]+]] !kernel_arg_addr_space [[META4:![0-9]+]] !kernel_arg_access_qual [[META5:![0-9]+]] !kernel_arg_type [[META6:![0-9]+]] !kernel_arg_base_type [[META6]] !kernel_arg_type_qual [[META7:![0-9]+]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local amdgpu_kernel void @ker( +// AMDGCN-SAME: ptr addrspace(1) noundef align 4 [[IN:%.*]], ptr addrspace(1) noundef align 4 [[OUT:%.*]]) #[[ATTR1:[0-9]+]] !kernel_arg_addr_space [[META4:![0-9]+]] !kernel_arg_access_qual [[META5:![0-9]+]] !kernel_arg_type [[META6:![0-9]+]] !kernel_arg_base_type [[META6]] !kernel_arg_type_qual [[META7:![0-9]+]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[IN_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // AMDGCN-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // AMDGCN-NEXT: [[TMP:%.*]] = alloca [[STRUCT_MAT4X4:%.*]], align 4, addrspace(5) -// AMDGCN-NEXT: store ptr addrspace(1) [[IN]], ptr addrspace(5) [[IN_ADDR]], align 8 -// AMDGCN-NEXT: store ptr addrspace(1) [[OUT]], ptr addrspace(5) [[OUT_ADDR]], align 8 -// AMDGCN-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 +// AMDGCN-NEXT: [[IN_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[IN_ADDR]] to ptr +// AMDGCN-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// AMDGCN-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr +// AMDGCN-NEXT: store ptr addrspace(1) [[IN]], ptr [[IN_ADDR_ASCAST]], align 8 +// AMDGCN-NEXT: store ptr addrspace(1) [[OUT]], ptr [[OUT_ADDR_ASCAST]], align 8 +// AMDGCN-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_MAT4X4]], ptr addrspace(1) [[TMP0]], i64 0 -// AMDGCN-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[IN_ADDR]], align 8 +// AMDGCN-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[IN_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [[STRUCT_MAT3X3:%.*]], ptr addrspace(1) [[TMP1]], i64 1 // AMDGCN-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT3X3]], ptr addrspace(1) [[ARRAYIDX1]], i32 0, i32 0 // AMDGCN-NEXT: [[TMP3:%.*]] = load [9 x i32], ptr addrspace(1) [[TMP2]], align 4 // AMDGCN-NEXT: [[CALL:%.*]] = call [[STRUCT_MAT4X4]] @[[FOO:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]]([9 x i32] [[TMP3]]) #[[ATTR3:[0-9]+]] -// AMDGCN-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT4X4]], ptr addrspace(5) [[TMP]], i32 0, i32 0 +// AMDGCN-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[STRUCT_MAT4X4]], ptr [[TMP_ASCAST]], i32 0, i32 0 // AMDGCN-NEXT: [[TMP5:%.*]] = extractvalue [[STRUCT_MAT4X4]] [[CALL]], 0 -// AMDGCN-NEXT: store [16 x i32] [[TMP5]], ptr addrspace(5) [[TMP4]], align 4 -// AMDGCN-NEXT: call void @llvm.memcpy.p1.p5.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr addrspace(5) align 4 [[TMP]], i64 64, i1 false) +// AMDGCN-NEXT: store [16 x i32] [[TMP5]], ptr [[TMP4]], align 4 +// AMDGCN-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr align 4 [[TMP_ASCAST]], i64 64, i1 false) // AMDGCN-NEXT: ret void // kernel void ker(global Mat3X3 *in, global Mat4X4 *out) { out[0] = foo(in[1]); } -// AMDGCN-LABEL: define dso_local void @foo_large -// AMDGCN-SAME: (ptr addrspace(5) dead_on_unwind noalias writable sret([[STRUCT_MAT64X64:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32:%.*]]) align 4 [[TMP0:%.*]]) #[[ATTR0]] { -// AMDGCN-NEXT: entry: -// AMDGCN-NEXT: [[IN:%.*]] = alloca [[STRUCT_MAT32X32]], align 4, addrspace(5) -// AMDGCN-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[IN]], ptr addrspace(5) align 4 [[TMP0]], i64 4096, i1 false) +// AMDGCN-LABEL: define dso_local void @foo_large( +// AMDGCN-SAME: ptr dead_on_unwind noalias writable sret([[STRUCT_MAT64X64:%.*]]) align 4 [[AGG_RESULT:%.*]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32:%.*]]) align 4 [[TMP0:%.*]]) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] +// AMDGCN-NEXT: [[COERCE:%.*]] = alloca [[STRUCT_MAT32X32]], align 4, addrspace(5) +// AMDGCN-NEXT: [[IN:%.*]] = addrspacecast ptr addrspace(5) [[COERCE]] to ptr +// AMDGCN-NEXT: call void @llvm.memcpy.p0.p5.i64(ptr align 4 [[IN]], ptr addrspace(5) align 4 [[TMP0]], i64 4096, i1 false) // AMDGCN-NEXT: ret void // Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) { @@ -97,56 +103,63 @@ Mat64X64 __attribute__((noinline)) foo_large(Mat32X32 in) { return out; } -// AMDGCN-LABEL: define dso_local amdgpu_kernel void @ker_large -// AMDGCN-SAME: (ptr addrspace(1) noundef align 4 [[IN:%.*]], ptr addrspace(1) noundef align 4 [[OUT:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META4]] !kernel_arg_access_qual [[META5]] !kernel_arg_type [[META8:![0-9]+]] !kernel_arg_base_type [[META8]] !kernel_arg_type_qual [[META7]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local amdgpu_kernel void @ker_large( +// AMDGCN-SAME: ptr addrspace(1) noundef align 4 [[IN:%.*]], ptr addrspace(1) noundef align 4 [[OUT:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META4]] !kernel_arg_access_qual [[META5]] !kernel_arg_type [[META8:![0-9]+]] !kernel_arg_base_type [[META8]] !kernel_arg_type_qual [[META7]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[IN_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // AMDGCN-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // AMDGCN-NEXT: [[TMP:%.*]] = alloca [[STRUCT_MAT64X64:%.*]], align 4, addrspace(5) // AMDGCN-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_MAT32X32:%.*]], align 4, addrspace(5) -// AMDGCN-NEXT: store ptr addrspace(1) [[IN]], ptr addrspace(5) [[IN_ADDR]], align 8 -// AMDGCN-NEXT: store ptr addrspace(1) [[OUT]], ptr addrspace(5) [[OUT_ADDR]], align 8 -// AMDGCN-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 +// AMDGCN-NEXT: [[IN_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[IN_ADDR]] to ptr +// AMDGCN-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// AMDGCN-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr +// AMDGCN-NEXT: store ptr addrspace(1) [[IN]], ptr [[IN_ADDR_ASCAST]], align 8 +// AMDGCN-NEXT: store ptr addrspace(1) [[OUT]], ptr [[OUT_ADDR_ASCAST]], align 8 +// AMDGCN-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_MAT64X64]], ptr addrspace(1) [[TMP0]], i64 0 -// AMDGCN-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[IN_ADDR]], align 8 +// AMDGCN-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[IN_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [[STRUCT_MAT32X32]], ptr addrspace(1) [[TMP1]], i64 1 // AMDGCN-NEXT: call void @llvm.memcpy.p5.p1.i64(ptr addrspace(5) align 4 [[BYVAL_TEMP]], ptr addrspace(1) align 4 [[ARRAYIDX1]], i64 4096, i1 false) -// AMDGCN-NEXT: call void @foo_large(ptr addrspace(5) dead_on_unwind writable sret([[STRUCT_MAT64X64]]) align 4 [[TMP]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32]]) align 4 [[BYVAL_TEMP]]) #[[ATTR3]] -// AMDGCN-NEXT: call void @llvm.memcpy.p1.p5.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr addrspace(5) align 4 [[TMP]], i64 16384, i1 false) +// AMDGCN-NEXT: call void @foo_large(ptr dead_on_unwind writable sret([[STRUCT_MAT64X64]]) align 4 [[TMP_ASCAST]], ptr addrspace(5) noundef byref([[STRUCT_MAT32X32]]) align 4 [[BYVAL_TEMP]]) #[[ATTR3]] +// AMDGCN-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) align 4 [[ARRAYIDX]], ptr align 4 [[TMP_ASCAST]], i64 16384, i1 false) // AMDGCN-NEXT: ret void // kernel void ker_large(global Mat32X32 *in, global Mat64X64 *out) { out[0] = foo_large(in[1]); } -// AMDGCN-LABEL: define dso_local void @FuncOneMember -// AMDGCN-SAME: (<2 x i32> [[U_COERCE:%.*]]) #[[ATTR0]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local void @FuncOneMember( +// AMDGCN-SAME: <2 x i32> [[U_COERCE:%.*]]) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[U:%.*]] = alloca [[STRUCT_STRUCTONEMEMBER:%.*]], align 8, addrspace(5) // AMDGCN-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca <2 x i32>, align 8, addrspace(5) -// AMDGCN-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN-NEXT: store <2 x i32> [[U_COERCE]], ptr addrspace(5) [[COERCE_DIVE]], align 8 -// AMDGCN-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN-NEXT: store <2 x i32> [[TMP0]], ptr addrspace(5) [[X]], align 8 +// AMDGCN-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN-NEXT: [[DOTCOMPOUNDLITERAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTCOMPOUNDLITERAL]] to ptr +// AMDGCN-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN-NEXT: store <2 x i32> [[U_COERCE]], ptr [[COERCE_DIVE]], align 8 +// AMDGCN-NEXT: store <2 x i32> zeroinitializer, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN-NEXT: store <2 x i32> [[TMP0]], ptr [[X]], align 8 // AMDGCN-NEXT: ret void // void FuncOneMember(struct StructOneMember u) { u.x = (int2)(0, 0); } -// AMDGCN-LABEL: define dso_local void @FuncOneLargeMember -// AMDGCN-SAME: (ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER:%.*]]) align 8 [[TMP0:%.*]]) #[[ATTR0]] { -// AMDGCN-NEXT: entry: -// AMDGCN-NEXT: [[U:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) +// AMDGCN-LABEL: define dso_local void @FuncOneLargeMember( +// AMDGCN-SAME: ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER:%.*]]) align 8 [[TMP0:%.*]]) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] +// AMDGCN-NEXT: [[COERCE:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) // AMDGCN-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca <2 x i32>, align 8, addrspace(5) -// AMDGCN-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 8 [[U]], ptr addrspace(5) align 8 [[TMP0]], i64 800, i1 false) -// AMDGCN-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x <2 x i32>], ptr addrspace(5) [[X]], i64 0, i64 0 -// AMDGCN-NEXT: store <2 x i32> [[TMP1]], ptr addrspace(5) [[ARRAYIDX]], align 8 +// AMDGCN-NEXT: [[U:%.*]] = addrspacecast ptr addrspace(5) [[COERCE]] to ptr +// AMDGCN-NEXT: [[DOTCOMPOUNDLITERAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTCOMPOUNDLITERAL]] to ptr +// AMDGCN-NEXT: call void @llvm.memcpy.p0.p5.i64(ptr align 8 [[U]], ptr addrspace(5) align 8 [[TMP0]], i64 800, i1 false) +// AMDGCN-NEXT: store <2 x i32> zeroinitializer, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTONEMEMBER]], ptr [[U]], i32 0, i32 0 +// AMDGCN-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x <2 x i32>], ptr [[X]], i64 0, i64 0 +// AMDGCN-NEXT: store <2 x i32> [[TMP1]], ptr [[ARRAYIDX]], align 8 // AMDGCN-NEXT: ret void // void FuncOneLargeMember(struct LargeStructOneMember u) { @@ -154,9 +167,9 @@ void FuncOneLargeMember(struct LargeStructOneMember u) { } #if (__OPENCL_C_VERSION__ == 200) || (__OPENCL_C_VERSION__ >= 300 && defined(__opencl_c_program_scope_global_variables)) -// AMDGCN-LABEL: define dso_local void @test_indirect_arg_globl -// AMDGCN-SAME: () #[[ATTR0]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local void @test_indirect_arg_globl( +// AMDGCN-SAME: ) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER:%.*]], align 8, addrspace(5) // AMDGCN-NEXT: call void @llvm.memcpy.p5.p1.i64(ptr addrspace(5) align 8 [[BYVAL_TEMP]], ptr addrspace(1) align 8 @g_s, i64 800, i1 false) // AMDGCN-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] @@ -167,9 +180,9 @@ void test_indirect_arg_globl(void) { } #endif -// AMDGCN-LABEL: define dso_local amdgpu_kernel void @test_indirect_arg_local -// AMDGCN-SAME: () #[[ATTR1]] !kernel_arg_addr_space [[META9:![0-9]+]] !kernel_arg_access_qual [[META9]] !kernel_arg_type [[META9]] !kernel_arg_base_type [[META9]] !kernel_arg_type_qual [[META9]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local amdgpu_kernel void @test_indirect_arg_local( +// AMDGCN-SAME: ) #[[ATTR1]] !kernel_arg_addr_space [[META9:![0-9]+]] !kernel_arg_access_qual [[META9]] !kernel_arg_type [[META9]] !kernel_arg_base_type [[META9]] !kernel_arg_type_qual [[META9]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER:%.*]], align 8, addrspace(5) // AMDGCN-NEXT: call void @llvm.memcpy.p5.p3.i64(ptr addrspace(5) align 8 [[BYVAL_TEMP]], ptr addrspace(3) align 8 @test_indirect_arg_local.l_s, i64 800, i1 false) // AMDGCN-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] @@ -180,11 +193,14 @@ kernel void test_indirect_arg_local(void) { FuncOneLargeMember(l_s); } -// AMDGCN-LABEL: define dso_local void @test_indirect_arg_private -// AMDGCN-SAME: () #[[ATTR0]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local void @test_indirect_arg_private( +// AMDGCN-SAME: ) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[P_S:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER:%.*]], align 8, addrspace(5) -// AMDGCN-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[P_S]]) #[[ATTR3]] +// AMDGCN-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) +// AMDGCN-NEXT: [[P_S_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_S]] to ptr +// AMDGCN-NEXT: call void @llvm.memcpy.p5.p0.i64(ptr addrspace(5) align 8 [[BYVAL_TEMP]], ptr align 8 [[P_S_ASCAST]], i64 800, i1 false) +// AMDGCN-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] // AMDGCN-NEXT: ret void // void test_indirect_arg_private(void) { @@ -192,14 +208,15 @@ void test_indirect_arg_private(void) { FuncOneLargeMember(p_s); } -// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelOneMember -// AMDGCN-SAME: (<2 x i32> [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10:![0-9]+]] !kernel_arg_access_qual [[META11:![0-9]+]] !kernel_arg_type [[META12:![0-9]+]] !kernel_arg_base_type [[META12]] !kernel_arg_type_qual [[META13:![0-9]+]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelOneMember( +// AMDGCN-SAME: <2 x i32> [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10:![0-9]+]] !kernel_arg_access_qual [[META11:![0-9]+]] !kernel_arg_type [[META12:![0-9]+]] !kernel_arg_base_type [[META12]] !kernel_arg_type_qual [[META13:![0-9]+]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[U:%.*]] = alloca [[STRUCT_STRUCTONEMEMBER:%.*]], align 8, addrspace(5) -// AMDGCN-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN-NEXT: store <2 x i32> [[U_COERCE]], ptr addrspace(5) [[COERCE_DIVE]], align 8 -// AMDGCN-NEXT: [[COERCE_DIVE1:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr addrspace(5) [[COERCE_DIVE1]], align 8 +// AMDGCN-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN-NEXT: store <2 x i32> [[U_COERCE]], ptr [[COERCE_DIVE]], align 8 +// AMDGCN-NEXT: [[COERCE_DIVE2:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[COERCE_DIVE2]], align 8 // AMDGCN-NEXT: call void @FuncOneMember(<2 x i32> [[TMP0]]) #[[ATTR3]] // AMDGCN-NEXT: ret void // @@ -207,12 +224,13 @@ kernel void KernelOneMember(struct StructOneMember u) { FuncOneMember(u); } -// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelOneMemberSpir -// AMDGCN-SAME: (ptr addrspace(1) noundef align 8 [[U:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META14:![0-9]+]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META15:![0-9]+]] !kernel_arg_base_type [[META15]] !kernel_arg_type_qual [[META13]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelOneMemberSpir( +// AMDGCN-SAME: ptr addrspace(1) noundef align 8 [[U:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META14:![0-9]+]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META15:![0-9]+]] !kernel_arg_base_type [[META15]] !kernel_arg_type_qual [[META13]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[U_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) -// AMDGCN-NEXT: store ptr addrspace(1) [[U]], ptr addrspace(5) [[U_ADDR]], align 8 -// AMDGCN-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[U_ADDR]], align 8 +// AMDGCN-NEXT: [[U_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[U_ADDR]] to ptr +// AMDGCN-NEXT: store ptr addrspace(1) [[U]], ptr [[U_ADDR_ASCAST]], align 8 +// AMDGCN-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[U_ADDR_ASCAST]], align 8 // AMDGCN-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTONEMEMBER:%.*]], ptr addrspace(1) [[TMP0]], i32 0, i32 0 // AMDGCN-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr addrspace(1) [[COERCE_DIVE]], align 8 // AMDGCN-NEXT: call void @FuncOneMember(<2 x i32> [[TMP1]]) #[[ATTR3]] @@ -222,70 +240,78 @@ kernel void KernelOneMemberSpir(global struct StructOneMember* u) { FuncOneMember(*u); } -// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelLargeOneMember -// AMDGCN-SAME: ([[STRUCT_LARGESTRUCTONEMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META16:![0-9]+]] !kernel_arg_base_type [[META16]] !kernel_arg_type_qual [[META13]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelLargeOneMember( +// AMDGCN-SAME: [[STRUCT_LARGESTRUCTONEMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META16:![0-9]+]] !kernel_arg_base_type [[META16]] !kernel_arg_type_qual [[META13]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[U:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) -// AMDGCN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTONEMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 +// AMDGCN-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGESTRUCTONEMEMBER]], align 8, addrspace(5) +// AMDGCN-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTONEMEMBER]], ptr [[U1]], i32 0, i32 0 // AMDGCN-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_LARGESTRUCTONEMEMBER]] [[U_COERCE]], 0 -// AMDGCN-NEXT: store [100 x <2 x i32>] [[TMP1]], ptr addrspace(5) [[TMP0]], align 8 -// AMDGCN-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[U]]) #[[ATTR3]] +// AMDGCN-NEXT: store [100 x <2 x i32>] [[TMP1]], ptr [[TMP0]], align 8 +// AMDGCN-NEXT: call void @llvm.memcpy.p5.p0.i64(ptr addrspace(5) align 8 [[BYVAL_TEMP]], ptr align 8 [[U1]], i64 800, i1 false) +// AMDGCN-NEXT: call void @FuncOneLargeMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTONEMEMBER]]) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] // AMDGCN-NEXT: ret void // kernel void KernelLargeOneMember(struct LargeStructOneMember u) { FuncOneLargeMember(u); } -// AMDGCN-LABEL: define dso_local void @FuncTwoMember -// AMDGCN-SAME: (<2 x i32> [[U_COERCE0:%.*]], <2 x i32> [[U_COERCE1:%.*]]) #[[ATTR0]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local void @FuncTwoMember( +// AMDGCN-SAME: <2 x i32> [[U_COERCE0:%.*]], <2 x i32> [[U_COERCE1:%.*]]) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[U:%.*]] = alloca [[STRUCT_STRUCTTWOMEMBER:%.*]], align 8, addrspace(5) // AMDGCN-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca <2 x i32>, align 8, addrspace(5) -// AMDGCN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN-NEXT: store <2 x i32> [[U_COERCE0]], ptr addrspace(5) [[TMP0]], align 8 -// AMDGCN-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 -// AMDGCN-NEXT: store <2 x i32> [[U_COERCE1]], ptr addrspace(5) [[TMP1]], align 8 -// AMDGCN-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 -// AMDGCN-NEXT: store <2 x i32> [[TMP2]], ptr addrspace(5) [[Y]], align 8 +// AMDGCN-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN-NEXT: [[DOTCOMPOUNDLITERAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTCOMPOUNDLITERAL]] to ptr +// AMDGCN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN-NEXT: store <2 x i32> [[U_COERCE0]], ptr [[TMP0]], align 8 +// AMDGCN-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 +// AMDGCN-NEXT: store <2 x i32> [[U_COERCE1]], ptr [[TMP1]], align 8 +// AMDGCN-NEXT: store <2 x i32> zeroinitializer, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 +// AMDGCN-NEXT: store <2 x i32> [[TMP2]], ptr [[Y]], align 8 // AMDGCN-NEXT: ret void // void FuncTwoMember(struct StructTwoMember u) { u.y = (int2)(0, 0); } -// AMDGCN-LABEL: define dso_local void @FuncLargeTwoMember -// AMDGCN-SAME: (ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTTWOMEMBER:%.*]]) align 8 [[TMP0:%.*]]) #[[ATTR0]] { -// AMDGCN-NEXT: entry: -// AMDGCN-NEXT: [[U:%.*]] = alloca [[STRUCT_LARGESTRUCTTWOMEMBER]], align 8, addrspace(5) +// AMDGCN-LABEL: define dso_local void @FuncLargeTwoMember( +// AMDGCN-SAME: ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTTWOMEMBER:%.*]]) align 8 [[TMP0:%.*]]) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] +// AMDGCN-NEXT: [[COERCE:%.*]] = alloca [[STRUCT_LARGESTRUCTTWOMEMBER]], align 8, addrspace(5) // AMDGCN-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca <2 x i32>, align 8, addrspace(5) -// AMDGCN-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 8 [[U]], ptr addrspace(5) align 8 [[TMP0]], i64 480, i1 false) -// AMDGCN-NEXT: store <2 x i32> zeroinitializer, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr addrspace(5) [[DOTCOMPOUNDLITERAL]], align 8 -// AMDGCN-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 -// AMDGCN-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [20 x <2 x i32>], ptr addrspace(5) [[Y]], i64 0, i64 0 -// AMDGCN-NEXT: store <2 x i32> [[TMP1]], ptr addrspace(5) [[ARRAYIDX]], align 8 +// AMDGCN-NEXT: [[U:%.*]] = addrspacecast ptr addrspace(5) [[COERCE]] to ptr +// AMDGCN-NEXT: [[DOTCOMPOUNDLITERAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTCOMPOUNDLITERAL]] to ptr +// AMDGCN-NEXT: call void @llvm.memcpy.p0.p5.i64(ptr align 8 [[U]], ptr addrspace(5) align 8 [[TMP0]], i64 480, i1 false) +// AMDGCN-NEXT: store <2 x i32> zeroinitializer, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[DOTCOMPOUNDLITERAL_ASCAST]], align 8 +// AMDGCN-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr [[U]], i32 0, i32 1 +// AMDGCN-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [20 x <2 x i32>], ptr [[Y]], i64 0, i64 0 +// AMDGCN-NEXT: store <2 x i32> [[TMP1]], ptr [[ARRAYIDX]], align 8 // AMDGCN-NEXT: ret void // void FuncLargeTwoMember(struct LargeStructTwoMember u) { u.y[0] = (int2)(0, 0); } -// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelTwoMember -// AMDGCN-SAME: ([[STRUCT_STRUCTTWOMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META17:![0-9]+]] !kernel_arg_base_type [[META17]] !kernel_arg_type_qual [[META13]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelTwoMember( +// AMDGCN-SAME: [[STRUCT_STRUCTTWOMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META17:![0-9]+]] !kernel_arg_base_type [[META17]] !kernel_arg_type_qual [[META13]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[U:%.*]] = alloca [[STRUCT_STRUCTTWOMEMBER]], align 8, addrspace(5) -// AMDGCN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 +// AMDGCN-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 0 // AMDGCN-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_STRUCTTWOMEMBER]] [[U_COERCE]], 0 -// AMDGCN-NEXT: store <2 x i32> [[TMP1]], ptr addrspace(5) [[TMP0]], align 8 -// AMDGCN-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 +// AMDGCN-NEXT: store <2 x i32> [[TMP1]], ptr [[TMP0]], align 8 +// AMDGCN-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 // AMDGCN-NEXT: [[TMP3:%.*]] = extractvalue [[STRUCT_STRUCTTWOMEMBER]] [[U_COERCE]], 1 -// AMDGCN-NEXT: store <2 x i32> [[TMP3]], ptr addrspace(5) [[TMP2]], align 8 -// AMDGCN-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 -// AMDGCN-NEXT: [[TMP5:%.*]] = load <2 x i32>, ptr addrspace(5) [[TMP4]], align 8 -// AMDGCN-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 -// AMDGCN-NEXT: [[TMP7:%.*]] = load <2 x i32>, ptr addrspace(5) [[TMP6]], align 8 +// AMDGCN-NEXT: store <2 x i32> [[TMP3]], ptr [[TMP2]], align 8 +// AMDGCN-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 0 +// AMDGCN-NEXT: [[TMP5:%.*]] = load <2 x i32>, ptr [[TMP4]], align 8 +// AMDGCN-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_STRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 +// AMDGCN-NEXT: [[TMP7:%.*]] = load <2 x i32>, ptr [[TMP6]], align 8 // AMDGCN-NEXT: call void @FuncTwoMember(<2 x i32> [[TMP5]], <2 x i32> [[TMP7]]) #[[ATTR3]] // AMDGCN-NEXT: ret void // @@ -293,19 +319,39 @@ kernel void KernelTwoMember(struct StructTwoMember u) { FuncTwoMember(u); } -// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelLargeTwoMember -// AMDGCN-SAME: ([[STRUCT_LARGESTRUCTTWOMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META18:![0-9]+]] !kernel_arg_base_type [[META18]] !kernel_arg_type_qual [[META13]] { -// AMDGCN-NEXT: entry: +// AMDGCN-LABEL: define dso_local amdgpu_kernel void @KernelLargeTwoMember( +// AMDGCN-SAME: [[STRUCT_LARGESTRUCTTWOMEMBER:%.*]] [[U_COERCE:%.*]]) #[[ATTR1]] !kernel_arg_addr_space [[META10]] !kernel_arg_access_qual [[META11]] !kernel_arg_type [[META18:![0-9]+]] !kernel_arg_base_type [[META18]] !kernel_arg_type_qual [[META13]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] // AMDGCN-NEXT: [[U:%.*]] = alloca [[STRUCT_LARGESTRUCTTWOMEMBER]], align 8, addrspace(5) -// AMDGCN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 0 +// AMDGCN-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGESTRUCTTWOMEMBER]], align 8, addrspace(5) +// AMDGCN-NEXT: [[U1:%.*]] = addrspacecast ptr addrspace(5) [[U]] to ptr +// AMDGCN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 0 // AMDGCN-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_LARGESTRUCTTWOMEMBER]] [[U_COERCE]], 0 -// AMDGCN-NEXT: store [40 x <2 x i32>] [[TMP1]], ptr addrspace(5) [[TMP0]], align 8 -// AMDGCN-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr addrspace(5) [[U]], i32 0, i32 1 +// AMDGCN-NEXT: store [40 x <2 x i32>] [[TMP1]], ptr [[TMP0]], align 8 +// AMDGCN-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGESTRUCTTWOMEMBER]], ptr [[U1]], i32 0, i32 1 // AMDGCN-NEXT: [[TMP3:%.*]] = extractvalue [[STRUCT_LARGESTRUCTTWOMEMBER]] [[U_COERCE]], 1 -// AMDGCN-NEXT: store [20 x <2 x i32>] [[TMP3]], ptr addrspace(5) [[TMP2]], align 8 -// AMDGCN-NEXT: call void @FuncLargeTwoMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTTWOMEMBER]]) align 8 [[U]]) #[[ATTR3]] +// AMDGCN-NEXT: store [20 x <2 x i32>] [[TMP3]], ptr [[TMP2]], align 8 +// AMDGCN-NEXT: call void @llvm.memcpy.p5.p0.i64(ptr addrspace(5) align 8 [[BYVAL_TEMP]], ptr align 8 [[U1]], i64 480, i1 false) +// AMDGCN-NEXT: call void @FuncLargeTwoMember(ptr addrspace(5) noundef byref([[STRUCT_LARGESTRUCTTWOMEMBER]]) align 8 [[BYVAL_TEMP]]) #[[ATTR3]] // AMDGCN-NEXT: ret void // kernel void KernelLargeTwoMember(struct LargeStructTwoMember u) { FuncLargeTwoMember(u); } +//. +// AMDGCN: [[META4]] = !{i32 1, i32 1} +// AMDGCN: [[META5]] = !{!"none", !"none"} +// AMDGCN: [[META6]] = !{!"Mat3X3*", !"Mat4X4*"} +// AMDGCN: [[META7]] = !{!"", !""} +// AMDGCN: [[META8]] = !{!"Mat32X32*", !"Mat64X64*"} +// AMDGCN: [[META9]] = !{} +// AMDGCN: [[META10]] = !{i32 0} +// AMDGCN: [[META11]] = !{!"none"} +// AMDGCN: [[META12]] = !{!"struct StructOneMember"} +// AMDGCN: [[META13]] = !{!""} +// AMDGCN: [[META14]] = !{i32 1} +// AMDGCN: [[META15]] = !{!"struct StructOneMember*"} +// AMDGCN: [[META16]] = !{!"struct LargeStructOneMember"} +// AMDGCN: [[META17]] = !{!"struct StructTwoMember"} +// AMDGCN: [[META18]] = !{!"struct LargeStructTwoMember"} +//. diff --git a/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl b/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl index 08b28f1814c1f..2fc7f9a24b887 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl @@ -70,11 +70,13 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: entry: // NOCPU-NEXT: [[ID_ADDR:%.*]] = alloca i64, align 8, addrspace(5) // NOCPU-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) -// NOCPU-NEXT: store i64 [[ID]], ptr addrspace(5) [[ID_ADDR]], align 8 -// NOCPU-NEXT: store ptr addrspace(1) [[OUT]], ptr addrspace(5) [[OUT_ADDR]], align 8 -// NOCPU-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(5) [[ID_ADDR]], align 8 -// NOCPU-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 -// NOCPU-NEXT: [[TMP2:%.*]] = load i64, ptr addrspace(5) [[ID_ADDR]], align 8 +// NOCPU-NEXT: [[ID_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ID_ADDR]] to ptr +// NOCPU-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// NOCPU-NEXT: store i64 [[ID]], ptr [[ID_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr addrspace(1) [[OUT]], ptr [[OUT_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP0:%.*]] = load i64, ptr [[ID_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP2:%.*]] = load i64, ptr [[ID_ADDR_ASCAST]], align 8 // NOCPU-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr addrspace(1) [[TMP1]], i64 [[TMP2]] // NOCPU-NEXT: store i64 [[TMP0]], ptr addrspace(1) [[ARRAYIDX]], align 8 // NOCPU-NEXT: ret void @@ -101,96 +103,108 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: [[BLOCK20:%.*]] = alloca ptr, align 8, addrspace(5) // NOCPU-NEXT: [[BLOCK21:%.*]] = alloca <{ i32, i32, ptr, i64, ptr addrspace(1) }>, align 8, addrspace(5) // NOCPU-NEXT: [[VARTMP27:%.*]] = alloca [[STRUCT_NDRANGE_T]], align 4, addrspace(5) -// NOCPU-NEXT: store ptr addrspace(1) [[A]], ptr addrspace(5) [[A_ADDR]], align 8 -// NOCPU-NEXT: store i8 [[B]], ptr addrspace(5) [[B_ADDR]], align 1 -// NOCPU-NEXT: store ptr addrspace(1) [[C]], ptr addrspace(5) [[C_ADDR]], align 8 -// NOCPU-NEXT: store i64 [[D]], ptr addrspace(5) [[D_ADDR]], align 8 -// NOCPU-NEXT: store i32 0, ptr addrspace(5) [[FLAGS]], align 4 -// NOCPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8 -// NOCPU-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4 -// NOCPU-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[TMP]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false) -// NOCPU-NEXT: [[BLOCK_SIZE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 0 -// NOCPU-NEXT: store i32 25, ptr addrspace(5) [[BLOCK_SIZE]], align 8 -// NOCPU-NEXT: [[BLOCK_ALIGN:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 1 -// NOCPU-NEXT: store i32 8, ptr addrspace(5) [[BLOCK_ALIGN]], align 4 -// NOCPU-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 2 -// NOCPU-NEXT: store ptr @__test_block_invoke, ptr addrspace(5) [[BLOCK_INVOKE]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 3 -// NOCPU-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[A_ADDR]], align 8 -// NOCPU-NEXT: store ptr addrspace(1) [[TMP2]], ptr addrspace(5) [[BLOCK_CAPTURED]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 4 -// NOCPU-NEXT: [[TMP3:%.*]] = load i8, ptr addrspace(5) [[B_ADDR]], align 1 -// NOCPU-NEXT: store i8 [[TMP3]], ptr addrspace(5) [[BLOCK_CAPTURED1]], align 8 -// NOCPU-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK]] to ptr -// NOCPU-NEXT: [[TMP5:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr addrspace(5) byval([[STRUCT_NDRANGE_T]]) [[TMP]], ptr @__test_block_invoke_kernel, ptr [[TMP4]]) -// NOCPU-NEXT: [[TMP6:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8 -// NOCPU-NEXT: [[TMP7:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4 -// NOCPU-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[VARTMP2]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false) -// NOCPU-NEXT: [[BLOCK_SIZE4:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 0 -// NOCPU-NEXT: store i32 41, ptr addrspace(5) [[BLOCK_SIZE4]], align 8 -// NOCPU-NEXT: [[BLOCK_ALIGN5:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 1 -// NOCPU-NEXT: store i32 8, ptr addrspace(5) [[BLOCK_ALIGN5]], align 4 -// NOCPU-NEXT: [[BLOCK_INVOKE6:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 2 -// NOCPU-NEXT: store ptr @__test_block_invoke_2, ptr addrspace(5) [[BLOCK_INVOKE6]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED7:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 3 -// NOCPU-NEXT: [[TMP8:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[A_ADDR]], align 8 -// NOCPU-NEXT: store ptr addrspace(1) [[TMP8]], ptr addrspace(5) [[BLOCK_CAPTURED7]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED8:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 6 -// NOCPU-NEXT: [[TMP9:%.*]] = load i8, ptr addrspace(5) [[B_ADDR]], align 1 -// NOCPU-NEXT: store i8 [[TMP9]], ptr addrspace(5) [[BLOCK_CAPTURED8]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED9:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 4 -// NOCPU-NEXT: [[TMP10:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[C_ADDR]], align 8 -// NOCPU-NEXT: store ptr addrspace(1) [[TMP10]], ptr addrspace(5) [[BLOCK_CAPTURED9]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED10:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 5 -// NOCPU-NEXT: [[TMP11:%.*]] = load i64, ptr addrspace(5) [[D_ADDR]], align 8 -// NOCPU-NEXT: store i64 [[TMP11]], ptr addrspace(5) [[BLOCK_CAPTURED10]], align 8 -// NOCPU-NEXT: [[TMP12:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK3]] to ptr -// NOCPU-NEXT: [[TMP13:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP6]], i32 [[TMP7]], ptr addrspace(5) byval([[STRUCT_NDRANGE_T]]) [[VARTMP2]], ptr @__test_block_invoke_2_kernel, ptr [[TMP12]]) -// NOCPU-NEXT: [[TMP14:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8 -// NOCPU-NEXT: [[TMP15:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4 -// NOCPU-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[VARTMP11]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false) -// NOCPU-NEXT: [[BLOCK_SIZE13:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 0 -// NOCPU-NEXT: store i32 41, ptr addrspace(5) [[BLOCK_SIZE13]], align 8 -// NOCPU-NEXT: [[BLOCK_ALIGN14:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 1 -// NOCPU-NEXT: store i32 8, ptr addrspace(5) [[BLOCK_ALIGN14]], align 4 -// NOCPU-NEXT: [[BLOCK_INVOKE15:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 2 -// NOCPU-NEXT: store ptr @__test_block_invoke_3, ptr addrspace(5) [[BLOCK_INVOKE15]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED16:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 3 -// NOCPU-NEXT: [[TMP16:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[A_ADDR]], align 8 -// NOCPU-NEXT: store ptr addrspace(1) [[TMP16]], ptr addrspace(5) [[BLOCK_CAPTURED16]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED17:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 6 -// NOCPU-NEXT: [[TMP17:%.*]] = load i8, ptr addrspace(5) [[B_ADDR]], align 1 -// NOCPU-NEXT: store i8 [[TMP17]], ptr addrspace(5) [[BLOCK_CAPTURED17]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED18:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 4 -// NOCPU-NEXT: [[TMP18:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[C_ADDR]], align 8 -// NOCPU-NEXT: store ptr addrspace(1) [[TMP18]], ptr addrspace(5) [[BLOCK_CAPTURED18]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED19:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 5 -// NOCPU-NEXT: [[TMP19:%.*]] = load i64, ptr addrspace(5) [[D_ADDR]], align 8 -// NOCPU-NEXT: store i64 [[TMP19]], ptr addrspace(5) [[BLOCK_CAPTURED19]], align 8 -// NOCPU-NEXT: [[TMP20:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK12]] to ptr -// NOCPU-NEXT: [[TMP21:%.*]] = getelementptr [1 x i64], ptr addrspace(5) [[BLOCK_SIZES]], i32 0, i32 0 -// NOCPU-NEXT: store i64 100, ptr addrspace(5) [[TMP21]], align 8 -// NOCPU-NEXT: [[TMP22:%.*]] = call i32 @__enqueue_kernel_varargs(ptr addrspace(1) [[TMP14]], i32 [[TMP15]], ptr addrspace(5) [[VARTMP11]], ptr @__test_block_invoke_3_kernel, ptr [[TMP20]], i32 1, ptr addrspace(5) [[TMP21]]) -// NOCPU-NEXT: [[BLOCK_SIZE22:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 0 -// NOCPU-NEXT: store i32 32, ptr addrspace(5) [[BLOCK_SIZE22]], align 8 -// NOCPU-NEXT: [[BLOCK_ALIGN23:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 1 -// NOCPU-NEXT: store i32 8, ptr addrspace(5) [[BLOCK_ALIGN23]], align 4 -// NOCPU-NEXT: [[BLOCK_INVOKE24:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 2 -// NOCPU-NEXT: store ptr @__test_block_invoke_4, ptr addrspace(5) [[BLOCK_INVOKE24]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED25:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 3 -// NOCPU-NEXT: [[TMP23:%.*]] = load i64, ptr addrspace(5) [[D_ADDR]], align 8 -// NOCPU-NEXT: store i64 [[TMP23]], ptr addrspace(5) [[BLOCK_CAPTURED25]], align 8 -// NOCPU-NEXT: [[BLOCK_CAPTURED26:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 4 -// NOCPU-NEXT: [[TMP24:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[C_ADDR]], align 8 -// NOCPU-NEXT: store ptr addrspace(1) [[TMP24]], ptr addrspace(5) [[BLOCK_CAPTURED26]], align 8 +// NOCPU-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// NOCPU-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// NOCPU-NEXT: [[C_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[C_ADDR]] to ptr +// NOCPU-NEXT: [[D_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D_ADDR]] to ptr +// NOCPU-NEXT: [[DEFAULT_QUEUE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DEFAULT_QUEUE]] to ptr +// NOCPU-NEXT: [[FLAGS_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FLAGS]] to ptr +// NOCPU-NEXT: [[NDRANGE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[NDRANGE]] to ptr +// NOCPU-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr +// NOCPU-NEXT: [[BLOCK_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK]] to ptr +// NOCPU-NEXT: [[TMP2_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[VARTMP2]] to ptr +// NOCPU-NEXT: [[BLOCK3_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK3]] to ptr +// NOCPU-NEXT: [[TMP11_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[VARTMP11]] to ptr +// NOCPU-NEXT: [[BLOCK12_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK12]] to ptr +// NOCPU-NEXT: [[BLOCK_SIZES_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK_SIZES]] to ptr +// NOCPU-NEXT: [[BLOCK20_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK20]] to ptr // NOCPU-NEXT: [[BLOCK21_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK21]] to ptr -// NOCPU-NEXT: store ptr [[BLOCK21_ASCAST]], ptr addrspace(5) [[BLOCK20]], align 8 -// NOCPU-NEXT: [[TMP25:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8 -// NOCPU-NEXT: [[TMP26:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4 -// NOCPU-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[VARTMP27]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false) -// NOCPU-NEXT: [[TMP27:%.*]] = load ptr, ptr addrspace(5) [[BLOCK20]], align 8 -// NOCPU-NEXT: [[TMP28:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK21]] to ptr -// NOCPU-NEXT: [[TMP29:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP25]], i32 [[TMP26]], ptr addrspace(5) byval([[STRUCT_NDRANGE_T]]) [[VARTMP27]], ptr @__test_block_invoke_4_kernel, ptr [[TMP28]]) +// NOCPU-NEXT: [[TMP27_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[VARTMP27]] to ptr +// NOCPU-NEXT: store ptr addrspace(1) [[A]], ptr [[A_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store i8 [[B]], ptr [[B_ADDR_ASCAST]], align 1 +// NOCPU-NEXT: store ptr addrspace(1) [[C]], ptr [[C_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store i64 [[D]], ptr [[D_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store i32 0, ptr [[FLAGS_ASCAST]], align 4 +// NOCPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP1:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 +// NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) +// NOCPU-NEXT: [[BLOCK_SIZE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 0 +// NOCPU-NEXT: store i32 25, ptr [[BLOCK_SIZE]], align 8 +// NOCPU-NEXT: [[BLOCK_ALIGN:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 1 +// NOCPU-NEXT: store i32 8, ptr [[BLOCK_ALIGN]], align 4 +// NOCPU-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 2 +// NOCPU-NEXT: store ptr @__test_block_invoke, ptr [[BLOCK_INVOKE]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 3 +// NOCPU-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr addrspace(1) [[TMP2]], ptr [[BLOCK_CAPTURED]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 4 +// NOCPU-NEXT: [[TMP3:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1 +// NOCPU-NEXT: store i8 [[TMP3]], ptr [[BLOCK_CAPTURED1]], align 8 +// NOCPU-NEXT: [[TMP4:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP_ASCAST]], ptr @__test_block_invoke_kernel, ptr [[BLOCK_ASCAST]]) +// NOCPU-NEXT: [[TMP5:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP6:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 +// NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP2_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) +// NOCPU-NEXT: [[BLOCK_SIZE4:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 0 +// NOCPU-NEXT: store i32 41, ptr [[BLOCK_SIZE4]], align 8 +// NOCPU-NEXT: [[BLOCK_ALIGN5:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 1 +// NOCPU-NEXT: store i32 8, ptr [[BLOCK_ALIGN5]], align 4 +// NOCPU-NEXT: [[BLOCK_INVOKE6:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 2 +// NOCPU-NEXT: store ptr @__test_block_invoke_2, ptr [[BLOCK_INVOKE6]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED7:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 3 +// NOCPU-NEXT: [[TMP7:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr addrspace(1) [[TMP7]], ptr [[BLOCK_CAPTURED7]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED8:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 6 +// NOCPU-NEXT: [[TMP8:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1 +// NOCPU-NEXT: store i8 [[TMP8]], ptr [[BLOCK_CAPTURED8]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED9:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 4 +// NOCPU-NEXT: [[TMP9:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr addrspace(1) [[TMP9]], ptr [[BLOCK_CAPTURED9]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED10:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 5 +// NOCPU-NEXT: [[TMP10:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store i64 [[TMP10]], ptr [[BLOCK_CAPTURED10]], align 8 +// NOCPU-NEXT: [[TMP11:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP5]], i32 [[TMP6]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP2_ASCAST]], ptr @__test_block_invoke_2_kernel, ptr [[BLOCK3_ASCAST]]) +// NOCPU-NEXT: [[TMP12:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP13:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 +// NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP11_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) +// NOCPU-NEXT: [[BLOCK_SIZE13:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 0 +// NOCPU-NEXT: store i32 41, ptr [[BLOCK_SIZE13]], align 8 +// NOCPU-NEXT: [[BLOCK_ALIGN14:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 1 +// NOCPU-NEXT: store i32 8, ptr [[BLOCK_ALIGN14]], align 4 +// NOCPU-NEXT: [[BLOCK_INVOKE15:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 2 +// NOCPU-NEXT: store ptr @__test_block_invoke_3, ptr [[BLOCK_INVOKE15]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED16:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 3 +// NOCPU-NEXT: [[TMP14:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr addrspace(1) [[TMP14]], ptr [[BLOCK_CAPTURED16]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED17:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 6 +// NOCPU-NEXT: [[TMP15:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1 +// NOCPU-NEXT: store i8 [[TMP15]], ptr [[BLOCK_CAPTURED17]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED18:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 4 +// NOCPU-NEXT: [[TMP16:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr addrspace(1) [[TMP16]], ptr [[BLOCK_CAPTURED18]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED19:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 5 +// NOCPU-NEXT: [[TMP17:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store i64 [[TMP17]], ptr [[BLOCK_CAPTURED19]], align 8 +// NOCPU-NEXT: [[TMP18:%.*]] = getelementptr [1 x i64], ptr [[BLOCK_SIZES_ASCAST]], i32 0, i32 0 +// NOCPU-NEXT: store i64 100, ptr [[TMP18]], align 8 +// NOCPU-NEXT: [[TMP19:%.*]] = call i32 @__enqueue_kernel_varargs(ptr addrspace(1) [[TMP12]], i32 [[TMP13]], ptr [[TMP11_ASCAST]], ptr @__test_block_invoke_3_kernel, ptr [[BLOCK12_ASCAST]], i32 1, ptr [[TMP18]]) +// NOCPU-NEXT: [[BLOCK_SIZE22:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 0 +// NOCPU-NEXT: store i32 32, ptr [[BLOCK_SIZE22]], align 8 +// NOCPU-NEXT: [[BLOCK_ALIGN23:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 1 +// NOCPU-NEXT: store i32 8, ptr [[BLOCK_ALIGN23]], align 4 +// NOCPU-NEXT: [[BLOCK_INVOKE24:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 2 +// NOCPU-NEXT: store ptr @__test_block_invoke_4, ptr [[BLOCK_INVOKE24]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED25:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 3 +// NOCPU-NEXT: [[TMP20:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store i64 [[TMP20]], ptr [[BLOCK_CAPTURED25]], align 8 +// NOCPU-NEXT: [[BLOCK_CAPTURED26:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 4 +// NOCPU-NEXT: [[TMP21:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr addrspace(1) [[TMP21]], ptr [[BLOCK_CAPTURED26]], align 8 +// NOCPU-NEXT: store ptr [[BLOCK21_ASCAST]], ptr [[BLOCK20_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP22:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP23:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 +// NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP27_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) +// NOCPU-NEXT: [[TMP24:%.*]] = load ptr, ptr [[BLOCK20_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP25:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP22]], i32 [[TMP23]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP27_ASCAST]], ptr @__test_block_invoke_4_kernel, ptr [[BLOCK21_ASCAST]]) // NOCPU-NEXT: ret void // // @@ -200,8 +214,10 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: entry: // NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // NOCPU-NEXT: [[BLOCK_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[BLOCK_ADDR]], align 8 +// NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// NOCPU-NEXT: [[BLOCK_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK_ADDR]] to ptr +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[BLOCK_ADDR_ASCAST]], align 8 // NOCPU-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 4 // NOCPU-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8 // NOCPU-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 @@ -228,8 +244,10 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: entry: // NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // NOCPU-NEXT: [[BLOCK_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[BLOCK_ADDR]], align 8 +// NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// NOCPU-NEXT: [[BLOCK_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK_ADDR]] to ptr +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[BLOCK_ADDR_ASCAST]], align 8 // NOCPU-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 // NOCPU-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8 // NOCPU-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 @@ -263,9 +281,12 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // NOCPU-NEXT: [[LP_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) // NOCPU-NEXT: [[BLOCK_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 -// NOCPU-NEXT: store ptr addrspace(3) [[LP]], ptr addrspace(5) [[LP_ADDR]], align 4 -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[BLOCK_ADDR]], align 8 +// NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// NOCPU-NEXT: [[LP_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LP_ADDR]] to ptr +// NOCPU-NEXT: [[BLOCK_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK_ADDR]] to ptr +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr addrspace(3) [[LP]], ptr [[LP_ADDR_ASCAST]], align 4 +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[BLOCK_ADDR_ASCAST]], align 8 // NOCPU-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 // NOCPU-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8 // NOCPU-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 @@ -278,7 +299,7 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: [[TMP3:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR3]], align 8 // NOCPU-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i64, ptr addrspace(1) [[TMP3]], i64 0 // NOCPU-NEXT: store i64 [[TMP2]], ptr addrspace(1) [[ARRAYIDX4]], align 8 -// NOCPU-NEXT: [[TMP4:%.*]] = load ptr addrspace(3), ptr addrspace(5) [[LP_ADDR]], align 4 +// NOCPU-NEXT: [[TMP4:%.*]] = load ptr addrspace(3), ptr [[LP_ADDR_ASCAST]], align 4 // NOCPU-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr addrspace(3) [[TMP4]], i64 0 // NOCPU-NEXT: store i32 1, ptr addrspace(3) [[ARRAYIDX5]], align 4 // NOCPU-NEXT: ret void @@ -301,8 +322,10 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: entry: // NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // NOCPU-NEXT: [[BLOCK_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[BLOCK_ADDR]], align 8 +// NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// NOCPU-NEXT: [[BLOCK_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK_ADDR]] to ptr +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[BLOCK_ADDR_ASCAST]], align 8 // NOCPU-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 // NOCPU-NEXT: [[TMP0:%.*]] = load i64, ptr [[BLOCK_CAPTURE_ADDR]], align 8 // NOCPU-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 4 @@ -331,13 +354,18 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: [[FLAGS:%.*]] = alloca i32, align 4, addrspace(5) // NOCPU-NEXT: [[NDRANGE:%.*]] = alloca [[STRUCT_NDRANGE_T:%.*]], align 4, addrspace(5) // NOCPU-NEXT: [[TMP:%.*]] = alloca [[STRUCT_NDRANGE_T]], align 4, addrspace(5) -// NOCPU-NEXT: store ptr addrspace(1) [[I]], ptr addrspace(5) [[I_ADDR]], align 8 -// NOCPU-NEXT: store i32 0, ptr addrspace(5) [[FLAGS]], align 4 +// NOCPU-NEXT: [[I_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[I_ADDR]] to ptr +// NOCPU-NEXT: [[DEFAULT_QUEUE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DEFAULT_QUEUE]] to ptr +// NOCPU-NEXT: [[FLAGS_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FLAGS]] to ptr +// NOCPU-NEXT: [[NDRANGE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[NDRANGE]] to ptr +// NOCPU-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr +// NOCPU-NEXT: store ptr addrspace(1) [[I]], ptr [[I_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store i32 0, ptr [[FLAGS_ASCAST]], align 4 // NOCPU-NEXT: [[TMP0:%.*]] = call i64 @llvm.amdgcn.s.memtime() -// NOCPU-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8 -// NOCPU-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4 -// NOCPU-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[TMP]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false) -// NOCPU-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr addrspace(5) byval([[STRUCT_NDRANGE_T]]) [[TMP]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) +// NOCPU-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8 +// NOCPU-NEXT: [[TMP2:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 +// NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) +// NOCPU-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP_ASCAST]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) // NOCPU-NEXT: ret void // // @@ -347,8 +375,10 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: entry: // NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // NOCPU-NEXT: [[BLOCK_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 -// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[BLOCK_ADDR]], align 8 +// NOCPU-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// NOCPU-NEXT: [[BLOCK_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK_ADDR]] to ptr +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 +// NOCPU-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[BLOCK_ADDR_ASCAST]], align 8 // NOCPU-NEXT: [[TMP0:%.*]] = call i64 @llvm.amdgcn.s.memtime() // NOCPU-NEXT: ret void // @@ -383,11 +413,13 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: entry: // GFX900-NEXT: [[ID_ADDR:%.*]] = alloca i64, align 8, addrspace(5) // GFX900-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) -// GFX900-NEXT: store i64 [[ID]], ptr addrspace(5) [[ID_ADDR]], align 8, !tbaa [[TBAA3:![0-9]+]] -// GFX900-NEXT: store ptr addrspace(1) [[OUT]], ptr addrspace(5) [[OUT_ADDR]], align 8, !tbaa [[TBAA7:![0-9]+]] -// GFX900-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(5) [[ID_ADDR]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: [[TMP2:%.*]] = load i64, ptr addrspace(5) [[ID_ADDR]], align 8, !tbaa [[TBAA3]] +// GFX900-NEXT: [[ID_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ID_ADDR]] to ptr +// GFX900-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// GFX900-NEXT: store i64 [[ID]], ptr [[ID_ADDR_ASCAST]], align 8, !tbaa [[TBAA3:![0-9]+]] +// GFX900-NEXT: store ptr addrspace(1) [[OUT]], ptr [[OUT_ADDR_ASCAST]], align 8, !tbaa [[TBAA7:![0-9]+]] +// GFX900-NEXT: [[TMP0:%.*]] = load i64, ptr [[ID_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] +// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP2:%.*]] = load i64, ptr [[ID_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr addrspace(1) [[TMP1]], i64 [[TMP2]] // GFX900-NEXT: store i64 [[TMP0]], ptr addrspace(1) [[ARRAYIDX]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: ret void @@ -414,102 +446,114 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[BLOCK20:%.*]] = alloca ptr, align 8, addrspace(5) // GFX900-NEXT: [[BLOCK21:%.*]] = alloca <{ i32, i32, ptr, i64, ptr addrspace(1) }>, align 8, addrspace(5) // GFX900-NEXT: [[VARTMP27:%.*]] = alloca [[STRUCT_NDRANGE_T]], align 4, addrspace(5) -// GFX900-NEXT: store ptr addrspace(1) [[A]], ptr addrspace(5) [[A_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store i8 [[B]], ptr addrspace(5) [[B_ADDR]], align 1, !tbaa [[TBAA13:![0-9]+]] -// GFX900-NEXT: store ptr addrspace(1) [[C]], ptr addrspace(5) [[C_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store i64 [[D]], ptr addrspace(5) [[D_ADDR]], align 8, !tbaa [[TBAA3]] +// GFX900-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// GFX900-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// GFX900-NEXT: [[C_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[C_ADDR]] to ptr +// GFX900-NEXT: [[D_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D_ADDR]] to ptr +// GFX900-NEXT: [[DEFAULT_QUEUE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DEFAULT_QUEUE]] to ptr +// GFX900-NEXT: [[FLAGS_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FLAGS]] to ptr +// GFX900-NEXT: [[NDRANGE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[NDRANGE]] to ptr +// GFX900-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr +// GFX900-NEXT: [[BLOCK_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK]] to ptr +// GFX900-NEXT: [[TMP2_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[VARTMP2]] to ptr +// GFX900-NEXT: [[BLOCK3_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK3]] to ptr +// GFX900-NEXT: [[TMP11_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[VARTMP11]] to ptr +// GFX900-NEXT: [[BLOCK12_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK12]] to ptr +// GFX900-NEXT: [[BLOCK_SIZES_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK_SIZES]] to ptr +// GFX900-NEXT: [[BLOCK20_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK20]] to ptr +// GFX900-NEXT: [[BLOCK21_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK21]] to ptr +// GFX900-NEXT: [[TMP27_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[VARTMP27]] to ptr +// GFX900-NEXT: store ptr addrspace(1) [[A]], ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store i8 [[B]], ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13:![0-9]+]] +// GFX900-NEXT: store ptr addrspace(1) [[C]], ptr [[C_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store i64 [[D]], ptr [[D_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[DEFAULT_QUEUE]]) #[[ATTR8:[0-9]+]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] -// GFX900-NEXT: store i32 0, ptr addrspace(5) [[FLAGS]], align 4, !tbaa [[TBAA14:![0-9]+]] +// GFX900-NEXT: store i32 0, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14:![0-9]+]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] -// GFX900-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8, !tbaa [[TBAA16:![0-9]+]] -// GFX900-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[TMP]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18:![0-9]+]] -// GFX900-NEXT: [[BLOCK_SIZE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 0 -// GFX900-NEXT: store i32 25, ptr addrspace(5) [[BLOCK_SIZE]], align 8 -// GFX900-NEXT: [[BLOCK_ALIGN:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 1 -// GFX900-NEXT: store i32 8, ptr addrspace(5) [[BLOCK_ALIGN]], align 4 -// GFX900-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 2 -// GFX900-NEXT: store ptr @__test_block_invoke, ptr addrspace(5) [[BLOCK_INVOKE]], align 8 -// GFX900-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 3 -// GFX900-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[A_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP2]], ptr addrspace(5) [[BLOCK_CAPTURED]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: [[BLOCK_CAPTURED1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr addrspace(5) [[BLOCK]], i32 0, i32 4 -// GFX900-NEXT: [[TMP3:%.*]] = load i8, ptr addrspace(5) [[B_ADDR]], align 1, !tbaa [[TBAA13]] -// GFX900-NEXT: store i8 [[TMP3]], ptr addrspace(5) [[BLOCK_CAPTURED1]], align 8, !tbaa [[TBAA13]] -// GFX900-NEXT: [[TMP4:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK]] to ptr -// GFX900-NEXT: [[TMP5:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr addrspace(5) byval([[STRUCT_NDRANGE_T]]) [[TMP]], ptr @__test_block_invoke_kernel, ptr [[TMP4]]) -// GFX900-NEXT: [[TMP6:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8, !tbaa [[TBAA16]] -// GFX900-NEXT: [[TMP7:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[VARTMP2]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] -// GFX900-NEXT: [[BLOCK_SIZE4:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 0 -// GFX900-NEXT: store i32 41, ptr addrspace(5) [[BLOCK_SIZE4]], align 8 -// GFX900-NEXT: [[BLOCK_ALIGN5:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 1 -// GFX900-NEXT: store i32 8, ptr addrspace(5) [[BLOCK_ALIGN5]], align 4 -// GFX900-NEXT: [[BLOCK_INVOKE6:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 2 -// GFX900-NEXT: store ptr @__test_block_invoke_2, ptr addrspace(5) [[BLOCK_INVOKE6]], align 8 -// GFX900-NEXT: [[BLOCK_CAPTURED7:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 3 -// GFX900-NEXT: [[TMP8:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[A_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP8]], ptr addrspace(5) [[BLOCK_CAPTURED7]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: [[BLOCK_CAPTURED8:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 6 -// GFX900-NEXT: [[TMP9:%.*]] = load i8, ptr addrspace(5) [[B_ADDR]], align 1, !tbaa [[TBAA13]] -// GFX900-NEXT: store i8 [[TMP9]], ptr addrspace(5) [[BLOCK_CAPTURED8]], align 8, !tbaa [[TBAA13]] -// GFX900-NEXT: [[BLOCK_CAPTURED9:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 4 -// GFX900-NEXT: [[TMP10:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[C_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP10]], ptr addrspace(5) [[BLOCK_CAPTURED9]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: [[BLOCK_CAPTURED10:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK3]], i32 0, i32 5 -// GFX900-NEXT: [[TMP11:%.*]] = load i64, ptr addrspace(5) [[D_ADDR]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: store i64 [[TMP11]], ptr addrspace(5) [[BLOCK_CAPTURED10]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: [[TMP12:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK3]] to ptr -// GFX900-NEXT: [[TMP13:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP6]], i32 [[TMP7]], ptr addrspace(5) byval([[STRUCT_NDRANGE_T]]) [[VARTMP2]], ptr @__test_block_invoke_2_kernel, ptr [[TMP12]]) -// GFX900-NEXT: [[TMP14:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8, !tbaa [[TBAA16]] -// GFX900-NEXT: [[TMP15:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[VARTMP11]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] -// GFX900-NEXT: [[BLOCK_SIZE13:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 0 -// GFX900-NEXT: store i32 41, ptr addrspace(5) [[BLOCK_SIZE13]], align 8 -// GFX900-NEXT: [[BLOCK_ALIGN14:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 1 -// GFX900-NEXT: store i32 8, ptr addrspace(5) [[BLOCK_ALIGN14]], align 4 -// GFX900-NEXT: [[BLOCK_INVOKE15:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 2 -// GFX900-NEXT: store ptr @__test_block_invoke_3, ptr addrspace(5) [[BLOCK_INVOKE15]], align 8 -// GFX900-NEXT: [[BLOCK_CAPTURED16:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 3 -// GFX900-NEXT: [[TMP16:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[A_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP16]], ptr addrspace(5) [[BLOCK_CAPTURED16]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: [[BLOCK_CAPTURED17:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 6 -// GFX900-NEXT: [[TMP17:%.*]] = load i8, ptr addrspace(5) [[B_ADDR]], align 1, !tbaa [[TBAA13]] -// GFX900-NEXT: store i8 [[TMP17]], ptr addrspace(5) [[BLOCK_CAPTURED17]], align 8, !tbaa [[TBAA13]] -// GFX900-NEXT: [[BLOCK_CAPTURED18:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 4 -// GFX900-NEXT: [[TMP18:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[C_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP18]], ptr addrspace(5) [[BLOCK_CAPTURED18]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: [[BLOCK_CAPTURED19:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr addrspace(5) [[BLOCK12]], i32 0, i32 5 -// GFX900-NEXT: [[TMP19:%.*]] = load i64, ptr addrspace(5) [[D_ADDR]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: store i64 [[TMP19]], ptr addrspace(5) [[BLOCK_CAPTURED19]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: [[TMP20:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK12]] to ptr +// GFX900-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16:![0-9]+]] +// GFX900-NEXT: [[TMP1:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18:![0-9]+]] +// GFX900-NEXT: [[BLOCK_SIZE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 0 +// GFX900-NEXT: store i32 25, ptr [[BLOCK_SIZE]], align 8 +// GFX900-NEXT: [[BLOCK_ALIGN:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 1 +// GFX900-NEXT: store i32 8, ptr [[BLOCK_ALIGN]], align 4 +// GFX900-NEXT: [[BLOCK_INVOKE:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 2 +// GFX900-NEXT: store ptr @__test_block_invoke, ptr [[BLOCK_INVOKE]], align 8 +// GFX900-NEXT: [[BLOCK_CAPTURED:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 3 +// GFX900-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP2]], ptr [[BLOCK_CAPTURED]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[BLOCK_CAPTURED1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 4 +// GFX900-NEXT: [[TMP3:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13]] +// GFX900-NEXT: store i8 [[TMP3]], ptr [[BLOCK_CAPTURED1]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP4:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP_ASCAST]], ptr @__test_block_invoke_kernel, ptr [[BLOCK_ASCAST]]) +// GFX900-NEXT: [[TMP5:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] +// GFX900-NEXT: [[TMP6:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP2_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] +// GFX900-NEXT: [[BLOCK_SIZE4:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 0 +// GFX900-NEXT: store i32 41, ptr [[BLOCK_SIZE4]], align 8 +// GFX900-NEXT: [[BLOCK_ALIGN5:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 1 +// GFX900-NEXT: store i32 8, ptr [[BLOCK_ALIGN5]], align 4 +// GFX900-NEXT: [[BLOCK_INVOKE6:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 2 +// GFX900-NEXT: store ptr @__test_block_invoke_2, ptr [[BLOCK_INVOKE6]], align 8 +// GFX900-NEXT: [[BLOCK_CAPTURED7:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 3 +// GFX900-NEXT: [[TMP7:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP7]], ptr [[BLOCK_CAPTURED7]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[BLOCK_CAPTURED8:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 6 +// GFX900-NEXT: [[TMP8:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13]] +// GFX900-NEXT: store i8 [[TMP8]], ptr [[BLOCK_CAPTURED8]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[BLOCK_CAPTURED9:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 4 +// GFX900-NEXT: [[TMP9:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP9]], ptr [[BLOCK_CAPTURED9]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[BLOCK_CAPTURED10:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 5 +// GFX900-NEXT: [[TMP10:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] +// GFX900-NEXT: store i64 [[TMP10]], ptr [[BLOCK_CAPTURED10]], align 8, !tbaa [[TBAA3]] +// GFX900-NEXT: [[TMP11:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP5]], i32 [[TMP6]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP2_ASCAST]], ptr @__test_block_invoke_2_kernel, ptr [[BLOCK3_ASCAST]]) +// GFX900-NEXT: [[TMP12:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] +// GFX900-NEXT: [[TMP13:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP11_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] +// GFX900-NEXT: [[BLOCK_SIZE13:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 0 +// GFX900-NEXT: store i32 41, ptr [[BLOCK_SIZE13]], align 8 +// GFX900-NEXT: [[BLOCK_ALIGN14:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 1 +// GFX900-NEXT: store i32 8, ptr [[BLOCK_ALIGN14]], align 4 +// GFX900-NEXT: [[BLOCK_INVOKE15:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 2 +// GFX900-NEXT: store ptr @__test_block_invoke_3, ptr [[BLOCK_INVOKE15]], align 8 +// GFX900-NEXT: [[BLOCK_CAPTURED16:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 3 +// GFX900-NEXT: [[TMP14:%.*]] = load ptr addrspace(1), ptr [[A_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP14]], ptr [[BLOCK_CAPTURED16]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[BLOCK_CAPTURED17:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 6 +// GFX900-NEXT: [[TMP15:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13]] +// GFX900-NEXT: store i8 [[TMP15]], ptr [[BLOCK_CAPTURED17]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[BLOCK_CAPTURED18:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 4 +// GFX900-NEXT: [[TMP16:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP16]], ptr [[BLOCK_CAPTURED18]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[BLOCK_CAPTURED19:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK12_ASCAST]], i32 0, i32 5 +// GFX900-NEXT: [[TMP17:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] +// GFX900-NEXT: store i64 [[TMP17]], ptr [[BLOCK_CAPTURED19]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[BLOCK_SIZES]]) #[[ATTR8]] -// GFX900-NEXT: [[TMP21:%.*]] = getelementptr [1 x i64], ptr addrspace(5) [[BLOCK_SIZES]], i32 0, i32 0 -// GFX900-NEXT: store i64 100, ptr addrspace(5) [[TMP21]], align 8 -// GFX900-NEXT: [[TMP22:%.*]] = call i32 @__enqueue_kernel_varargs(ptr addrspace(1) [[TMP14]], i32 [[TMP15]], ptr addrspace(5) [[VARTMP11]], ptr @__test_block_invoke_3_kernel, ptr [[TMP20]], i32 1, ptr addrspace(5) [[TMP21]]) +// GFX900-NEXT: [[TMP18:%.*]] = getelementptr [1 x i64], ptr [[BLOCK_SIZES_ASCAST]], i32 0, i32 0 +// GFX900-NEXT: store i64 100, ptr [[TMP18]], align 8 +// GFX900-NEXT: [[TMP19:%.*]] = call i32 @__enqueue_kernel_varargs(ptr addrspace(1) [[TMP12]], i32 [[TMP13]], ptr [[TMP11_ASCAST]], ptr @__test_block_invoke_3_kernel, ptr [[BLOCK12_ASCAST]], i32 1, ptr [[TMP18]]) // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[BLOCK_SIZES]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[BLOCK20]]) #[[ATTR8]] -// GFX900-NEXT: [[BLOCK_SIZE22:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 0 -// GFX900-NEXT: store i32 32, ptr addrspace(5) [[BLOCK_SIZE22]], align 8 -// GFX900-NEXT: [[BLOCK_ALIGN23:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 1 -// GFX900-NEXT: store i32 8, ptr addrspace(5) [[BLOCK_ALIGN23]], align 4 -// GFX900-NEXT: [[BLOCK_INVOKE24:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 2 -// GFX900-NEXT: store ptr @__test_block_invoke_4, ptr addrspace(5) [[BLOCK_INVOKE24]], align 8 -// GFX900-NEXT: [[BLOCK_CAPTURED25:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 3 -// GFX900-NEXT: [[TMP23:%.*]] = load i64, ptr addrspace(5) [[D_ADDR]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: store i64 [[TMP23]], ptr addrspace(5) [[BLOCK_CAPTURED25]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: [[BLOCK_CAPTURED26:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr addrspace(5) [[BLOCK21]], i32 0, i32 4 -// GFX900-NEXT: [[TMP24:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[C_ADDR]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: store ptr addrspace(1) [[TMP24]], ptr addrspace(5) [[BLOCK_CAPTURED26]], align 8, !tbaa [[TBAA7]] -// GFX900-NEXT: [[BLOCK21_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK21]] to ptr -// GFX900-NEXT: store ptr [[BLOCK21_ASCAST]], ptr addrspace(5) [[BLOCK20]], align 8, !tbaa [[TBAA13]] -// GFX900-NEXT: [[TMP25:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8, !tbaa [[TBAA16]] -// GFX900-NEXT: [[TMP26:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[VARTMP27]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] -// GFX900-NEXT: [[TMP27:%.*]] = load ptr, ptr addrspace(5) [[BLOCK20]], align 8, !tbaa [[TBAA13]] -// GFX900-NEXT: [[TMP28:%.*]] = addrspacecast ptr addrspace(5) [[BLOCK21]] to ptr -// GFX900-NEXT: [[TMP29:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP25]], i32 [[TMP26]], ptr addrspace(5) byval([[STRUCT_NDRANGE_T]]) [[VARTMP27]], ptr @__test_block_invoke_4_kernel, ptr [[TMP28]]) +// GFX900-NEXT: [[BLOCK_SIZE22:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 0 +// GFX900-NEXT: store i32 32, ptr [[BLOCK_SIZE22]], align 8 +// GFX900-NEXT: [[BLOCK_ALIGN23:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 1 +// GFX900-NEXT: store i32 8, ptr [[BLOCK_ALIGN23]], align 4 +// GFX900-NEXT: [[BLOCK_INVOKE24:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 2 +// GFX900-NEXT: store ptr @__test_block_invoke_4, ptr [[BLOCK_INVOKE24]], align 8 +// GFX900-NEXT: [[BLOCK_CAPTURED25:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 3 +// GFX900-NEXT: [[TMP20:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] +// GFX900-NEXT: store i64 [[TMP20]], ptr [[BLOCK_CAPTURED25]], align 8, !tbaa [[TBAA3]] +// GFX900-NEXT: [[BLOCK_CAPTURED26:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[BLOCK21_ASCAST]], i32 0, i32 4 +// GFX900-NEXT: [[TMP21:%.*]] = load ptr addrspace(1), ptr [[C_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr addrspace(1) [[TMP21]], ptr [[BLOCK_CAPTURED26]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: store ptr [[BLOCK21_ASCAST]], ptr [[BLOCK20_ASCAST]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP22:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] +// GFX900-NEXT: [[TMP23:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP27_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] +// GFX900-NEXT: [[TMP24:%.*]] = load ptr, ptr [[BLOCK20_ASCAST]], align 8, !tbaa [[TBAA13]] +// GFX900-NEXT: [[TMP25:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP22]], i32 [[TMP23]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP27_ASCAST]], ptr @__test_block_invoke_4_kernel, ptr [[BLOCK21_ASCAST]]) // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[BLOCK20]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] @@ -522,7 +566,8 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-SAME: (ptr noundef [[DOTBLOCK_DESCRIPTOR:%.*]]) #[[ATTR5:[0-9]+]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 +// GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 4 // GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA13]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 @@ -548,7 +593,8 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-SAME: (ptr noundef [[DOTBLOCK_DESCRIPTOR:%.*]]) #[[ATTR5]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 +// GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 // GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA13]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 @@ -581,8 +627,10 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: entry: // GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // GFX900-NEXT: [[LP_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) -// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 -// GFX900-NEXT: store ptr addrspace(3) [[LP]], ptr addrspace(5) [[LP_ADDR]], align 4, !tbaa [[TBAA7]] +// GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// GFX900-NEXT: [[LP_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LP_ADDR]] to ptr +// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 +// GFX900-NEXT: store ptr addrspace(3) [[LP]], ptr [[LP_ADDR_ASCAST]], align 4, !tbaa [[TBAA7]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 6 // GFX900-NEXT: [[TMP0:%.*]] = load i8, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA13]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 @@ -595,7 +643,7 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[TMP3:%.*]] = load ptr addrspace(1), ptr [[BLOCK_CAPTURE_ADDR3]], align 8, !tbaa [[TBAA7]] // GFX900-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i64, ptr addrspace(1) [[TMP3]], i64 0 // GFX900-NEXT: store i64 [[TMP2]], ptr addrspace(1) [[ARRAYIDX4]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: [[TMP4:%.*]] = load ptr addrspace(3), ptr addrspace(5) [[LP_ADDR]], align 4, !tbaa [[TBAA7]] +// GFX900-NEXT: [[TMP4:%.*]] = load ptr addrspace(3), ptr [[LP_ADDR_ASCAST]], align 4, !tbaa [[TBAA7]] // GFX900-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr addrspace(3) [[TMP4]], i64 0 // GFX900-NEXT: store i32 1, ptr addrspace(3) [[ARRAYIDX5]], align 4, !tbaa [[TBAA14]] // GFX900-NEXT: ret void @@ -617,7 +665,8 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-SAME: (ptr noundef [[DOTBLOCK_DESCRIPTOR:%.*]]) #[[ATTR5]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 +// GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 3 // GFX900-NEXT: [[TMP0:%.*]] = load i64, ptr [[BLOCK_CAPTURE_ADDR]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: [[BLOCK_CAPTURE_ADDR1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i64, ptr addrspace(1) }>, ptr [[DOTBLOCK_DESCRIPTOR]], i32 0, i32 4 @@ -646,16 +695,21 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[FLAGS:%.*]] = alloca i32, align 4, addrspace(5) // GFX900-NEXT: [[NDRANGE:%.*]] = alloca [[STRUCT_NDRANGE_T:%.*]], align 4, addrspace(5) // GFX900-NEXT: [[TMP:%.*]] = alloca [[STRUCT_NDRANGE_T]], align 4, addrspace(5) -// GFX900-NEXT: store ptr addrspace(1) [[I]], ptr addrspace(5) [[I_ADDR]], align 8, !tbaa [[TBAA7]] +// GFX900-NEXT: [[I_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[I_ADDR]] to ptr +// GFX900-NEXT: [[DEFAULT_QUEUE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DEFAULT_QUEUE]] to ptr +// GFX900-NEXT: [[FLAGS_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FLAGS]] to ptr +// GFX900-NEXT: [[NDRANGE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[NDRANGE]] to ptr +// GFX900-NEXT: [[TMP_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[TMP]] to ptr +// GFX900-NEXT: store ptr addrspace(1) [[I]], ptr [[I_ADDR_ASCAST]], align 8, !tbaa [[TBAA7]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[DEFAULT_QUEUE]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] -// GFX900-NEXT: store i32 0, ptr addrspace(5) [[FLAGS]], align 4, !tbaa [[TBAA14]] +// GFX900-NEXT: store i32 0, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] // GFX900-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] // GFX900-NEXT: [[TMP0:%.*]] = call i64 @llvm.amdgcn.s.memtime() -// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[DEFAULT_QUEUE]], align 8, !tbaa [[TBAA16]] -// GFX900-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[FLAGS]], align 4, !tbaa [[TBAA14]] -// GFX900-NEXT: call void @llvm.memcpy.p5.p5.i64(ptr addrspace(5) align 4 [[TMP]], ptr addrspace(5) align 4 [[NDRANGE]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] -// GFX900-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr addrspace(5) byval([[STRUCT_NDRANGE_T]]) [[TMP]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) +// GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] +// GFX900-NEXT: [[TMP2:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] +// GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] +// GFX900-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP_ASCAST]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[DEFAULT_QUEUE]]) #[[ATTR8]] @@ -667,7 +721,8 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-SAME: (ptr noundef [[DOTBLOCK_DESCRIPTOR:%.*]]) #[[ATTR5]] { // GFX900-NEXT: entry: // GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]], align 8 +// GFX900-NEXT: [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DOTBLOCK_DESCRIPTOR_ADDR]] to ptr +// GFX900-NEXT: store ptr [[DOTBLOCK_DESCRIPTOR]], ptr [[DOTBLOCK_DESCRIPTOR_ADDR_ASCAST]], align 8 // GFX900-NEXT: [[TMP0:%.*]] = call i64 @llvm.amdgcn.s.memtime() // GFX900-NEXT: ret void // diff --git a/clang/test/CodeGenOpenCL/amdgpu-features.cl b/clang/test/CodeGenOpenCL/amdgpu-features.cl index 854ab39791f16..f3473346baae5 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-features.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-features.cl @@ -50,6 +50,7 @@ // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1150 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1150 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1151 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1151 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1152 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1152 %s +// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1153 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1153 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1200 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1200 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1201 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1201 %s @@ -102,6 +103,7 @@ // GFX1150: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" // GFX1151: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" // GFX1152: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" +// GFX1153: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" // GFX1200: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" // GFX1201: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" diff --git a/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl b/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl index 8a04456b5df04..53cca49e87ef4 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-nullptr.cl @@ -139,12 +139,12 @@ void test_static_var_local(void) { // Test function-scope variable initialization. // NOOPT-LABEL: @test_func_scope_var_private( -// NOOPT: store ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), ptr addrspace(5) %sp1, align 4 -// NOOPT: store ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), ptr addrspace(5) %sp2, align 4 -// NOOPT: store ptr addrspace(5) null, ptr addrspace(5) %sp3, align 4 -// NOOPT: store ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), ptr addrspace(5) %sp4, align 4 -// NOOPT: call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) align 8 %SS1, ptr addrspace(4) align 8 @__const.test_func_scope_var_private.SS1, i64 32, i1 false) -// NOOPT: call void @llvm.memset.p5.i64(ptr addrspace(5) align 8 %SS2, i8 0, i64 24, i1 false) +// NOOPT: store ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), ptr %sp1{{.*}}, align 4 +// NOOPT: store ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), ptr %sp2{{.*}}, align 4 +// NOOPT: store ptr addrspace(5) null, ptr %sp3{{.*}}, align 4 +// NOOPT: store ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)), ptr %sp4{{.*}}, align 4 +// NOOPT: call void @llvm.memcpy.p0.p4.i64(ptr align 8 %SS1{{.*}}, ptr addrspace(4) align 8 @__const.test_func_scope_var_private.SS1, i64 32, i1 false) +// NOOPT: call void @llvm.memset.p0.i64(ptr align 8 %SS2{{.*}}, i8 0, i64 24, i1 false) void test_func_scope_var_private(void) { private char *sp1 = 0; private char *sp2 = NULL; @@ -157,12 +157,12 @@ void test_func_scope_var_private(void) { // Test function-scope variable initialization. // NOOPT-LABEL: @test_func_scope_var_local( -// NOOPT: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr addrspace(5) %sp1, align 4 -// NOOPT: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr addrspace(5) %sp2, align 4 -// NOOPT: store ptr addrspace(3) null, ptr addrspace(5) %sp3, align 4 -// NOOPT: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr addrspace(5) %sp4, align 4 -// NOOPT: call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) align 8 %SS1, ptr addrspace(4) align 8 @__const.test_func_scope_var_local.SS1, i64 32, i1 false) -// NOOPT: call void @llvm.memset.p5.i64(ptr addrspace(5) align 8 %SS2, i8 0, i64 24, i1 false) +// NOOPT: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr %sp1{{.*}}, align 4 +// NOOPT: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr %sp2{{.*}}, align 4 +// NOOPT: store ptr addrspace(3) null, ptr %sp3{{.*}}, align 4 +// NOOPT: store ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)), ptr %sp4{{.*}}, align 4 +// NOOPT: call void @llvm.memcpy.p0.p4.i64(ptr align 8 %SS1{{.*}}, ptr addrspace(4) align 8 @__const.test_func_scope_var_local.SS1, i64 32, i1 false) +// NOOPT: call void @llvm.memset.p0.i64(ptr align 8 %SS2{{.*}}, i8 0, i64 24, i1 false) void test_func_scope_var_local(void) { local char *sp1 = 0; local char *sp2 = NULL; @@ -603,7 +603,7 @@ int test_and_ptr(private char* p1, local char* p2) { // Test folding of null pointer in function scope. // NOOPT-LABEL: test_fold_private // NOOPT: call void @test_fold_callee -// NOOPT: store ptr addrspace(1) null, ptr addrspace(5) %glob, align 8 +// NOOPT: store ptr addrspace(1) null, ptr %glob{{.*}}, align 8 // NOOPT: %{{.*}} = sub i64 %{{.*}}, 0 // NOOPT: call void @test_fold_callee // NOOPT: %[[SEXT:.*]] = sext i32 ptrtoint (ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)) to i32) to i64 @@ -619,7 +619,7 @@ void test_fold_private(void) { // NOOPT-LABEL: test_fold_local // NOOPT: call void @test_fold_callee -// NOOPT: store ptr addrspace(1) null, ptr addrspace(5) %glob, align 8 +// NOOPT: store ptr addrspace(1) null, ptr %glob{{.*}}, align 8 // NOOPT: %{{.*}} = sub i64 %{{.*}}, 0 // NOOPT: call void @test_fold_callee // NOOPT: %[[SEXT:.*]] = sext i32 ptrtoint (ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)) to i32) to i64 diff --git a/clang/test/CodeGenOpenCL/atomic-ops.cl b/clang/test/CodeGenOpenCL/atomic-ops.cl index 9c1775cc04303..1d850261e5e81 100644 --- a/clang/test/CodeGenOpenCL/atomic-ops.cl +++ b/clang/test/CodeGenOpenCL/atomic-ops.cl @@ -344,11 +344,14 @@ int test_volatile(volatile atomic_int *i) { // CHECK-LABEL: @test_volatile // CHECK: %[[i_addr:.*]] = alloca ptr // CHECK-NEXT: %[[atomicdst:.*]] = alloca i32 - // CHECK-NEXT: store ptr %i, ptr addrspace(5) %[[i_addr]] - // CHECK-NEXT: %[[addr:.*]] = load ptr, ptr addrspace(5) %[[i_addr]] + // CHECK-NEXT: %[[retval_ascast:.*]] = addrspacecast ptr addrspace(5) {{.*}} to ptr + // CHECK-NEXT: %[[i_addr_ascast:.*]] = addrspacecast ptr addrspace(5) %[[i_addr]] to ptr + // CHECK-NEXT: %[[atomicdst_ascast:.*]] = addrspacecast ptr addrspace(5) %[[atomicdst]] to ptr + // CHECK-NEXT: store ptr %i, ptr %[[i_addr_ascast]] + // CHECK-NEXT: %[[addr:.*]] = load ptr, ptr %[[i_addr_ascast]] // CHECK-NEXT: %[[res:.*]] = load atomic volatile i32, ptr %[[addr]] syncscope("workgroup") seq_cst, align 4{{$}} - // CHECK-NEXT: store i32 %[[res]], ptr addrspace(5) %[[atomicdst]] - // CHECK-NEXT: %[[retval:.*]] = load i32, ptr addrspace(5) %[[atomicdst]] + // CHECK-NEXT: store i32 %[[res]], ptr %[[atomicdst_ascast]] + // CHECK-NEXT: %[[retval:.*]] = load i32, ptr %[[atomicdst_ascast]] // CHECK-NEXT: ret i32 %[[retval]] return __opencl_atomic_load(i, memory_order_seq_cst, memory_scope_work_group); } diff --git a/clang/test/CodeGenOpenCL/atomics-unsafe-hw-remarks-gfx90a.cl b/clang/test/CodeGenOpenCL/atomics-unsafe-hw-remarks-gfx90a.cl index 7d684bc185a58..0dafb44f12a3c 100644 --- a/clang/test/CodeGenOpenCL/atomics-unsafe-hw-remarks-gfx90a.cl +++ b/clang/test/CodeGenOpenCL/atomics-unsafe-hw-remarks-gfx90a.cl @@ -31,9 +31,9 @@ typedef enum memory_scope { // GFX90A-HW-REMARK: Hardware instruction generated for atomic fadd operation at memory scope agent-one-as due to an unsafe request. [-Rpass=si-lower] // GFX90A-HW-REMARK: Hardware instruction generated for atomic fadd operation at memory scope workgroup-one-as due to an unsafe request. [-Rpass=si-lower] -// GFX90A-HW-REMARK: global_atomic_add_f32 v0, v[0:1], v2, off glc -// GFX90A-HW-REMARK: global_atomic_add_f32 v0, v[0:1], v2, off glc -// GFX90A-HW-REMARK: global_atomic_add_f32 v0, v[0:1], v2, off glc +// GFX90A-HW-REMARK: global_atomic_add_f32 v{{[0-9]+}}, v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}, off glc +// GFX90A-HW-REMARK: global_atomic_add_f32 v{{[0-9]+}}, v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}, off glc +// GFX90A-HW-REMARK: global_atomic_add_f32 v{{[0-9]+}}, v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}, off glc // GFX90A-HW-LABEL: @atomic_unsafe_hw // GFX90A-HW: atomicrmw fadd ptr addrspace(1) %{{.*}}, float %{{.*}} syncscope("workgroup-one-as") monotonic, align 4 // GFX90A-HW: atomicrmw fadd ptr addrspace(1) %{{.*}}, float %{{.*}} syncscope("agent-one-as") monotonic, align 4 diff --git a/clang/test/CodeGenOpenCL/blocks.cl b/clang/test/CodeGenOpenCL/blocks.cl index e04722f657cfa..161f1406c96cb 100644 --- a/clang/test/CodeGenOpenCL/blocks.cl +++ b/clang/test/CodeGenOpenCL/blocks.cl @@ -25,13 +25,13 @@ void foo(){ // COMMON-NOT: %block.reserved // COMMON-NOT: %block.descriptor // SPIR: %[[block_size:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr addrspace(4), i32 }>, ptr %block, i32 0, i32 0 - // AMDGCN: %[[block_size:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i32 }>, ptr addrspace(5) %block, i32 0, i32 0 + // AMDGCN: %[[block_size:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i32 }>, ptr %block{{.*}}, i32 0, i32 0 // SPIR: store i32 16, ptr %[[block_size]] - // AMDGCN: store i32 20, ptr addrspace(5) %[[block_size]] + // AMDGCN: store i32 20, ptr %[[block_size]] // SPIR: %[[block_align:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr addrspace(4), i32 }>, ptr %block, i32 0, i32 1 - // AMDGCN: %[[block_align:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i32 }>, ptr addrspace(5) %block, i32 0, i32 1 + // AMDGCN: %[[block_align:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i32 }>, ptr %block{{.*}}, i32 0, i32 1 // SPIR: store i32 4, ptr %[[block_align]] - // AMDGCN: store i32 8, ptr addrspace(5) %[[block_align]] + // AMDGCN: store i32 8, ptr %[[block_align]] // SPIR: %[[block_invoke:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr addrspace(4), i32 }>, ptr %[[block:.*]], i32 0, i32 2 // SPIR: store ptr addrspace(4) addrspacecast (ptr @__foo_block_invoke to ptr addrspace(4)), ptr %[[block_invoke]] // SPIR: %[[block_captured:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr addrspace(4), i32 }>, ptr %[[block]], i32 0, i32 3 @@ -41,14 +41,13 @@ void foo(){ // SPIR: store ptr addrspace(4) %[[blk_gen_ptr]], ptr %[[block_B:.*]], // SPIR: %[[block_literal:.*]] = load ptr addrspace(4), ptr %[[block_B]] // SPIR: call {{.*}}i32 @__foo_block_invoke(ptr addrspace(4) noundef %[[block_literal]]) - // AMDGCN: %[[block_invoke:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i32 }>, ptr addrspace(5) %[[block:.*]], i32 0, i32 2 - // AMDGCN: store ptr @__foo_block_invoke, ptr addrspace(5) %[[block_invoke]] - // AMDGCN: %[[block_captured:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i32 }>, ptr addrspace(5) %[[block]], i32 0, i32 3 - // AMDGCN: %[[i_value:.*]] = load i32, ptr addrspace(5) %i - // AMDGCN: store i32 %[[i_value]], ptr addrspace(5) %[[block_captured]], - // AMDGCN: %[[blk_gen_ptr:.*]] = addrspacecast ptr addrspace(5) %[[block]] to ptr - // AMDGCN: store ptr %[[blk_gen_ptr]], ptr addrspace(5) %[[block_B:.*]], - // AMDGCN: %[[block_literal:.*]] = load ptr, ptr addrspace(5) %[[block_B]] + // AMDGCN: %[[block_invoke:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i32 }>, ptr %[[block:.*]], i32 0, i32 2 + // AMDGCN: store ptr @__foo_block_invoke, ptr %[[block_invoke]] + // AMDGCN: %[[block_captured:.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, i32 }>, ptr %[[block]], i32 0, i32 3 + // AMDGCN: %[[i_value:.*]] = load i32, ptr %i + // AMDGCN: store i32 %[[i_value]], ptr %[[block_captured]], + // AMDGCN: store ptr %[[block]], ptr %[[block_B:.*]], + // AMDGCN: %[[block_literal:.*]] = load ptr, ptr %[[block_B]] // AMDGCN: call {{.*}}i32 @__foo_block_invoke(ptr noundef %[[block_literal]]) int (^ block_B)(void) = ^{ diff --git a/clang/test/CodeGenOpenCL/builtins-alloca.cl b/clang/test/CodeGenOpenCL/builtins-alloca.cl index 474e95e74e006..85b449e45a0f1 100644 --- a/clang/test/CodeGenOpenCL/builtins-alloca.cl +++ b/clang/test/CodeGenOpenCL/builtins-alloca.cl @@ -1,12 +1,12 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -cl-std=CL1.2 \ -// RUN: -emit-llvm -o - | FileCheck --check-prefixes=OPENCL %s +// RUN: -emit-llvm -o - | FileCheck --check-prefixes=OPENCL12 %s // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -cl-std=CL2.0 \ -// RUN: -emit-llvm -o - | FileCheck --check-prefixes=OPENCL %s +// RUN: -emit-llvm -o - | FileCheck --check-prefixes=OPENCL20 %s // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -cl-std=CL3.0 \ -// RUN: -emit-llvm -o - | FileCheck --check-prefixes=OPENCL %s +// RUN: -emit-llvm -o - | FileCheck --check-prefixes=OPENCL30 %s // RUN: %clang_cc1 %s -O0 -triple amdgcn-amd-amdhsa -cl-std=CL3.0 -cl-ext=+__opencl_c_generic_address_space \ -// RUN: -emit-llvm -o - | FileCheck --check-prefixes=OPENCL %s +// RUN: -emit-llvm -o - | FileCheck --check-prefixes=OPENCL30GAS %s // OPENCL-LABEL: define dso_local void @test1_builtin_alloca( // OPENCL-SAME: i32 noundef [[N:%.*]]) #[[ATTR0:[0-9]+]] { @@ -20,6 +20,61 @@ // OPENCL-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) // OPENCL-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR]], align 4 // OPENCL-NEXT: ret void +// OPENCL12-LABEL: define dso_local void @test1_builtin_alloca( +// OPENCL12-SAME: i32 noundef [[N:%.*]]) #[[ATTR0:[0-9]+]] { +// OPENCL12-NEXT: [[ENTRY:.*:]] +// OPENCL12-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL12-NEXT: [[ALLOC_PTR:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL12-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL12-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL12-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) +// OPENCL12-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR]], align 4 +// OPENCL12-NEXT: ret void +// +// OPENCL20-LABEL: define dso_local void @test1_builtin_alloca( +// OPENCL20-SAME: i32 noundef [[N:%.*]]) #[[ATTR0:[0-9]+]] { +// OPENCL20-NEXT: [[ENTRY:.*:]] +// OPENCL20-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL20-NEXT: [[ALLOC_PTR:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL20-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL20-NEXT: [[ALLOC_PTR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR]] to ptr +// OPENCL20-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL20-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL20-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) +// OPENCL20-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ASCAST]], align 4 +// OPENCL20-NEXT: ret void +// +// OPENCL30-LABEL: define dso_local void @test1_builtin_alloca( +// OPENCL30-SAME: i32 noundef [[N:%.*]]) #[[ATTR0:[0-9]+]] { +// OPENCL30-NEXT: [[ENTRY:.*:]] +// OPENCL30-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30-NEXT: [[ALLOC_PTR:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL30-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) +// OPENCL30-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR]], align 4 +// OPENCL30-NEXT: ret void +// +// OPENCL30GAS-LABEL: define dso_local void @test1_builtin_alloca( +// OPENCL30GAS-SAME: i32 noundef [[N:%.*]]) #[[ATTR0:[0-9]+]] { +// OPENCL30GAS-NEXT: [[ENTRY:.*:]] +// OPENCL30GAS-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[ALLOC_PTR:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR]] to ptr +// OPENCL30GAS-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30GAS-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL30GAS-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) +// OPENCL30GAS-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: ret void // void test1_builtin_alloca(unsigned n) { __private float* alloc_ptr = (__private float*)__builtin_alloca(n*sizeof(int)); @@ -37,6 +92,61 @@ void test1_builtin_alloca(unsigned n) { // OPENCL-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) // OPENCL-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]], align 4 // OPENCL-NEXT: ret void +// OPENCL12-LABEL: define dso_local void @test1_builtin_alloca_uninitialized( +// OPENCL12-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL12-NEXT: [[ENTRY:.*:]] +// OPENCL12-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL12-NEXT: [[ALLOC_PTR_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL12-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL12-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL12-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) +// OPENCL12-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]], align 4 +// OPENCL12-NEXT: ret void +// +// OPENCL20-LABEL: define dso_local void @test1_builtin_alloca_uninitialized( +// OPENCL20-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL20-NEXT: [[ENTRY:.*:]] +// OPENCL20-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL20-NEXT: [[ALLOC_PTR_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL20-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL20-NEXT: [[ALLOC_PTR_UNINITIALIZED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]] to ptr +// OPENCL20-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL20-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL20-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) +// OPENCL20-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_UNINITIALIZED_ASCAST]], align 4 +// OPENCL20-NEXT: ret void +// +// OPENCL30-LABEL: define dso_local void @test1_builtin_alloca_uninitialized( +// OPENCL30-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30-NEXT: [[ENTRY:.*:]] +// OPENCL30-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30-NEXT: [[ALLOC_PTR_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL30-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) +// OPENCL30-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]], align 4 +// OPENCL30-NEXT: ret void +// +// OPENCL30GAS-LABEL: define dso_local void @test1_builtin_alloca_uninitialized( +// OPENCL30GAS-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30GAS-NEXT: [[ENTRY:.*:]] +// OPENCL30GAS-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[ALLOC_PTR_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL30GAS-NEXT: [[ALLOC_PTR_UNINITIALIZED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]] to ptr +// OPENCL30GAS-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30GAS-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL30GAS-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 8, addrspace(5) +// OPENCL30GAS-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_UNINITIALIZED_ASCAST]], align 4 +// OPENCL30GAS-NEXT: ret void // void test1_builtin_alloca_uninitialized(unsigned n) { __private float* alloc_ptr_uninitialized = (__private float*)__builtin_alloca_uninitialized(n*sizeof(int)); @@ -54,6 +164,61 @@ void test1_builtin_alloca_uninitialized(unsigned n) { // OPENCL-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) // OPENCL-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN]], align 4 // OPENCL-NEXT: ret void +// OPENCL12-LABEL: define dso_local void @test1_builtin_alloca_with_align( +// OPENCL12-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL12-NEXT: [[ENTRY:.*:]] +// OPENCL12-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL12-NEXT: [[ALLOC_PTR_ALIGN:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL12-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL12-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL12-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) +// OPENCL12-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN]], align 4 +// OPENCL12-NEXT: ret void +// +// OPENCL20-LABEL: define dso_local void @test1_builtin_alloca_with_align( +// OPENCL20-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL20-NEXT: [[ENTRY:.*:]] +// OPENCL20-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL20-NEXT: [[ALLOC_PTR_ALIGN:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL20-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL20-NEXT: [[ALLOC_PTR_ALIGN_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_ALIGN]] to ptr +// OPENCL20-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL20-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL20-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) +// OPENCL20-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ALIGN_ASCAST]], align 4 +// OPENCL20-NEXT: ret void +// +// OPENCL30-LABEL: define dso_local void @test1_builtin_alloca_with_align( +// OPENCL30-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30-NEXT: [[ENTRY:.*:]] +// OPENCL30-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30-NEXT: [[ALLOC_PTR_ALIGN:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL30-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) +// OPENCL30-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN]], align 4 +// OPENCL30-NEXT: ret void +// +// OPENCL30GAS-LABEL: define dso_local void @test1_builtin_alloca_with_align( +// OPENCL30GAS-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30GAS-NEXT: [[ENTRY:.*:]] +// OPENCL30GAS-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ALIGN:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ALIGN_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_ALIGN]] to ptr +// OPENCL30GAS-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30GAS-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL30GAS-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) +// OPENCL30GAS-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ALIGN_ASCAST]], align 4 +// OPENCL30GAS-NEXT: ret void // void test1_builtin_alloca_with_align(unsigned n) { __private float* alloc_ptr_align = (__private float*)__builtin_alloca_with_align((n*sizeof(int)), 8); @@ -71,6 +236,61 @@ void test1_builtin_alloca_with_align(unsigned n) { // OPENCL-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) // OPENCL-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]], align 4 // OPENCL-NEXT: ret void +// OPENCL12-LABEL: define dso_local void @test1_builtin_alloca_with_align_uninitialized( +// OPENCL12-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL12-NEXT: [[ENTRY:.*:]] +// OPENCL12-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL12-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL12-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL12-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL12-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) +// OPENCL12-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]], align 4 +// OPENCL12-NEXT: ret void +// +// OPENCL20-LABEL: define dso_local void @test1_builtin_alloca_with_align_uninitialized( +// OPENCL20-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL20-NEXT: [[ENTRY:.*:]] +// OPENCL20-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL20-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL20-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL20-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]] to ptr +// OPENCL20-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL20-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL20-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) +// OPENCL20-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ALIGN_UNINITIALIZED_ASCAST]], align 4 +// OPENCL20-NEXT: ret void +// +// OPENCL30-LABEL: define dso_local void @test1_builtin_alloca_with_align_uninitialized( +// OPENCL30-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30-NEXT: [[ENTRY:.*:]] +// OPENCL30-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL30-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) +// OPENCL30-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]], align 4 +// OPENCL30-NEXT: ret void +// +// OPENCL30GAS-LABEL: define dso_local void @test1_builtin_alloca_with_align_uninitialized( +// OPENCL30GAS-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30GAS-NEXT: [[ENTRY:.*:]] +// OPENCL30GAS-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]] to ptr +// OPENCL30GAS-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30GAS-NEXT: [[MUL:%.*]] = mul i64 [[CONV]], 4 +// OPENCL30GAS-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[MUL]], align 1, addrspace(5) +// OPENCL30GAS-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ALIGN_UNINITIALIZED_ASCAST]], align 4 +// OPENCL30GAS-NEXT: ret void // void test1_builtin_alloca_with_align_uninitialized(unsigned n) { __private float* alloc_ptr_align_uninitialized = (__private float*)__builtin_alloca_with_align_uninitialized((n*sizeof(int)), 8); @@ -87,6 +307,57 @@ void test1_builtin_alloca_with_align_uninitialized(unsigned n) { // OPENCL-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) // OPENCL-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR]], align 4 // OPENCL-NEXT: ret void +// OPENCL12-LABEL: define dso_local void @test2_builtin_alloca( +// OPENCL12-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL12-NEXT: [[ENTRY:.*:]] +// OPENCL12-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL12-NEXT: [[ALLOC_PTR:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL12-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL12-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) +// OPENCL12-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR]], align 4 +// OPENCL12-NEXT: ret void +// +// OPENCL20-LABEL: define dso_local void @test2_builtin_alloca( +// OPENCL20-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL20-NEXT: [[ENTRY:.*:]] +// OPENCL20-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL20-NEXT: [[ALLOC_PTR:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL20-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL20-NEXT: [[ALLOC_PTR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR]] to ptr +// OPENCL20-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL20-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) +// OPENCL20-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ASCAST]], align 4 +// OPENCL20-NEXT: ret void +// +// OPENCL30-LABEL: define dso_local void @test2_builtin_alloca( +// OPENCL30-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30-NEXT: [[ENTRY:.*:]] +// OPENCL30-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30-NEXT: [[ALLOC_PTR:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) +// OPENCL30-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR]], align 4 +// OPENCL30-NEXT: ret void +// +// OPENCL30GAS-LABEL: define dso_local void @test2_builtin_alloca( +// OPENCL30GAS-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30GAS-NEXT: [[ENTRY:.*:]] +// OPENCL30GAS-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[ALLOC_PTR:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR]] to ptr +// OPENCL30GAS-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30GAS-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) +// OPENCL30GAS-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: ret void // void test2_builtin_alloca(unsigned n) { __private void *alloc_ptr = __builtin_alloca(n); @@ -103,6 +374,57 @@ void test2_builtin_alloca(unsigned n) { // OPENCL-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) // OPENCL-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]], align 4 // OPENCL-NEXT: ret void +// OPENCL12-LABEL: define dso_local void @test2_builtin_alloca_uninitialized( +// OPENCL12-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL12-NEXT: [[ENTRY:.*:]] +// OPENCL12-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL12-NEXT: [[ALLOC_PTR_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL12-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL12-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) +// OPENCL12-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]], align 4 +// OPENCL12-NEXT: ret void +// +// OPENCL20-LABEL: define dso_local void @test2_builtin_alloca_uninitialized( +// OPENCL20-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL20-NEXT: [[ENTRY:.*:]] +// OPENCL20-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL20-NEXT: [[ALLOC_PTR_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL20-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL20-NEXT: [[ALLOC_PTR_UNINITIALIZED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]] to ptr +// OPENCL20-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL20-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) +// OPENCL20-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_UNINITIALIZED_ASCAST]], align 4 +// OPENCL20-NEXT: ret void +// +// OPENCL30-LABEL: define dso_local void @test2_builtin_alloca_uninitialized( +// OPENCL30-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30-NEXT: [[ENTRY:.*:]] +// OPENCL30-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30-NEXT: [[ALLOC_PTR_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) +// OPENCL30-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]], align 4 +// OPENCL30-NEXT: ret void +// +// OPENCL30GAS-LABEL: define dso_local void @test2_builtin_alloca_uninitialized( +// OPENCL30GAS-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30GAS-NEXT: [[ENTRY:.*:]] +// OPENCL30GAS-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[ALLOC_PTR_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL30GAS-NEXT: [[ALLOC_PTR_UNINITIALIZED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_UNINITIALIZED]] to ptr +// OPENCL30GAS-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30GAS-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 8, addrspace(5) +// OPENCL30GAS-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_UNINITIALIZED_ASCAST]], align 4 +// OPENCL30GAS-NEXT: ret void // void test2_builtin_alloca_uninitialized(unsigned n) { __private void *alloc_ptr_uninitialized = __builtin_alloca_uninitialized(n); @@ -119,6 +441,57 @@ void test2_builtin_alloca_uninitialized(unsigned n) { // OPENCL-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) // OPENCL-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN]], align 4 // OPENCL-NEXT: ret void +// OPENCL12-LABEL: define dso_local void @test2_builtin_alloca_with_align( +// OPENCL12-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL12-NEXT: [[ENTRY:.*:]] +// OPENCL12-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL12-NEXT: [[ALLOC_PTR_ALIGN:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL12-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL12-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) +// OPENCL12-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN]], align 4 +// OPENCL12-NEXT: ret void +// +// OPENCL20-LABEL: define dso_local void @test2_builtin_alloca_with_align( +// OPENCL20-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL20-NEXT: [[ENTRY:.*:]] +// OPENCL20-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL20-NEXT: [[ALLOC_PTR_ALIGN:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL20-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL20-NEXT: [[ALLOC_PTR_ALIGN_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_ALIGN]] to ptr +// OPENCL20-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL20-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) +// OPENCL20-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ALIGN_ASCAST]], align 4 +// OPENCL20-NEXT: ret void +// +// OPENCL30-LABEL: define dso_local void @test2_builtin_alloca_with_align( +// OPENCL30-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30-NEXT: [[ENTRY:.*:]] +// OPENCL30-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30-NEXT: [[ALLOC_PTR_ALIGN:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) +// OPENCL30-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN]], align 4 +// OPENCL30-NEXT: ret void +// +// OPENCL30GAS-LABEL: define dso_local void @test2_builtin_alloca_with_align( +// OPENCL30GAS-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30GAS-NEXT: [[ENTRY:.*:]] +// OPENCL30GAS-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ALIGN:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ALIGN_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_ALIGN]] to ptr +// OPENCL30GAS-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30GAS-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) +// OPENCL30GAS-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ALIGN_ASCAST]], align 4 +// OPENCL30GAS-NEXT: ret void // void test2_builtin_alloca_with_align(unsigned n) { __private void *alloc_ptr_align = __builtin_alloca_with_align(n, 8); @@ -135,6 +508,57 @@ void test2_builtin_alloca_with_align(unsigned n) { // OPENCL-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) // OPENCL-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]], align 4 // OPENCL-NEXT: ret void +// OPENCL12-LABEL: define dso_local void @test2_builtin_alloca_with_align_uninitialized( +// OPENCL12-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL12-NEXT: [[ENTRY:.*:]] +// OPENCL12-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL12-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL12-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL12-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL12-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) +// OPENCL12-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]], align 4 +// OPENCL12-NEXT: ret void +// +// OPENCL20-LABEL: define dso_local void @test2_builtin_alloca_with_align_uninitialized( +// OPENCL20-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL20-NEXT: [[ENTRY:.*:]] +// OPENCL20-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL20-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL20-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL20-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]] to ptr +// OPENCL20-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL20-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL20-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) +// OPENCL20-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ALIGN_UNINITIALIZED_ASCAST]], align 4 +// OPENCL20-NEXT: ret void +// +// OPENCL30-LABEL: define dso_local void @test2_builtin_alloca_with_align_uninitialized( +// OPENCL30-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30-NEXT: [[ENTRY:.*:]] +// OPENCL30-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30-NEXT: store i32 [[N]], ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[N_ADDR]], align 4 +// OPENCL30-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) +// OPENCL30-NEXT: store ptr addrspace(5) [[TMP1]], ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]], align 4 +// OPENCL30-NEXT: ret void +// +// OPENCL30GAS-LABEL: define dso_local void @test2_builtin_alloca_with_align_uninitialized( +// OPENCL30GAS-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// OPENCL30GAS-NEXT: [[ENTRY:.*:]] +// OPENCL30GAS-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED:%.*]] = alloca ptr addrspace(5), align 4, addrspace(5) +// OPENCL30GAS-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[N_ADDR]] to ptr +// OPENCL30GAS-NEXT: [[ALLOC_PTR_ALIGN_UNINITIALIZED_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ALLOC_PTR_ALIGN_UNINITIALIZED]] to ptr +// OPENCL30GAS-NEXT: store i32 [[N]], ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR_ASCAST]], align 4 +// OPENCL30GAS-NEXT: [[CONV:%.*]] = zext i32 [[TMP0]] to i64 +// OPENCL30GAS-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[CONV]], align 1, addrspace(5) +// OPENCL30GAS-NEXT: store ptr addrspace(5) [[TMP1]], ptr [[ALLOC_PTR_ALIGN_UNINITIALIZED_ASCAST]], align 4 +// OPENCL30GAS-NEXT: ret void // void test2_builtin_alloca_with_align_uninitialized(unsigned n) { __private void *alloc_ptr_align_uninitialized = __builtin_alloca_with_align_uninitialized(n, 8); diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl index 7f07160bf5e88..19ab6562e52b9 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl @@ -6,6 +6,7 @@ // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1150 -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1151 -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1152 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1153 -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple spirv64-amd-amdhsa -emit-llvm -o - %s | FileCheck %s typedef unsigned int uint; diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx12.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx12.cl index 3d74667b62b8c..9bfedac003296 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx12.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx12.cl @@ -8,8 +8,9 @@ typedef unsigned int uint; // CHECK-LABEL: @test_s_sleep_var( // CHECK-NEXT: entry: // CHECK-NEXT: [[D_ADDR:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store i32 [[D:%.*]], ptr addrspace(5) [[D_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[D_ADDR]], align 4 +// CHECK-NEXT: [[D_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D_ADDR]] to ptr +// CHECK-NEXT: store i32 [[D:%.*]], ptr [[D_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[D_ADDR_ASCAST]], align 4 // CHECK-NEXT: call void @llvm.amdgcn.s.sleep.var(i32 [[TMP0]]) // CHECK-NEXT: call void @llvm.amdgcn.s.sleep.var(i32 15) // CHECK-NEXT: ret void @@ -26,15 +27,19 @@ void test_s_sleep_var(int d) // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4, addrspace(5) // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) // CHECK-NEXT: [[C_ADDR:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr addrspace(5) [[OUT_ADDR]], align 8 -// CHECK-NEXT: store i32 [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 4 -// CHECK-NEXT: store i32 [[B:%.*]], ptr addrspace(5) [[B_ADDR]], align 4 -// CHECK-NEXT: store i32 [[C:%.*]], ptr addrspace(5) [[C_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[A_ADDR]], align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[B_ADDR]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[C_ADDR]], align 4 +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[C_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[C_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[C:%.*]], ptr [[C_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[C_ADDR_ASCAST]], align 4 // CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.amdgcn.permlane16.var(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i1 false, i1 false) -// CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 // CHECK-NEXT: store i32 [[TMP3]], ptr addrspace(1) [[TMP4]], align 4 // CHECK-NEXT: ret void // @@ -48,15 +53,19 @@ void test_permlane16_var(global uint* out, uint a, uint b, uint c) { // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4, addrspace(5) // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4, addrspace(5) // CHECK-NEXT: [[C_ADDR:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr addrspace(5) [[OUT_ADDR]], align 8 -// CHECK-NEXT: store i32 [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 4 -// CHECK-NEXT: store i32 [[B:%.*]], ptr addrspace(5) [[B_ADDR]], align 4 -// CHECK-NEXT: store i32 [[C:%.*]], ptr addrspace(5) [[C_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[A_ADDR]], align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[B_ADDR]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[C_ADDR]], align 4 +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[C_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[C_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[C:%.*]], ptr [[C_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[C_ADDR_ASCAST]], align 4 // CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.amdgcn.permlanex16.var(i32 [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i1 false, i1 false) -// CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 // CHECK-NEXT: store i32 [[TMP3]], ptr addrspace(1) [[TMP4]], align 4 // CHECK-NEXT: ret void // @@ -79,8 +88,9 @@ void test_s_barrier_signal() // CHECK-LABEL: @test_s_barrier_signal_var( // CHECK-NEXT: entry: // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store i32 [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[A_ADDR]], align 4 +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR_ASCAST]], align 4 // CHECK-NEXT: call void @llvm.amdgcn.s.barrier.signal.var(i32 [[TMP0]]) // CHECK-NEXT: ret void // @@ -94,18 +104,21 @@ void test_s_barrier_signal_var(int a) // CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // CHECK-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // CHECK-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// CHECK-NEXT: store ptr [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 8 -// CHECK-NEXT: store ptr [[B:%.*]], ptr addrspace(5) [[B_ADDR]], align 8 -// CHECK-NEXT: store ptr [[C:%.*]], ptr addrspace(5) [[C_ADDR]], align 8 +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[C_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[C_ADDR]] to ptr +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[B:%.*]], ptr [[B_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[C:%.*]], ptr [[C_ADDR_ASCAST]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = call i1 @llvm.amdgcn.s.barrier.signal.isfirst(i32 1) // CHECK-NEXT: br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] // CHECK: if.then: -// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr addrspace(5) [[B_ADDR]], align 8 -// CHECK-NEXT: store ptr [[TMP1]], ptr addrspace(5) [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[B_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[A_ADDR_ASCAST]], align 8 // CHECK-NEXT: br label [[IF_END:%.*]] // CHECK: if.else: -// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr addrspace(5) [[C_ADDR]], align 8 -// CHECK-NEXT: store ptr [[TMP2]], ptr addrspace(5) [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[C_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[A_ADDR_ASCAST]], align 8 // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: call void @llvm.amdgcn.s.barrier.wait(i16 1) @@ -127,20 +140,24 @@ void test_s_barrier_signal_isfirst(int* a, int* b, int *c) // CHECK-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // CHECK-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // CHECK-NEXT: [[D_ADDR:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store ptr [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 8 -// CHECK-NEXT: store ptr [[B:%.*]], ptr addrspace(5) [[B_ADDR]], align 8 -// CHECK-NEXT: store ptr [[C:%.*]], ptr addrspace(5) [[C_ADDR]], align 8 -// CHECK-NEXT: store i32 [[D:%.*]], ptr addrspace(5) [[D_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[D_ADDR]], align 4 +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[C_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[C_ADDR]] to ptr +// CHECK-NEXT: [[D_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[D_ADDR]] to ptr +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[B:%.*]], ptr [[B_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[C:%.*]], ptr [[C_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[D:%.*]], ptr [[D_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[D_ADDR_ASCAST]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.s.barrier.signal.isfirst.var(i32 [[TMP0]]) // CHECK-NEXT: br i1 [[TMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] // CHECK: if.then: -// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr addrspace(5) [[B_ADDR]], align 8 -// CHECK-NEXT: store ptr [[TMP2]], ptr addrspace(5) [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[B_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[A_ADDR_ASCAST]], align 8 // CHECK-NEXT: br label [[IF_END:%.*]] // CHECK: if.else: -// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr addrspace(5) [[C_ADDR]], align 8 -// CHECK-NEXT: store ptr [[TMP3]], ptr addrspace(5) [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[C_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[TMP3]], ptr [[A_ADDR_ASCAST]], align 8 // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: call void @llvm.amdgcn.s.barrier.wait(i16 1) @@ -160,8 +177,9 @@ void test_s_barrier_isfirst_var(int* a, int* b, int *c, int d) // CHECK-LABEL: @test_s_barrier_init( // CHECK-NEXT: entry: // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store i32 [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[A_ADDR]], align 4 +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR_ASCAST]], align 4 // CHECK-NEXT: call void @llvm.amdgcn.s.barrier.init(i32 1, i32 [[TMP0]]) // CHECK-NEXT: ret void // @@ -195,18 +213,21 @@ void test_s_wakeup_barrier() // CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // CHECK-NEXT: [[B_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) // CHECK-NEXT: [[C_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) -// CHECK-NEXT: store ptr [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 8 -// CHECK-NEXT: store ptr [[B:%.*]], ptr addrspace(5) [[B_ADDR]], align 8 -// CHECK-NEXT: store ptr [[C:%.*]], ptr addrspace(5) [[C_ADDR]], align 8 +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[C_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[C_ADDR]] to ptr +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[B:%.*]], ptr [[B_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[C:%.*]], ptr [[C_ADDR_ASCAST]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = call i1 @llvm.amdgcn.s.barrier.leave() // CHECK-NEXT: br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] // CHECK: if.then: -// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr addrspace(5) [[B_ADDR]], align 8 -// CHECK-NEXT: store ptr [[TMP1]], ptr addrspace(5) [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[B_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[TMP1]], ptr [[A_ADDR_ASCAST]], align 8 // CHECK-NEXT: br label [[IF_END:%.*]] // CHECK: if.else: -// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr addrspace(5) [[C_ADDR]], align 8 -// CHECK-NEXT: store ptr [[TMP2]], ptr addrspace(5) [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[C_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr [[TMP2]], ptr [[A_ADDR_ASCAST]], align 8 // CHECK-NEXT: br label [[IF_END]] // CHECK: if.end: // CHECK-NEXT: ret void @@ -221,13 +242,17 @@ void test_s_barrier_leave(int* a, int* b, int *c) // CHECK-LABEL: @test_s_get_barrier_state( // CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4, addrspace(5) // CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4, addrspace(5) // CHECK-NEXT: [[STATE:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store i32 [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[A_ADDR]], align 4 +// CHECK-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[STATE_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[STATE]] to ptr +// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR_ASCAST]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.amdgcn.s.get.barrier.state(i32 [[TMP0]]) -// CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(5) [[STATE]], align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[STATE]], align 4 +// CHECK-NEXT: store i32 [[TMP1]], ptr [[STATE_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[STATE_ASCAST]], align 4 // CHECK-NEXT: ret i32 [[TMP2]] // unsigned test_s_get_barrier_state(int a) @@ -262,16 +287,20 @@ void test_s_ttracedata_imm() // CHECK-NEXT: [[GP_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // CHECK-NEXT: [[CP_ADDR:%.*]] = alloca ptr addrspace(4), align 8, addrspace(5) // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store ptr [[FP:%.*]], ptr addrspace(5) [[FP_ADDR]], align 8 -// CHECK-NEXT: store ptr addrspace(1) [[GP:%.*]], ptr addrspace(5) [[GP_ADDR]], align 8 -// CHECK-NEXT: store ptr addrspace(4) [[CP:%.*]], ptr addrspace(5) [[CP_ADDR]], align 8 -// CHECK-NEXT: store i32 [[LEN:%.*]], ptr addrspace(5) [[LEN_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr addrspace(5) [[FP_ADDR]], align 8 +// CHECK-NEXT: [[FP_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FP_ADDR]] to ptr +// CHECK-NEXT: [[GP_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[GP_ADDR]] to ptr +// CHECK-NEXT: [[CP_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[CP_ADDR]] to ptr +// CHECK-NEXT: [[LEN_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LEN_ADDR]] to ptr +// CHECK-NEXT: store ptr [[FP:%.*]], ptr [[FP_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr addrspace(1) [[GP:%.*]], ptr [[GP_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr addrspace(4) [[CP:%.*]], ptr [[CP_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[LEN:%.*]], ptr [[LEN_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FP_ADDR_ASCAST]], align 8 // CHECK-NEXT: call void @llvm.amdgcn.s.prefetch.data.p0(ptr [[TMP0]], i32 0) -// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[GP_ADDR]], align 8 -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[GP_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[LEN_ADDR_ASCAST]], align 4 // CHECK-NEXT: call void @llvm.amdgcn.s.prefetch.data.p1(ptr addrspace(1) [[TMP1]], i32 [[TMP2]]) -// CHECK-NEXT: [[TMP3:%.*]] = load ptr addrspace(4), ptr addrspace(5) [[CP_ADDR]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr addrspace(4), ptr [[CP_ADDR_ASCAST]], align 8 // CHECK-NEXT: call void @llvm.amdgcn.s.prefetch.data.p4(ptr addrspace(4) [[TMP3]], i32 31) // CHECK-NEXT: ret void // @@ -286,12 +315,14 @@ void test_s_prefetch_data(int *fp, global float *gp, constant char *cp, unsigned // CHECK-NEXT: entry: // CHECK-NEXT: [[RSRC_ADDR:%.*]] = alloca ptr addrspace(8), align 16, addrspace(5) // CHECK-NEXT: [[LEN_ADDR:%.*]] = alloca i32, align 4, addrspace(5) -// CHECK-NEXT: store ptr addrspace(8) [[RSRC:%.*]], ptr addrspace(5) [[RSRC_ADDR]], align 16 -// CHECK-NEXT: store i32 [[LEN:%.*]], ptr addrspace(5) [[LEN_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(8), ptr addrspace(5) [[RSRC_ADDR]], align 16 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr addrspace(5) [[LEN_ADDR]], align 4 +// CHECK-NEXT: [[RSRC_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RSRC_ADDR]] to ptr +// CHECK-NEXT: [[LEN_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[LEN_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(8) [[RSRC:%.*]], ptr [[RSRC_ADDR_ASCAST]], align 16 +// CHECK-NEXT: store i32 [[LEN:%.*]], ptr [[LEN_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(8), ptr [[RSRC_ADDR_ASCAST]], align 16 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[LEN_ADDR_ASCAST]], align 4 // CHECK-NEXT: call void @llvm.amdgcn.s.buffer.prefetch.data(ptr addrspace(8) [[TMP0]], i32 128, i32 [[TMP1]]) -// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(8), ptr addrspace(5) [[RSRC_ADDR]], align 16 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(8), ptr [[RSRC_ADDR_ASCAST]], align 16 // CHECK-NEXT: call void @llvm.amdgcn.s.buffer.prefetch.data(ptr addrspace(8) [[TMP2]], i32 0, i32 31) // CHECK-NEXT: ret void // diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx940.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx940.cl index fc5649d8a41f7..a2f14c652c828 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx940.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx940.cl @@ -10,10 +10,12 @@ typedef unsigned char u8; // CHECK-NEXT: entry: // CHECK-NEXT: [[SRC_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // CHECK-NEXT: [[DST_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) -// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr addrspace(5) [[SRC_ADDR]], align 8 -// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr addrspace(5) [[DST_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[SRC_ADDR]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: [[SRC_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SRC_ADDR]] to ptr +// CHECK-NEXT: [[DST_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DST_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr [[SRC_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr [[DST_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[SRC_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr [[DST_ADDR_ASCAST]], align 4 // CHECK-NEXT: call void @llvm.amdgcn.global.load.lds(ptr addrspace(1) [[TMP0]], ptr addrspace(3) [[TMP1]], i32 4, i32 0, i32 0) // CHECK-NEXT: ret void // @@ -25,10 +27,12 @@ void test_global_load_lds_u32(global u32* src, local u32 *dst) { // CHECK-NEXT: entry: // CHECK-NEXT: [[SRC_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // CHECK-NEXT: [[DST_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) -// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr addrspace(5) [[SRC_ADDR]], align 8 -// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr addrspace(5) [[DST_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[SRC_ADDR]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: [[SRC_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SRC_ADDR]] to ptr +// CHECK-NEXT: [[DST_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DST_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr [[SRC_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr [[DST_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[SRC_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr [[DST_ADDR_ASCAST]], align 4 // CHECK-NEXT: call void @llvm.amdgcn.global.load.lds(ptr addrspace(1) [[TMP0]], ptr addrspace(3) [[TMP1]], i32 2, i32 0, i32 0) // CHECK-NEXT: ret void // @@ -40,10 +44,12 @@ void test_global_load_lds_u16(global u16* src, local u16 *dst) { // CHECK-NEXT: entry: // CHECK-NEXT: [[SRC_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) // CHECK-NEXT: [[DST_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) -// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr addrspace(5) [[SRC_ADDR]], align 8 -// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr addrspace(5) [[DST_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[SRC_ADDR]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr addrspace(5) [[DST_ADDR]], align 4 +// CHECK-NEXT: [[SRC_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SRC_ADDR]] to ptr +// CHECK-NEXT: [[DST_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[DST_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[SRC:%.*]], ptr [[SRC_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store ptr addrspace(3) [[DST:%.*]], ptr [[DST_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(1), ptr [[SRC_ADDR_ASCAST]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(3), ptr [[DST_ADDR_ASCAST]], align 4 // CHECK-NEXT: call void @llvm.amdgcn.global.load.lds(ptr addrspace(1) [[TMP0]], ptr addrspace(3) [[TMP1]], i32 1, i32 0, i32 0) // CHECK-NEXT: ret void // diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl index 5bd8f77a5930c..269f20e2f53fe 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-vi.cl @@ -102,20 +102,145 @@ void test_s_dcache_wb() __builtin_amdgcn_s_dcache_wb(); } -// CHECK-LABEL: @test_mov_dpp +// CHECK-LABEL: @test_mov_dpp_int // CHECK: {{.*}}call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 poison, i32 %src, i32 0, i32 0, i32 0, i1 false) -void test_mov_dpp(global int* out, int src) +void test_mov_dpp_int(global int* out, int src) { *out = __builtin_amdgcn_mov_dpp(src, 0, 0, 0, false); } -// CHECK-LABEL: @test_update_dpp +// CHECK-LABEL: @test_mov_dpp_long +// CHECK: %0 = tail call{{.*}} i64 @llvm.amdgcn.update.dpp.i64(i64 poison, i64 %x, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: store i64 %0, +void test_mov_dpp_long(long x, global long *p) { + *p = __builtin_amdgcn_mov_dpp(x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_mov_dpp_float +// CHECK: %0 = bitcast float %x to i32 +// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 poison, i32 %0, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: store i32 %1, +void test_mov_dpp_float(float x, global float *p) { + *p = __builtin_amdgcn_mov_dpp(x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_mov_dpp_double +// CHECK: %0 = bitcast double %x to i64 +// CHECK-NEXT: %1 = tail call{{.*}} i64 @llvm.amdgcn.update.dpp.i64(i64 poison, i64 %0, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: store i64 %1, +void test_mov_dpp_double(double x, global double *p) { + *p = __builtin_amdgcn_mov_dpp(x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_mov_dpp_short +// CHECK: %0 = zext i16 %x to i32 +// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 poison, i32 %0, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: %2 = trunc i32 %1 to i16 +// CHECK-NEXT: store i16 %2, +void test_mov_dpp_short(short x, global short *p) { + *p = __builtin_amdgcn_mov_dpp(x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_mov_dpp_char +// CHECK: %0 = zext i8 %x to i32 +// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 poison, i32 %0, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: %2 = trunc i32 %1 to i8 +// CHECK-NEXT: store i8 %2, +void test_mov_dpp_char(char x, global char *p) { + *p = __builtin_amdgcn_mov_dpp(x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_mov_dpp_half +// CHECK: %0 = load i16, +// CHECK: %1 = zext i16 %0 to i32 +// CHECK-NEXT: %2 = tail call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 poison, i32 %1, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: %3 = trunc i32 %2 to i16 +// CHECK-NEXT: store i16 %3, +void test_mov_dpp_half(half *x, global half *p) { + *p = __builtin_amdgcn_mov_dpp(*x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_update_dpp_int +// CHECK: {{.*}}call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 %arg1, i32 %arg2, i32 0, i32 0, i32 0, i1 false) +void test_update_dpp_int(global int* out, int arg1, int arg2) +{ + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, 0, false); +} + +// CHECK-LABEL: @test_update_dpp_long +// CHECK: %0 = tail call{{.*}} i64 @llvm.amdgcn.update.dpp.i64(i64 %x, i64 %x, i32 257, i32 15, i32 15, i1 false) +// CHECk-NEXT: store i64 %0, +void test_update_dpp_long(long x, global long *p) { + *p = __builtin_amdgcn_update_dpp(x, x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_update_dpp_float +// CHECK: %0 = bitcast float %x to i32 +// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 %0, i32 %0, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: store i32 %1, +void test_update_dpp_float(float x, global float *p) { + *p = __builtin_amdgcn_update_dpp(x, x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_update_dpp_double +// CHECK: %0 = bitcast double %x to i64 +// CHECK-NEXT: %1 = tail call{{.*}} i64 @llvm.amdgcn.update.dpp.i64(i64 %0, i64 %0, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: store i64 %1, +void test_update_dpp_double(double x, global double *p) { + *p = __builtin_amdgcn_update_dpp(x, x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_update_dpp_short +// CHECK: %0 = zext i16 %x to i32 +// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 %0, i32 %0, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: %2 = trunc i32 %1 to i16 +// CHECK-NEXT: store i16 %2, +void test_update_dpp_short(short x, global short *p) { + *p = __builtin_amdgcn_update_dpp(x, x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_update_dpp_char +// CHECK: %0 = zext i8 %x to i32 +// CHECK-NEXT: %1 = tail call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 %0, i32 %0, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: %2 = trunc i32 %1 to i8 +// CHECK-NEXT: store i8 %2, +void test_update_dpp_char(char x, global char *p) { + *p = __builtin_amdgcn_update_dpp(x, x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_update_dpp_half +// CHECK: %0 = load i16, +// CHECK: %1 = zext i16 %0 to i32 +// CHECK-NEXT: %2 = tail call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 %1, i32 %1, i32 257, i32 15, i32 15, i1 false) +// CHECK-NEXT: %3 = trunc i32 %2 to i16 +// CHECK-NEXT: store i16 %3, +void test_update_dpp_half(half *x, global half *p) { + *p = __builtin_amdgcn_update_dpp(*x, *x, 0x101, 0xf, 0xf, 0); +} + +// CHECK-LABEL: @test_update_dpp_int_uint // CHECK: {{.*}}call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 %arg1, i32 %arg2, i32 0, i32 0, i32 0, i1 false) -void test_update_dpp(global int* out, int arg1, int arg2) +void test_update_dpp_int_uint(global int* out, int arg1, unsigned int arg2) { *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, 0, false); } +// CHECK-LABEL: @test_update_dpp_lit_int +// CHECK: {{.*}}call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 5, i32 %arg1, i32 0, i32 0, i32 0, i1 false) +void test_update_dpp_lit_int(global int* out, int arg1) +{ + *out = __builtin_amdgcn_update_dpp(5, arg1, 0, 0, 0, false); +} + +__constant int gi = 5; + +// CHECK-LABEL: @test_update_dpp_const_int +// CHECK: {{.*}}call{{.*}} i32 @llvm.amdgcn.update.dpp.i32(i32 5, i32 %arg1, i32 0, i32 0, i32 0, i1 false) +void test_update_dpp_const_int(global int* out, int arg1) +{ + *out = __builtin_amdgcn_update_dpp(gi, arg1, 0, 0, 0, false); +} + // CHECK-LABEL: @test_ds_fadd // CHECK: atomicrmw fadd ptr addrspace(3) %out, float %src monotonic, align 4{{$}} // CHECK: atomicrmw volatile fadd ptr addrspace(3) %out, float %src monotonic, align 4{{$}} diff --git a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx12.cl b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx12.cl index e8b6eb57c38d7..461abc3708128 100644 --- a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx12.cl +++ b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx12.cl @@ -71,7 +71,7 @@ short2 test_flat_add_2bf16(__generic short2 *addr, short2 x) { // CHECK: [[RMW:%.+]] = atomicrmw fadd ptr addrspace(1) %{{.+}}, <2 x half> %{{.+}} syncscope("agent") monotonic, align 4, !amdgpu.no.fine.grained.memory !{{[0-9]+$}} // GFX12-LABEL: test_global_add_half2 -// GFX12: global_atomic_pk_add_f16 v2, v[0:1], v2, off th:TH_ATOMIC_RETURN +// GFX12: global_atomic_pk_add_f16 v2, v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}, off th:TH_ATOMIC_RETURN void test_global_add_half2(__global half2 *addr, half2 x) { half2 *rtn; *rtn = __builtin_amdgcn_global_atomic_fadd_v2f16(addr, x); @@ -93,7 +93,7 @@ void test_global_add_half2_noret(__global half2 *addr, half2 x) { // GFX12-LABEL: test_global_add_2bf16 -// GFX12: global_atomic_pk_add_bf16 v2, v[0:1], v2, off th:TH_ATOMIC_RETURN +// GFX12: global_atomic_pk_add_bf16 v2, v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}, off th:TH_ATOMIC_RETURN void test_global_add_2bf16(__global short2 *addr, short2 x) { short2 *rtn; *rtn = __builtin_amdgcn_global_atomic_fadd_v2bf16(addr, x); diff --git a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx8.cl b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx8.cl index 2f00977ec6014..2728490d5c02e 100644 --- a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx8.cl +++ b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx8.cl @@ -8,7 +8,7 @@ // CHECK-LABEL: test_fadd_local // CHECK: = atomicrmw fadd ptr addrspace(3) %{{.+}}, float %{{.+}} monotonic, align 4 // GFX8-LABEL: test_fadd_local$local: -// GFX8: ds_add_rtn_f32 v2, v0, v1 +// GFX8: ds_add_rtn_f32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} // GFX8: s_endpgm kernel void test_fadd_local(__local float *ptr, float val){ float *res; diff --git a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx90a.cl b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx90a.cl index 556e553903d1a..ef97d12afab1d 100644 --- a/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx90a.cl +++ b/clang/test/CodeGenOpenCL/builtins-fp-atomics-gfx90a.cl @@ -20,7 +20,7 @@ void test_global_add_f64(__global double *addr, double x) { // CHECK-LABEL: test_global_add_half2 // CHECK: = atomicrmw fadd ptr addrspace(1) %{{.+}}, <2 x half> %{{.+}} syncscope("agent") monotonic, align 4, !amdgpu.no.fine.grained.memory !{{[0-9]+$}} // GFX90A-LABEL: test_global_add_half2 -// GFX90A: global_atomic_pk_add_f16 v2, v[0:1], v2, off glc +// GFX90A: global_atomic_pk_add_f16 v2, v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}, off glc void test_global_add_half2(__global half2 *addr, half2 x) { half2 *rtn; *rtn = __builtin_amdgcn_global_atomic_fadd_v2f16(addr, x); diff --git a/clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl b/clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl index 625f0660482a9..b1e45e6d6e6dc 100644 --- a/clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl +++ b/clang/test/CodeGenOpenCL/enqueue-kernel-non-entry-block.cl @@ -18,7 +18,7 @@ kernel void test(int i) { // SPIR64: %block_sizes = alloca [1 x i64] // COMMON-LABEL: if.then: // COMMON-NOT: alloca -// CHECK-DEBUG: getelementptr {{.*}} %block_sizes, {{.*}} !dbg ![[TEMPLOCATION:[0-9]+]] +// CHECK-DEBUG: getelementptr {{.*}} %block_sizes{{.*}}, {{.*}} !dbg ![[TEMPLOCATION:[0-9]+]] // COMMON-LABEL: if.end queue_t default_queue; unsigned flags = 0; diff --git a/clang/test/CodeGenOpenCL/opencl_types.cl b/clang/test/CodeGenOpenCL/opencl_types.cl index 5b1c2afd4f1e3..7cab853c76d9a 100644 --- a/clang/test/CodeGenOpenCL/opencl_types.cl +++ b/clang/test/CodeGenOpenCL/opencl_types.cl @@ -42,7 +42,7 @@ kernel void foo(image1d_t img) { // CHECK-AMDGCN: alloca ptr addrspace(4) event_t evt; // CHECK-SPIR: alloca target("spirv.Event") - // CHECK-AMDGCN: alloca ptr addrspace(5) + // CHECK-AMDGCN: alloca ptr clk_event_t clk_evt; // CHECK-SPIR: alloca target("spirv.DeviceEvent") // CHECK-AMDGCN: alloca ptr addrspace(1) diff --git a/clang/test/CoverageMapping/branch-constfolded.cpp b/clang/test/CoverageMapping/branch-constfolded.cpp index 1e7e32808e838..a2ac1c1eacd28 100644 --- a/clang/test/CoverageMapping/branch-constfolded.cpp +++ b/clang/test/CoverageMapping/branch-constfolded.cpp @@ -5,94 +5,94 @@ // CHECK-LABEL: _Z6fand_0b: bool fand_0(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2 - return false && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0 + return false && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, (#0 - #1) } // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #2, (#1 - #2) // CHECK-LABEL: _Z6fand_1b: bool fand_1(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2 return a && true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1) -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = #2, 0 // CHECK-LABEL: _Z6fand_2bb: bool fand_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3 - return false && a && b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0 + return false && a && b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, (#0 - #3) } // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #4, (#3 - #4) // CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = #2, (#1 - #2) // CHECK-LABEL: _Z6fand_3bb: bool fand_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3 return a && true && b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3) -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = #4, 0 // CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = #2, (#1 - #2) // CHECK-LABEL: _Z6fand_4bb: bool fand_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3 return a && b && false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3) } // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = #4, (#3 - #4) - // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:25 = 0, 0 + // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:25 = 0, (#1 - #2) // CHECK-LABEL: _Z6fand_5b: bool fand_5(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:3, C:2 - return false && true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0 -} // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:23 = 0, 0 + return false && true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, (#0 - #1) +} // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:23 = #2, 0 // CHECK-LABEL: _Z6fand_6b: bool fand_6(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2 - return true && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0 + return true && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = #1, 0 } // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = #2, (#1 - #2) // CHECK-LABEL: _Z6fand_7b: bool fand_7(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2 return a && false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1) -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, (#1 - #2) // CHECK-LABEL: _Z5for_0b: bool for_0(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2 - return true || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0 + return true || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = (#0 - #1), 0 } // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#1 - #2), #2 // CHECK-LABEL: _Z5for_1b: bool for_1(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2 return a || false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1 -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, #2 // CHECK-LABEL: _Z5for_2bb: bool for_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3 - return true || a || b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0 + return true || a || b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = (#0 - #3), 0 } // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#3 - #4), #4 // CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = (#1 - #2), #2 // CHECK-LABEL: _Z5for_3bb: bool for_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3 return a || false || b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3 -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, #4 // CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = (#1 - #2), #2 // CHECK-LABEL: _Z5for_4bb: bool for_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3 return a || b || true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3 } // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = (#3 - #4), #4 - // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:24 = 0, 0 + // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:24 = (#1 - #2), 0 // CHECK-LABEL: _Z5for_5b: bool for_5(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:3, C:2 - return true || false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0 -} // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:23 = 0, 0 + return true || false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = (#0 - #1), 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:23 = 0, #2 // CHECK-LABEL: _Z5for_6b: bool for_6(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2 - return false || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0 + return false || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, #1 } // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = (#1 - #2), #2 // CHECK-LABEL: _Z5for_7b: bool for_7(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2 return a || true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1 -} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0 +} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = (#1 - #2), 0 // CHECK-LABEL: _Z5for_8b: bool for_8(bool a) { // MCDC: Decision,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:20 = M:3, C:2 - // CHECK: Branch,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:11 = 0, 0 - // CHECK: Branch,File 0, [[@LINE+1]]:15 -> [[@LINE+1]]:20 = 0, 0 + // CHECK: Branch,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:11 = #2, 0 + // CHECK: Branch,File 0, [[@LINE+1]]:15 -> [[@LINE+1]]:20 = 0, (#2 - #3) if (true && false) return true; else diff --git a/clang/test/CoverageMapping/if.cpp b/clang/test/CoverageMapping/if.cpp index 445cdfc20e2af..b6fd525e930f9 100644 --- a/clang/test/CoverageMapping/if.cpp +++ b/clang/test/CoverageMapping/if.cpp @@ -14,7 +14,7 @@ struct S { // CHECK-LABEL: _Z3foov: // CHECK-NEXT: [[@LINE+3]]:12 -> [[@LINE+8]]:2 = #0 // CHECK-NEXT: [[@LINE+3]]:15 -> [[@LINE+3]]:19 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = 0, 0 + // CHECK-NEXT: Branch,File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:19 = #2, 0 void foo() { // CHECK-NEXT: Gap,File 0, [[@LINE+1]]:21 -> [[@LINE+1]]:22 = #2 if (int j = true ? nop() // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = #2 : nop(); // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = (#0 - #2) @@ -168,7 +168,7 @@ int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = // GH-45481 S s; s.the_prop = 0? 1 : 2; // CHECK-NEXT: File 0, [[@LINE]]:16 -> [[@LINE]]:17 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:17 = 0, 0 + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:17 = 0, (#0 - #7) // CHECK-NEXT: Gap,File 0, [[@LINE-2]]:18 -> [[@LINE-2]]:19 = #7 // CHECK-NEXT: File 0, [[@LINE-3]]:19 -> [[@LINE-3]]:20 = #7 // CHECK-NEXT: File 0, [[@LINE-4]]:23 -> [[@LINE-4]]:24 = (#0 - #7) diff --git a/clang/test/CoverageMapping/macro-expansion.c b/clang/test/CoverageMapping/macro-expansion.c index ad71fb15eda42..4cd2c93437193 100644 --- a/clang/test/CoverageMapping/macro-expansion.c +++ b/clang/test/CoverageMapping/macro-expansion.c @@ -4,29 +4,29 @@ // CHECK: File 1, [[@LINE+7]]:12 -> [[@LINE+7]]:38 = #0 // CHECK-NEXT: File 1, [[@LINE+6]]:15 -> [[@LINE+6]]:28 = (#0 + #2) // CHECK-NEXT: File 1, [[@LINE+5]]:21 -> [[@LINE+5]]:22 = (#0 + #2) -// CHECK: Branch,File 1, [[@LINE+4]]:21 -> [[@LINE+4]]:22 = 0, 0 +// CHECK: Branch,File 1, [[@LINE+4]]:21 -> [[@LINE+4]]:22 = 0, ((#0 + #2) - #3) // CHECK-NEXT: File 1, [[@LINE+3]]:24 -> [[@LINE+3]]:26 = #3 // CHECK-NEXT: File 1, [[@LINE+2]]:36 -> [[@LINE+2]]:37 = (#0 + #2) -// CHECK-NEXT: Branch,File 1, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, 0 +// CHECK-NEXT: Branch,File 1, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, #0 #define M1 do { if (0) {} } while (0) // CHECK-NEXT: File 2, [[@LINE+12]]:15 -> [[@LINE+12]]:41 = #0 // CHECK-NEXT: File 2, [[@LINE+11]]:18 -> [[@LINE+11]]:31 = (#0 + #4) // CHECK-NEXT: File 2, [[@LINE+10]]:24 -> [[@LINE+10]]:25 = (#0 + #4) // CHECK: File 2, [[@LINE+9]]:27 -> [[@LINE+9]]:29 = #5 // CHECK-NEXT: File 2, [[@LINE+8]]:39 -> [[@LINE+8]]:40 = (#0 + #4) -// CHECK-NEXT: Branch,File 2, [[@LINE+7]]:39 -> [[@LINE+7]]:40 = 0, 0 +// CHECK-NEXT: Branch,File 2, [[@LINE+7]]:39 -> [[@LINE+7]]:40 = 0, #0 // CHECK-NEXT: File 3, [[@LINE+6]]:15 -> [[@LINE+6]]:41 = #0 // CHECK-NEXT: File 3, [[@LINE+5]]:18 -> [[@LINE+5]]:31 = (#0 + #6) // CHECK-NEXT: File 3, [[@LINE+4]]:24 -> [[@LINE+4]]:25 = (#0 + #6) // CHECK: File 3, [[@LINE+3]]:27 -> [[@LINE+3]]:29 = #7 // CHECK-NEXT: File 3, [[@LINE+2]]:39 -> [[@LINE+2]]:40 = (#0 + #6) -// CHECK-NEXT: Branch,File 3, [[@LINE+1]]:39 -> [[@LINE+1]]:40 = 0, 0 +// CHECK-NEXT: Branch,File 3, [[@LINE+1]]:39 -> [[@LINE+1]]:40 = 0, #0 #define M2(x) do { if (x) {} } while (0) // CHECK-NEXT: File 4, [[@LINE+5]]:15 -> [[@LINE+5]]:38 = #0 // CHECK-NEXT: File 4, [[@LINE+4]]:18 -> [[@LINE+4]]:28 = (#0 + #8) // CHECK-NEXT: Expansion,File 4, [[@LINE+3]]:20 -> [[@LINE+3]]:22 = (#0 + #8) // CHECK-NEXT: File 4, [[@LINE+2]]:36 -> [[@LINE+2]]:37 = (#0 + #8) -// CHECK-NEXT: Branch,File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, 0 +// CHECK-NEXT: Branch,File 4, [[@LINE+1]]:36 -> [[@LINE+1]]:37 = 0, #0 #define M3(x) do { M2(x); } while (0) // CHECK-NEXT: File 5, [[@LINE+4]]:15 -> [[@LINE+4]]:27 = #0 // CHECK-NEXT: File 5, [[@LINE+3]]:16 -> [[@LINE+3]]:19 = #0 diff --git a/clang/test/CoverageMapping/mcdc-scratch-space.c b/clang/test/CoverageMapping/mcdc-scratch-space.c index a263e9b688fae..60e456948a518 100644 --- a/clang/test/CoverageMapping/mcdc-scratch-space.c +++ b/clang/test/CoverageMapping/mcdc-scratch-space.c @@ -3,7 +3,7 @@ // CHECK: builtin_macro0: int builtin_macro0(int a) { // CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:15 = M:3, C:2 - return (__LINE__ // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:11 = 0, 0 [1,2,0] + return (__LINE__ // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:11 = #1, 0 [1,2,0] && a); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:15 = #2, (#1 - #2) [2,0,0] } @@ -11,7 +11,7 @@ int builtin_macro0(int a) { int builtin_macro1(int a) { // CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:22 = M:3, C:2 return (a // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = (#0 - #1), #1 [1,0,2] - || __LINE__); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:14 = 0, 0 [2,0,0] + || __LINE__); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:14 = (#1 - #2), 0 [2,0,0] } #define PRE(x) pre_##x diff --git a/clang/test/CoverageMapping/mcdc-system-headers.cpp b/clang/test/CoverageMapping/mcdc-system-headers.cpp index ae26ed5fe469f..cb1c8743c36e8 100644 --- a/clang/test/CoverageMapping/mcdc-system-headers.cpp +++ b/clang/test/CoverageMapping/mcdc-system-headers.cpp @@ -17,10 +17,10 @@ int func0(int a) { // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:3, C:2 // W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded file = 1) - // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = 0, 0 [1,2,0] + // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, 0 [1,2,0] return (CONST && a); // CHECK: Branch,File 0, [[@LINE-1]]:20 -> [[@LINE-1]]:21 = #2, (#1 - #2) [2,0,0] - // W_SYS: Branch,File 1, [[@LINE-16]]:15 -> [[@LINE-16]]:17 = 0, 0 [1,2,0] + // W_SYS: Branch,File 1, [[@LINE-16]]:15 -> [[@LINE-16]]:17 = #1, 0 [1,2,0] } // CHECK: _Z5func1ii: diff --git a/clang/test/CoverageMapping/switch.cpp b/clang/test/CoverageMapping/switch.cpp index b47c0e8009952..a1fee644faaf0 100644 --- a/clang/test/CoverageMapping/switch.cpp +++ b/clang/test/CoverageMapping/switch.cpp @@ -2,13 +2,13 @@ // CHECK: foo void foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+11]]:2 = #0 - switch(i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = ((#0 - #2) - #3), (#2 + #3) + switch(i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = 0, ((#0 - #2) - #3) // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+5]]:10 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:11 = #2 - return; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2) + return; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:12 -> [[@LINE+1]]:3 = 0 case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #3 - break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3) + break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, 0 } // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = #1 int x = 0; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #1 @@ -18,24 +18,24 @@ int nop() { return 0; } // CHECK: bar void bar(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+21]]:2 = #0 - switch (i) // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = #0, 0 + switch (i) // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = 0, #0 ; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:6 = 0 switch (i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+17]]:2 = #1 - } // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = #1, 0 + } // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = 0, #1 switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+14]]:2 = #2 - nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = #2, 0 + nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = 0, #2 // CHECK-NEXT: File 0, [[@LINE-1]]:5 -> [[@LINE-1]]:10 = 0 switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+11]]:2 = #3 - case 1: // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = (#3 - #5), #5 + case 1: // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:11 -> [[@LINE-1]]:12 = 0, (#3 - #5) // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE+1]]:10 = #5 - nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #5, (#3 - #5) + nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #5, 0 // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> [[@LINE+7]]:2 = #4 - switch (i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = (#4 - #7), #7 + switch (i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = 0, (#4 - #7) nop(); // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+2]]:10 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #7 - nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, (#4 - #7) + nop(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, 0 } nop(); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #6 } @@ -44,7 +44,7 @@ void bar(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+21]]:2 = #0 void baz() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+5]]:2 = #0 switch (int i = true ? nop() // CHECK: [[@LINE]]:26 -> [[@LINE]]:31 = #2 : nop(); // CHECK-NEXT: [[@LINE]]:26 -> [[@LINE]]:31 = (#0 - #2) - i) {} // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = #0, 0 + i) {} // CHECK-NEXT: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = 0, #0 nop(); // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:2 = #1 } @@ -53,35 +53,35 @@ int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+39]]:2 = #0 int i = 0; switch(i) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+8]]:10 = 0 case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = #2 - i = 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2) + i = 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, 0 break; // CHECK-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:3 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = #3 - i = 2; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3) + i = 2; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, 0 break; // CHECK-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:3 = 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #4 - break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #4, (#0 - #4) + break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #4, 0 } // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+1]]:3 = #1 switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+27]]:2 = #1 case 0: // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+7]]:10 = 0 i = 1; // CHECK-NEXT: File 0, [[@LINE-1]]:3 -> [[@LINE+1]]:10 = #6 - break; // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #6, (#1 - #6) + break; // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:3 -> [[@LINE-2]]:9 = #6, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:10 = #7 - i = 2; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, (#1 - #7) + i = 2; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #7, 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = (#7 + #8) - break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #8, (#1 - #8) + break; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #8, 0 } // CHECK-NEXT: Gap,File 0, [[@LINE]]:4 -> [[@LINE+2]]:3 = #5 // CHECK-NEXT: File 0, [[@LINE+1]]:3 -> [[@LINE+17]]:2 = #5 - switch(i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = ((((#5 - #10) - #11) - #12) - #13), (((#10 + #11) + #12) + #13) + switch(i) { // CHECK-NEXT: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = 0, ((((#5 - #10) - #11) - #12) - #13) // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+8]]:11 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+7]]:11 = #10 - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #10, (#5 - #10) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #10, 0 case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:11 = (#10 + #11) - i = 11; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #11, (#5 - #11) + i = 11; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #11, 0 case 3: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:11 = ((#10 + #11) + #12) - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #12, (#5 - #12) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #12, 0 case 4: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:11 = (((#10 + #11) + #12) + #13) - i = 99; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #13, (#5 - #13) + i = 99; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #13, 0 } foo(1); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:11 = #9 @@ -95,10 +95,10 @@ int pr44011(int i) { // CHECK-NEXT: File 0, [[@LINE]]:20 -> {{.*}}:2 = #0 switch (i) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+6]]:13 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = #2 - return 0; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2) + return 0; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:3 = 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 = #3 - return 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #3, (#0 - #3) + return 1; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #3, 0 } } // A region for counter #1 is missing due to the missing return. @@ -106,17 +106,17 @@ int pr44011(int i) { // CHECK-NEXT: File 0, [[@LINE]]:20 -> {{.*}}:2 = #0 // FIXME: End location for "case 1" shouldn't point at the end of the switch. // CHECK: fallthrough int fallthrough(int i) { // CHECK-NEXT: File 0, [[@LINE]]:24 -> [[@LINE+14]]:2 = #0 - // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:11 = ((((#0 - #2) - #3) - #4) - #5), (((#2 + #3) + #4) + #5) + // CHECK-NEXT: Branch,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:11 = 0, ((((#0 - #2) - #3) - #4) - #5) switch(i) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:13 -> [[@LINE+10]]:10 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+9]]:10 = #2 - i = 23; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, (#0 - #2) + i = 23; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #2, 0 case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = (#2 + #3) - i = 11; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3) + i = 11; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, 0 break; // CHECK-NEXT: Gap,File 0, [[@LINE]]:11 -> [[@LINE+1]]:3 = 0 case 3: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:10 = #4 - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, 0 case 4: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = (#4 + #5) - i = 99; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #5, (#0 - #5) + i = 99; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #5, 0 break; } } @@ -126,12 +126,12 @@ void abort(void) __attribute((noreturn)); int noret(int x) { // CHECK-NEXT: File 0, [[@LINE]]:18 -> [[@LINE+11]]:2 switch (x) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+8]]:14 = 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:12 - abort(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, (#0 - #2) + abort(); // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+1]]:3 = 0 case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:13 - return 5; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, (#0 - #3) + return 5; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #3, 0 // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:3 = 0 case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:14 - return 10; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4) + return 10; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, 0 } } diff --git a/clang/test/CoverageMapping/switchmacro.c b/clang/test/CoverageMapping/switchmacro.c index 4c98cc7d9403a..0696e7490cdf9 100644 --- a/clang/test/CoverageMapping/switchmacro.c +++ b/clang/test/CoverageMapping/switchmacro.c @@ -6,7 +6,7 @@ int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> {{[0-9]+}}:2 = #0 switch (i) { // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> {{[0-9]+}}:11 = 0 default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> {{[0-9]+}}:11 = #2 - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, (#0 - #2) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:10 = #2, 0 if (i == 1) // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:15 = #2 // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:15 = #3, (#2 - #3) return 0; // CHECK: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = #3 @@ -15,7 +15,7 @@ int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> {{[0-9]+}}:2 = #0 // CHECK-NEXT: File 0, [[@LINE+1]]:8 -> {{[0-9]+}}:11 = (#2 - #3) FOO(1); case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:13 = ((#2 + #4) - #3) - // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, (#0 - #4) + // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:3 -> [[@LINE-1]]:9 = #4, 0 return 2; // CHECK-NEXT: Gap,File 0, [[@LINE]]:14 -> [[@LINE+4]]:3 = 0 // CHECK-NEXT: Expansion,File 0, [[@LINE+2]]:3 -> [[@LINE+2]]:6 = 0 diff --git a/clang/test/Driver/XRay/xray-shared.cpp b/clang/test/Driver/XRay/xray-shared.cpp new file mode 100644 index 0000000000000..215854e1fc7ce --- /dev/null +++ b/clang/test/Driver/XRay/xray-shared.cpp @@ -0,0 +1,17 @@ +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fpic -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s +// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s +// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fno-PIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-PIC +// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -fno-pic -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-PIC + +// On 64 bit darwin, PIC is always enabled +// RUN: %clang -### --target=x86_64-apple-darwin -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s + +// Check unsupported targets +// RUN: not %clang -### --target=aarch64-pc-freebsd -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET +// RUN: not %clang -### --target=arm64-apple-macos -fPIC -fxray-instrument -fxray-shared -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TARGET + +// CHECK: "-cc1" {{.*}}"-fxray-instrument" {{.*}}"-fxray-shared" +// ERR-TARGET: error: unsupported option '-fxray-shared' for target +// ERR-PIC: error: option '-fxray-shared' cannot be specified without '-fPIC' + diff --git a/clang/test/Driver/aarch64-v96a.c b/clang/test/Driver/aarch64-v96a.c index 80c99be934334..343e347c928ca 100644 --- a/clang/test/Driver/aarch64-v96a.c +++ b/clang/test/Driver/aarch64-v96a.c @@ -53,3 +53,16 @@ // RUN: %clang -target aarch64 -march=armv9.6a+sve-f16f32mm -### -c %s 2>&1 | FileCheck -check-prefix=V96A-SVE-F16F32MM %s // RUN: %clang -target aarch64 -march=armv9.6-a+sve-f16f32mm -### -c %s 2>&1 | FileCheck -check-prefix=V96A-SVE-F16F32MM %s // V96A-SVE-F16F32MM: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.6a"{{.*}} "-target-feature" "+sve-f16f32mm" +// +// RUN: %clang -target aarch64 -march=armv9.6a+lsui -### -c %s 2>&1 | FileCheck -check-prefix=V96A-LSUI %s +// RUN: %clang -target aarch64 -march=armv9.6-a+lsui -### -c %s 2>&1 | FileCheck -check-prefix=V96A-LSUI %s +// V96A-LSUI: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.6a"{{.*}} "-target-feature" "+lsui" +// +// RUN: %clang -target aarch64 -march=armv9.6a+occmo -### -c %s 2>&1 | FileCheck -check-prefix=V96A-OCCMO %s +// RUN: %clang -target aarch64 -march=armv9.6-a+occmo -### -c %s 2>&1 | FileCheck -check-prefix=V96A-OCCMO %s +// V96A-OCCMO: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.6a"{{.*}} "-target-feature" "+occmo" +// +// RUN: %clang -target aarch64 -march=armv9.6a+pcdphint -### -c %s 2>&1 | FileCheck -check-prefix=V96A-PCDPHINT %s +// RUN: %clang -target aarch64 -march=armv9.6-a+pcdphint -### -c %s 2>&1 | FileCheck -check-prefix=V96A-PCDPHINT %s +// V96A-PCDPHINT: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.6a"{{.*}} "-target-feature" "+pcdphint" +// diff --git a/clang/test/Driver/amdgpu-macros.cl b/clang/test/Driver/amdgpu-macros.cl index 3e4a570671bab..dd5a4483e4d60 100644 --- a/clang/test/Driver/amdgpu-macros.cl +++ b/clang/test/Driver/amdgpu-macros.cl @@ -128,6 +128,7 @@ // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1150 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1150 -DFAMILY=GFX11 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1151 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1151 -DFAMILY=GFX11 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1152 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1152 -DFAMILY=GFX11 +// RUN: %clang -E -dM -target amdgcn -mcpu=gfx1153 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1153 -DFAMILY=GFX11 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1200 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1200 -DFAMILY=GFX12 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1201 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1201 -DFAMILY=GFX12 diff --git a/clang/test/Driver/amdgpu-mcpu.cl b/clang/test/Driver/amdgpu-mcpu.cl index 4b0ef92b682a5..42ce33db6eec0 100644 --- a/clang/test/Driver/amdgpu-mcpu.cl +++ b/clang/test/Driver/amdgpu-mcpu.cl @@ -113,6 +113,7 @@ // RUN: %clang -### -target amdgcn -mcpu=gfx1150 %s 2>&1 | FileCheck --check-prefix=GFX1150 %s // RUN: %clang -### -target amdgcn -mcpu=gfx1151 %s 2>&1 | FileCheck --check-prefix=GFX1151 %s // RUN: %clang -### -target amdgcn -mcpu=gfx1152 %s 2>&1 | FileCheck --check-prefix=GFX1152 %s +// RUN: %clang -### -target amdgcn -mcpu=gfx1153 %s 2>&1 | FileCheck --check-prefix=GFX1153 %s // RUN: %clang -### -target amdgcn -mcpu=gfx1200 %s 2>&1 | FileCheck --check-prefix=GFX1200 %s // RUN: %clang -### -target amdgcn -mcpu=gfx1201 %s 2>&1 | FileCheck --check-prefix=GFX1201 %s @@ -166,6 +167,7 @@ // GFX1150: "-target-cpu" "gfx1150" // GFX1151: "-target-cpu" "gfx1151" // GFX1152: "-target-cpu" "gfx1152" +// GFX1153: "-target-cpu" "gfx1153" // GFX1200: "-target-cpu" "gfx1200" // GFX1201: "-target-cpu" "gfx1201" diff --git a/clang/test/Driver/cuda-cross-compiling.c b/clang/test/Driver/cuda-cross-compiling.c index 5f24e7a5accb0..126e9e9fc83d5 100644 --- a/clang/test/Driver/cuda-cross-compiling.c +++ b/clang/test/Driver/cuda-cross-compiling.c @@ -104,4 +104,4 @@ // RUN: %clang -target nvptx64-nvidia-cuda --cuda-feature=+ptx63 -march=sm_52 -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=FEATURE %s -// FEATURE: clang-nvlink-wrapper{{.*}}"--feature" "+ptx63" +// FEATURE: clang-nvlink-wrapper{{.*}}"--plugin-opt=-mattr=+ptx63" diff --git a/clang/test/Driver/flang/msvc-link.f90 b/clang/test/Driver/flang/msvc-link.f90 index 3f7e162a9a611..463749510eb5f 100644 --- a/clang/test/Driver/flang/msvc-link.f90 +++ b/clang/test/Driver/flang/msvc-link.f90 @@ -1,5 +1,5 @@ -! RUN: %clang --driver-mode=flang --target=x86_64-pc-windows-msvc -### %s -Ltest 2>&1 | FileCheck %s -! -! Test that user provided paths come before the Flang runtimes -! CHECK: "-libpath:test" -! CHECK: "-libpath:{{.*(\\|/)}}lib" +! RUN: %clang --driver-mode=flang --target=x86_64-pc-windows-msvc -### %s -Ltest 2>&1 | FileCheck %s +! +! Test that user provided paths come before the Flang runtimes +! CHECK: "-libpath:test" +! CHECK: "-libpath:{{.*(\\|/)}}lib" diff --git a/clang/test/Driver/loongarch-march.c b/clang/test/Driver/loongarch-march.c index 2d5b315d962a1..d4cd5b07ae905 100644 --- a/clang/test/Driver/loongarch-march.c +++ b/clang/test/Driver/loongarch-march.c @@ -39,21 +39,21 @@ // CC1-LA64V1P1: "-target-cpu" "loongarch64" // CC1-LA64V1P1-NOT: "-target-feature" -// CC1-LA64V1P1: "-target-feature" "+64bit" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+ual" "-target-feature" "+frecipe" +// CC1-LA64V1P1: "-target-feature" "+64bit" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+ual" "-target-feature" "+frecipe" "-target-feature" "+lam-bh" // CC1-LA64V1P1-NOT: "-target-feature" // CC1-LA64V1P1: "-target-abi" "lp64d" // CC1-LA664: "-target-cpu" "la664" // CC1-LA664-NOT: "-target-feature" -// CC1-LA664: "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+lasx" "-target-feature" "+ual" "-target-feature" "+frecipe" +// CC1-LA664: "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+lasx" "-target-feature" "+ual" "-target-feature" "+frecipe" "-target-feature" "+lam-bh" // CC1-LA664-NOT: "-target-feature" // CC1-LA664: "-target-abi" "lp64d" // IR-LOONGARCH64: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+f,+ual" // IR-LA464: attributes #[[#]] ={{.*}}"target-cpu"="la464" {{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx,+ual" // IR-LA64V1P0: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+lsx,+ual" -// IR-LA64V1P1: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+frecipe,+lsx,+ual" -// IR-LA664: attributes #[[#]] ={{.*}}"target-cpu"="la664" {{.*}}"target-features"="+64bit,+d,+f,+frecipe,+lasx,+lsx,+ual" +// IR-LA64V1P1: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+frecipe,+lam-bh,+lsx,+ual" +// IR-LA664: attributes #[[#]] ={{.*}}"target-cpu"="la664" {{.*}}"target-features"="+64bit,+d,+f,+frecipe,+lam-bh,+lasx,+lsx,+ual" int foo(void) { return 3; diff --git a/clang/test/Driver/loongarch-mlam-bh.c b/clang/test/Driver/loongarch-mlam-bh.c new file mode 100644 index 0000000000000..6f2901e594dfc --- /dev/null +++ b/clang/test/Driver/loongarch-mlam-bh.c @@ -0,0 +1,30 @@ +/// Test -m[no]lam-bh options. + +// RUN: %clang --target=loongarch64 -mlam-bh -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1-LAM-BH +// RUN: %clang --target=loongarch64 -mno-lam-bh -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1-NO-LAM-BH +// RUN: %clang --target=loongarch64 -mno-lam-bh -mlam-bh -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1-LAM-BH +// RUN: %clang --target=loongarch64 -mlam-bh -mno-lam-bh -fsyntax-only %s -### 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CC1-NO-LAM-BH + +// RUN: %clang --target=loongarch64 -mlam-bh -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefix=IR-LAM-BH +// RUN: %clang --target=loongarch64 -mno-lam-bh -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefix=IR-NO-LAM-BH +// RUN: %clang --target=loongarch64 -mno-lam-bh -mlam-bh -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefix=IR-LAM-BH +// RUN: %clang --target=loongarch64 -mlam-bh -mno-lam-bh -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefix=IR-NO-LAM-BH + + +// CC1-LAM-BH: "-target-feature" "+lam-bh" +// CC1-NO-LAM-BH: "-target-feature" "-lam-bh" + +// IR-LAM-BH: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+lam-bh{{(,.*)?}}" +// IR-NO-LAM-BH: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-lam-bh{{(,.*)?}}" + +int foo(void) { + return 42; +} \ No newline at end of file diff --git a/clang/test/Driver/print-supported-extensions-aarch64.c b/clang/test/Driver/print-supported-extensions-aarch64.c index fbc0d70c4901c..7ff4f17beff75 100644 --- a/clang/test/Driver/print-supported-extensions-aarch64.c +++ b/clang/test/Driver/print-supported-extensions-aarch64.c @@ -40,12 +40,15 @@ // CHECK-NEXT: lse FEAT_LSE Enable Armv8.1-A Large System Extension (LSE) atomic instructions // CHECK-NEXT: lse128 FEAT_LSE128 Enable Armv9.4-A 128-bit Atomic instructions // CHECK-NEXT: lsfe FEAT_LSFE Enable Armv9.6-A base Atomic floating-point in-memory instructions +// CHECK-NEXT: lsui FEAT_LSUI Enable Armv9.6-A unprivileged load/store instructions // CHECK-NEXT: lut FEAT_LUT Enable Lookup Table instructions // CHECK-NEXT: mops FEAT_MOPS Enable Armv8.8-A memcpy and memset acceleration instructions // CHECK-NEXT: memtag FEAT_MTE, FEAT_MTE2 Enable Memory Tagging Extension // CHECK-NEXT: simd FEAT_AdvSIMD Enable Advanced SIMD instructions +// CHECK-NEXT: occmo FEAT_OCCMO Enable Armv9.6-A Outer cacheable cache maintenance operations // CHECK-NEXT: pauth FEAT_PAuth Enable Armv8.3-A Pointer Authentication extension // CHECK-NEXT: pauth-lr FEAT_PAuth_LR Enable Armv9.5-A PAC enhancements +// CHECK-NEXT: pcdphint FEAT_PCDPHINT Enable Armv9.6-A Producer Consumer Data Placement hints // CHECK-NEXT: pmuv3 FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension // CHECK-NEXT: predres FEAT_SPECRES Enable Armv8.5-A execution and data prediction invalidation instructions // CHECK-NEXT: rng FEAT_RNG Enable Random Number generation instructions diff --git a/clang/test/Driver/ps5-linker.c b/clang/test/Driver/ps5-linker.c index 4ae65963e361a..d18309a650726 100644 --- a/clang/test/Driver/ps5-linker.c +++ b/clang/test/Driver/ps5-linker.c @@ -14,6 +14,22 @@ // CHECK-NO-PIE-NOT: "-pie" // CHECK-SHARED: "--shared" +// Test the driver passes PlayStation-specific -z options to the linker. + +// RUN: %clang --target=x86_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-Z %s + +// CHECK-Z: {{ld(\.exe)?}}" +// CHECK-Z-SAME: "-z" "now" +// CHECK-Z-SAME: "-z" "start-stop-visibility=hidden" +// CHECK-Z-SAME: "-z" "dead-reloc-in-nonalloc=.debug_*=0xffffffffffffffff" +// CHECK-Z-SAME: "-z" "dead-reloc-in-nonalloc=.debug_ranges=0xfffffffffffffffe" +// CHECK-Z-SAME: "-z" "dead-reloc-in-nonalloc=.debug_loc=0xfffffffffffffffe" + +// RUN: %clang --target=x86_64-sie-ps5 -r %s -### 2>&1 | FileCheck --check-prefixes=CHECK-NO-Z %s + +// CHECK-NO-Z: {{ld(\.exe)?}}" +// CHECK-NO-Z-NOT: "-z" + // Test that -static is forwarded to the linker // RUN: %clang --target=x86_64-sie-ps5 -static %s -### 2>&1 | FileCheck --check-prefixes=CHECK-STATIC %s diff --git a/clang/test/FixIt/fixit-newline-style.c b/clang/test/FixIt/fixit-newline-style.c index 2aac143d4d753..61e4df67e85ba 100644 --- a/clang/test/FixIt/fixit-newline-style.c +++ b/clang/test/FixIt/fixit-newline-style.c @@ -1,11 +1,11 @@ -// RUN: %clang_cc1 -pedantic -Wunused-label -fno-diagnostics-show-line-numbers -x c %s 2>&1 | FileCheck %s -strict-whitespace - -// This file intentionally uses a CRLF newline style -// CHECK: warning: unused label 'ddd' -// CHECK-NEXT: {{^ ddd:}} -// CHECK-NEXT: {{^ \^~~~$}} -// CHECK-NOT: {{^ ;}} -void f(void) { - ddd: - ; -} +// RUN: %clang_cc1 -pedantic -Wunused-label -fno-diagnostics-show-line-numbers -x c %s 2>&1 | FileCheck %s -strict-whitespace + +// This file intentionally uses a CRLF newline style +// CHECK: warning: unused label 'ddd' +// CHECK-NEXT: {{^ ddd:}} +// CHECK-NEXT: {{^ \^~~~$}} +// CHECK-NOT: {{^ ;}} +void f(void) { + ddd: + ; +} diff --git a/clang/test/Format/dry-run-warning.cpp b/clang/test/Format/dry-run-warning.cpp new file mode 100644 index 0000000000000..4b85de40b8cd0 --- /dev/null +++ b/clang/test/Format/dry-run-warning.cpp @@ -0,0 +1,22 @@ +// RUN: echo '{' > %t.json +// RUN: echo ' "married": true' >> %t.json +// RUN: echo '}' >> %t.json + +// RUN: clang-format -n -style=LLVM %t.json 2>&1 | FileCheck %s -allow-empty + +// RUN: clang-format -n -style=LLVM < %t.json 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK2 -strict-whitespace + +// RUN: echo '{' > %t.json +// RUN: echo ' "married" : true' >> %t.json +// RUN: echo '}' >> %t.json + +// RUN: clang-format -n -style=LLVM < %t.json 2>&1 | FileCheck %s -allow-empty + +// RUN: clang-format -n -style=LLVM %t.json 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK2 -strict-whitespace + +// RUN: rm %t.json + +// CHECK-NOT: warning +// CHECK2: warning: code should be clang-formatted diff --git a/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c b/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c index 2faeaba322921..d6724444c0667 100644 --- a/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c +++ b/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -E -frewrite-includes %s | %clang_cc1 - -// expected-no-diagnostics -// Note: This source file has CRLF line endings. -// This test validates that -frewrite-includes translates the end of line (EOL) -// form used in header files to the EOL form used in the the primary source -// file when the files use different EOL forms. -#include "rewrite-includes-mixed-eol-crlf.h" -#include "rewrite-includes-mixed-eol-lf.h" +// RUN: %clang_cc1 -E -frewrite-includes %s | %clang_cc1 - +// expected-no-diagnostics +// Note: This source file has CRLF line endings. +// This test validates that -frewrite-includes translates the end of line (EOL) +// form used in header files to the EOL form used in the the primary source +// file when the files use different EOL forms. +#include "rewrite-includes-mixed-eol-crlf.h" +#include "rewrite-includes-mixed-eol-lf.h" diff --git a/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h b/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h index baedc282296bd..0439b88b75e2c 100644 --- a/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h +++ b/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h @@ -1,11 +1,11 @@ -// Note: This header file has CRLF line endings. -// The indentation in some of the conditional inclusion directives below is -// intentional and is required for this test to function as a regression test -// for GH59736. -_Static_assert(__LINE__ == 5, ""); -#if 1 -_Static_assert(__LINE__ == 7, ""); - #if 1 - _Static_assert(__LINE__ == 9, ""); - #endif -#endif +// Note: This header file has CRLF line endings. +// The indentation in some of the conditional inclusion directives below is +// intentional and is required for this test to function as a regression test +// for GH59736. +_Static_assert(__LINE__ == 5, ""); +#if 1 +_Static_assert(__LINE__ == 7, ""); + #if 1 + _Static_assert(__LINE__ == 9, ""); + #endif +#endif diff --git a/clang/test/Frontend/system-header-line-directive-ms-lineendings.c b/clang/test/Frontend/system-header-line-directive-ms-lineendings.c index dffdd5cf1959a..92fc07f65e0d4 100644 --- a/clang/test/Frontend/system-header-line-directive-ms-lineendings.c +++ b/clang/test/Frontend/system-header-line-directive-ms-lineendings.c @@ -1,21 +1,21 @@ -// RUN: %clang_cc1 %s -E -o - -I %S/Inputs -isystem %S/Inputs/SystemHeaderPrefix | FileCheck %s -#include -#include - -#include "line-directive.h" - -// This tests that the line numbers for the current file are correctly outputted -// for the include-file-completed test case. This file should be CRLF. - -// CHECK: # 1 "{{.*}}system-header-line-directive-ms-lineendings.c" 2 -// CHECK: # 1 "{{.*}}noline.h" 1 3 -// CHECK: foo(void); -// CHECK: # 3 "{{.*}}system-header-line-directive-ms-lineendings.c" 2 -// CHECK: # 1 "{{.*}}line-directive-in-system.h" 1 3 -// The "3" below indicates that "foo.h" is considered a system header. -// CHECK: # 1 "foo.h" 3 -// CHECK: foo(void); -// CHECK: # 4 "{{.*}}system-header-line-directive-ms-lineendings.c" 2 -// CHECK: # 1 "{{.*}}line-directive.h" 1 -// CHECK: # 10 "foo.h"{{$}} -// CHECK: # 6 "{{.*}}system-header-line-directive-ms-lineendings.c" 2 +// RUN: %clang_cc1 %s -E -o - -I %S/Inputs -isystem %S/Inputs/SystemHeaderPrefix | FileCheck %s +#include +#include + +#include "line-directive.h" + +// This tests that the line numbers for the current file are correctly outputted +// for the include-file-completed test case. This file should be CRLF. + +// CHECK: # 1 "{{.*}}system-header-line-directive-ms-lineendings.c" 2 +// CHECK: # 1 "{{.*}}noline.h" 1 3 +// CHECK: foo(void); +// CHECK: # 3 "{{.*}}system-header-line-directive-ms-lineendings.c" 2 +// CHECK: # 1 "{{.*}}line-directive-in-system.h" 1 3 +// The "3" below indicates that "foo.h" is considered a system header. +// CHECK: # 1 "foo.h" 3 +// CHECK: foo(void); +// CHECK: # 4 "{{.*}}system-header-line-directive-ms-lineendings.c" 2 +// CHECK: # 1 "{{.*}}line-directive.h" 1 +// CHECK: # 10 "foo.h"{{$}} +// CHECK: # 6 "{{.*}}system-header-line-directive-ms-lineendings.c" 2 diff --git a/clang/test/Headers/opencl-c-header.cl b/clang/test/Headers/opencl-c-header.cl index 7c4c673cf2ee0..7317ff0adaafb 100644 --- a/clang/test/Headers/opencl-c-header.cl +++ b/clang/test/Headers/opencl-c-header.cl @@ -190,6 +190,9 @@ global atomic_int z = ATOMIC_VAR_INIT(99); #if __opencl_c_ext_image_raw10_raw12 != 1 #error "Incorrectly defined __opencl_c_ext_image_raw10_raw12" #endif +#if __opencl_c_ext_image_unorm_int_2_101010 != 1 +#error "Incorrectly defined __opencl_c_ext_image_unorm_int_2_101010" +#endif #else @@ -277,6 +280,9 @@ global atomic_int z = ATOMIC_VAR_INIT(99); #ifdef __opencl_c_ext_image_raw10_raw12 #error "Incorrect __opencl_c_ext_image_raw10_raw12 define" #endif +#ifdef __opencl_c_ext_image_unorm_int_2_101010 +#error "Incorrect __opencl_c_ext_image_unorm_int_2_101010 define" +#endif #endif //(defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) diff --git a/clang/test/Index/pipe-size.cl b/clang/test/Index/pipe-size.cl index 08b936f1a9b07..a48857baef1a6 100644 --- a/clang/test/Index/pipe-size.cl +++ b/clang/test/Index/pipe-size.cl @@ -11,6 +11,6 @@ __kernel void testPipe( pipe int test ) // SPIR: store i32 4, ptr %s, align 4 // SPIR64: store target("spirv.Pipe", 0) %test, ptr %test.addr, align 8 // SPIR64: store i32 8, ptr %s, align 4 - // AMDGCN: store ptr addrspace(1) %test, ptr addrspace(5) %test.addr, align 8 - // AMDGCN: store i32 8, ptr addrspace(5) %s, align 4 + // AMDGCN: store ptr addrspace(1) %test, ptr %test{{.*}}, align 8 + // AMDGCN: store i32 8, ptr %s{{.*}}, align 4 } diff --git a/clang/test/Misc/target-invalid-cpu-note/amdgcn.c b/clang/test/Misc/target-invalid-cpu-note/amdgcn.c index 0f01ff35035bd..b3ddbd53a0391 100644 --- a/clang/test/Misc/target-invalid-cpu-note/amdgcn.c +++ b/clang/test/Misc/target-invalid-cpu-note/amdgcn.c @@ -66,6 +66,7 @@ // CHECK-SAME: {{^}}, gfx1150 // CHECK-SAME: {{^}}, gfx1151 // CHECK-SAME: {{^}}, gfx1152 +// CHECK-SAME: {{^}}, gfx1153 // CHECK-SAME: {{^}}, gfx1200 // CHECK-SAME: {{^}}, gfx1201 // CHECK-SAME: {{^}}, gfx9-generic diff --git a/clang/test/Misc/target-invalid-cpu-note/nvptx.c b/clang/test/Misc/target-invalid-cpu-note/nvptx.c index 43524ab2906bf..a59e1c6fab1c4 100644 --- a/clang/test/Misc/target-invalid-cpu-note/nvptx.c +++ b/clang/test/Misc/target-invalid-cpu-note/nvptx.c @@ -74,6 +74,7 @@ // CHECK-SAME: {{^}}, gfx1150 // CHECK-SAME: {{^}}, gfx1151 // CHECK-SAME: {{^}}, gfx1152 +// CHECK-SAME: {{^}}, gfx1153 // CHECK-SAME: {{^}}, gfx12-generic // CHECK-SAME: {{^}}, gfx1200 // CHECK-SAME: {{^}}, gfx1201 diff --git a/clang/test/PCH/cxx2a-constraints-crash.cpp b/clang/test/PCH/cxx2a-constraints-crash.cpp index 637c55f0c879c..5c54ba4c42546 100644 --- a/clang/test/PCH/cxx2a-constraints-crash.cpp +++ b/clang/test/PCH/cxx2a-constraints-crash.cpp @@ -1,7 +1,5 @@ -// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t -// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s - -// expected-no-diagnostics +// RUN: %clang_cc1 -std=c++2a -fallow-pch-with-compiler-errors -emit-pch -o %t %s -verify +// RUN: %clang_cc1 -std=c++2a -fallow-pch-with-compiler-errors -include-pch %t %s -verify #ifndef HEADER #define HEADER @@ -27,3 +25,12 @@ int main() { } #endif + +namespace GH99036 { + +template +concept C; // expected-error {{expected '='}} + +template void f(); + +} // namespace GH99036 diff --git a/clang/test/ParserHLSL/bitfields.hlsl b/clang/test/ParserHLSL/bitfields.hlsl index 57b6705babdc1..307d1143a068e 100644 --- a/clang/test/ParserHLSL/bitfields.hlsl +++ b/clang/test/ParserHLSL/bitfields.hlsl @@ -1,31 +1,31 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -ast-dump -x hlsl -o - %s | FileCheck %s - - -struct MyBitFields { - // CHECK: FieldDecl 0x{{[0-9a-f]+}} col:16 referenced field1 'unsigned int' - // CHECK:-ConstantExpr 0x{{[0-9a-f]+}} 'int' - // CHECK:-value: Int 3 - // CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} 'int' 3 - unsigned int field1 : 3; // 3 bits for field1 - - // CHECK:FieldDecl 0x{{[0-9a-f]+}} col:16 referenced field2 'unsigned int' - // CHECK:-ConstantExpr 0x{{[0-9a-f]+}} 'int' - // CHECK:-value: Int 4 - // CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} 'int' 4 - unsigned int field2 : 4; // 4 bits for field2 - - // CHECK:FieldDecl 0x{{[0-9a-f]+}} col:7 field3 'int' - // CHECK:-ConstantExpr 0x{{[0-9a-f]+}} 'int' - // CHECK:-value: Int 5 - // CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} 'int' 5 - int field3 : 5; // 5 bits for field3 (signed) -}; - - - -[numthreads(1,1,1)] -void main() { - MyBitFields m; - m.field1 = 4; - m.field2 = m.field1*2; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -ast-dump -x hlsl -o - %s | FileCheck %s + + +struct MyBitFields { + // CHECK: FieldDecl 0x{{[0-9a-f]+}} col:16 referenced field1 'unsigned int' + // CHECK:-ConstantExpr 0x{{[0-9a-f]+}} 'int' + // CHECK:-value: Int 3 + // CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} 'int' 3 + unsigned int field1 : 3; // 3 bits for field1 + + // CHECK:FieldDecl 0x{{[0-9a-f]+}} col:16 referenced field2 'unsigned int' + // CHECK:-ConstantExpr 0x{{[0-9a-f]+}} 'int' + // CHECK:-value: Int 4 + // CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} 'int' 4 + unsigned int field2 : 4; // 4 bits for field2 + + // CHECK:FieldDecl 0x{{[0-9a-f]+}} col:7 field3 'int' + // CHECK:-ConstantExpr 0x{{[0-9a-f]+}} 'int' + // CHECK:-value: Int 5 + // CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} 'int' 5 + int field3 : 5; // 5 bits for field3 (signed) +}; + + + +[numthreads(1,1,1)] +void main() { + MyBitFields m; + m.field1 = 4; + m.field2 = m.field1*2; } \ No newline at end of file diff --git a/clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl b/clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl index 5b228d039345e..2eebc920388b5 100644 --- a/clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl +++ b/clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl @@ -1,21 +1,21 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s - -// tests that hlsl annotations are properly parsed when applied on field decls, -// and that the annotation gets properly placed on the AST. - -struct Eg9{ - // CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} col:8 implicit struct Eg9 - // CHECK: FieldDecl 0x{{[0-9a-f]+}} col:16 referenced a 'unsigned int' - // CHECK: -HLSLSV_DispatchThreadIDAttr 0x{{[0-9a-f]+}} - unsigned int a : SV_DispatchThreadID; -}; -Eg9 e9; - - -RWBuffer In : register(u1); - - -[numthreads(1,1,1)] -void main() { - In[0] = e9.a; -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s + +// tests that hlsl annotations are properly parsed when applied on field decls, +// and that the annotation gets properly placed on the AST. + +struct Eg9{ + // CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} col:8 implicit struct Eg9 + // CHECK: FieldDecl 0x{{[0-9a-f]+}} col:16 referenced a 'unsigned int' + // CHECK: -HLSLSV_DispatchThreadIDAttr 0x{{[0-9a-f]+}} + unsigned int a : SV_DispatchThreadID; +}; +Eg9 e9; + + +RWBuffer In : register(u1); + + +[numthreads(1,1,1)] +void main() { + In[0] = e9.a; +} diff --git a/clang/test/ParserHLSL/hlsl_contained_type_attr.hlsl b/clang/test/ParserHLSL/hlsl_contained_type_attr.hlsl index 476ec39e14da9..5a72aa242e581 100644 --- a/clang/test/ParserHLSL/hlsl_contained_type_attr.hlsl +++ b/clang/test/ParserHLSL/hlsl_contained_type_attr.hlsl @@ -1,25 +1,25 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -x hlsl -ast-dump -o - %s | FileCheck %s - -typedef vector float4; - -// CHECK: -TypeAliasDecl 0x{{[0-9a-f]+}} -// CHECK: -HLSLAttributedResourceType 0x{{[0-9a-f]+}} '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]] -using ResourceIntAliasT = __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(int)]]; -ResourceIntAliasT h1; - -// CHECK: -VarDecl 0x{{[0-9a-f]+}} col:82 h2 '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float4)]] -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float4)]] h2; - -// CHECK: ClassTemplateDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 6]]:30 S -// CHECK: TemplateTypeParmDecl 0x{{[0-9a-f]+}} col:20 referenced typename depth 0 index 0 T -// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 4]]:30 struct S definition -// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:79 h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::contained_type(T)]] -template struct S { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(T)]] h; -}; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -x hlsl -ast-dump -o - %s | FileCheck %s + +typedef vector float4; + +// CHECK: -TypeAliasDecl 0x{{[0-9a-f]+}} +// CHECK: -HLSLAttributedResourceType 0x{{[0-9a-f]+}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]] +using ResourceIntAliasT = __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(int)]]; +ResourceIntAliasT h1; + +// CHECK: -VarDecl 0x{{[0-9a-f]+}} col:82 h2 '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float4)]] +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float4)]] h2; + +// CHECK: ClassTemplateDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 6]]:30 S +// CHECK: TemplateTypeParmDecl 0x{{[0-9a-f]+}} col:20 referenced typename depth 0 index 0 T +// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 4]]:30 struct S definition +// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:79 h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(T)]] +template struct S { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(T)]] h; +}; diff --git a/clang/test/ParserHLSL/hlsl_contained_type_attr_error.hlsl b/clang/test/ParserHLSL/hlsl_contained_type_attr_error.hlsl index 673ff8693b83b..b2d492d95945c 100644 --- a/clang/test/ParserHLSL/hlsl_contained_type_attr_error.hlsl +++ b/clang/test/ParserHLSL/hlsl_contained_type_attr_error.hlsl @@ -1,28 +1,28 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -x hlsl -o - %s -verify - -typedef vector float4; - -// expected-error@+1{{'contained_type' attribute cannot be applied to a declaration}} -[[hlsl::contained_type(float4)]] __hlsl_resource_t h1; - -// expected-error@+1{{'contained_type' attribute takes one argument}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type()]] h3; - -// expected-error@+1{{expected a type}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(0)]] h4; - -// expected-error@+1{{unknown type name 'a'}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(a)]] h5; - -// expected-error@+1{{expected a type}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type("b", c)]] h6; - -// expected-warning@+1{{attribute 'contained_type' is already applied}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] [[hlsl::contained_type(float)]] h7; - -// expected-warning@+1{{attribute 'contained_type' is already applied with different arguments}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] [[hlsl::contained_type(int)]] h8; - -// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}} -// expected-error@+1{{attribute 'contained_type' can be used only on HLSL intangible type '__hlsl_resource_t'}} -float [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] res5; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -x hlsl -o - %s -verify + +typedef vector float4; + +// expected-error@+1{{'contained_type' attribute cannot be applied to a declaration}} +[[hlsl::contained_type(float4)]] __hlsl_resource_t h1; + +// expected-error@+1{{'contained_type' attribute takes one argument}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type()]] h3; + +// expected-error@+1{{expected a type}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(0)]] h4; + +// expected-error@+1{{unknown type name 'a'}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(a)]] h5; + +// expected-error@+1{{expected a type}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type("b", c)]] h6; + +// expected-warning@+1{{attribute 'contained_type' is already applied}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] [[hlsl::contained_type(float)]] h7; + +// expected-warning@+1{{attribute 'contained_type' is already applied with different arguments}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] [[hlsl::contained_type(int)]] h8; + +// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}} +// expected-error@+1{{attribute 'contained_type' can be used only on HLSL intangible type '__hlsl_resource_t'}} +float [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] res5; diff --git a/clang/test/ParserHLSL/hlsl_is_rov_attr.hlsl b/clang/test/ParserHLSL/hlsl_is_rov_attr.hlsl index 487dc32413032..836d129c8d000 100644 --- a/clang/test/ParserHLSL/hlsl_is_rov_attr.hlsl +++ b/clang/test/ParserHLSL/hlsl_is_rov_attr.hlsl @@ -1,22 +1,22 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s - -// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition -// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:68 h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::is_rov]] -struct MyBuffer { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] h; -}; - -// CHECK: VarDecl 0x{{[0-9a-f]+}} col:66 res '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] -// CHECK-SAME{LITERAL}: [[hlsl::is_rov]] -__hlsl_resource_t [[hlsl::is_rov]] [[hlsl::resource_class(SRV)]] res; - -// CHECK: FunctionDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 4]]:6 f 'void () -// CHECK: VarDecl 0x{{[0-9a-f]+}} col:72 r '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]] -// CHECK-SAME{LITERAL}: [[hlsl::is_rov]] -void f() { - __hlsl_resource_t [[hlsl::resource_class(Sampler)]] [[hlsl::is_rov]] r; -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s + +// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition +// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:68 h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::is_rov]] +struct MyBuffer { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] h; +}; + +// CHECK: VarDecl 0x{{[0-9a-f]+}} col:66 res '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::is_rov]] +__hlsl_resource_t [[hlsl::is_rov]] [[hlsl::resource_class(SRV)]] res; + +// CHECK: FunctionDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 4]]:6 f 'void () +// CHECK: VarDecl 0x{{[0-9a-f]+}} col:72 r '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]] +// CHECK-SAME{LITERAL}: [[hlsl::is_rov]] +void f() { + __hlsl_resource_t [[hlsl::resource_class(Sampler)]] [[hlsl::is_rov]] r; +} diff --git a/clang/test/ParserHLSL/hlsl_is_rov_attr_error.hlsl b/clang/test/ParserHLSL/hlsl_is_rov_attr_error.hlsl index 9bb64ea990e28..3b2c12e7a96c5 100644 --- a/clang/test/ParserHLSL/hlsl_is_rov_attr_error.hlsl +++ b/clang/test/ParserHLSL/hlsl_is_rov_attr_error.hlsl @@ -1,20 +1,20 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify - -// expected-error@+1{{'is_rov' attribute cannot be applied to a declaration}} -[[hlsl::is_rov]] __hlsl_resource_t res0; - -// expected-error@+1{{HLSL resource needs to have [[hlsl::resource_class()]] attribute}} -__hlsl_resource_t [[hlsl::is_rov]] res1; - -// expected-error@+1{{'is_rov' attribute takes no arguments}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov(3)]] res2; - -// expected-error@+1{{use of undeclared identifier 'gibberish'}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov(gibberish)]] res3; - -// expected-warning@+1{{attribute 'is_rov' is already applied}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] [[hlsl::is_rov]] res4; - -// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}} -// expected-error@+1{{attribute 'is_rov' can be used only on HLSL intangible type '__hlsl_resource_t'}} -float [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] res5; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify + +// expected-error@+1{{'is_rov' attribute cannot be applied to a declaration}} +[[hlsl::is_rov]] __hlsl_resource_t res0; + +// expected-error@+1{{HLSL resource needs to have [[hlsl::resource_class()]] attribute}} +__hlsl_resource_t [[hlsl::is_rov]] res1; + +// expected-error@+1{{'is_rov' attribute takes no arguments}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov(3)]] res2; + +// expected-error@+1{{use of undeclared identifier 'gibberish'}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov(gibberish)]] res3; + +// expected-warning@+1{{attribute 'is_rov' is already applied}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] [[hlsl::is_rov]] res4; + +// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}} +// expected-error@+1{{attribute 'is_rov' can be used only on HLSL intangible type '__hlsl_resource_t'}} +float [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] res5; diff --git a/clang/test/ParserHLSL/hlsl_raw_buffer_attr.hlsl b/clang/test/ParserHLSL/hlsl_raw_buffer_attr.hlsl index e09ed5586c102..84c924eec24ef 100644 --- a/clang/test/ParserHLSL/hlsl_raw_buffer_attr.hlsl +++ b/clang/test/ParserHLSL/hlsl_raw_buffer_attr.hlsl @@ -1,22 +1,22 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s - -// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition -// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:72 h1 '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] -struct MyBuffer { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] h1; -}; - -// CHECK: VarDecl 0x{{[0-9a-f]+}} col:70 h2 '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] -// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] -__hlsl_resource_t [[hlsl::raw_buffer]] [[hlsl::resource_class(SRV)]] h2; - -// CHECK: FunctionDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 4]]:6 f 'void () -// CHECK: VarDecl 0x{{[0-9a-f]+}} col:72 h3 '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] -void f() { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] h3; -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s + +// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition +// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:72 h1 '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] +struct MyBuffer { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] h1; +}; + +// CHECK: VarDecl 0x{{[0-9a-f]+}} col:70 h2 '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] +__hlsl_resource_t [[hlsl::raw_buffer]] [[hlsl::resource_class(SRV)]] h2; + +// CHECK: FunctionDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 4]]:6 f 'void () +// CHECK: VarDecl 0x{{[0-9a-f]+}} col:72 h3 '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] +void f() { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] h3; +} diff --git a/clang/test/ParserHLSL/hlsl_raw_buffer_attr_error.hlsl b/clang/test/ParserHLSL/hlsl_raw_buffer_attr_error.hlsl index a10aca4e96fc5..77530cbf9e4d9 100644 --- a/clang/test/ParserHLSL/hlsl_raw_buffer_attr_error.hlsl +++ b/clang/test/ParserHLSL/hlsl_raw_buffer_attr_error.hlsl @@ -1,17 +1,17 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify - -// expected-error@+1{{'raw_buffer' attribute cannot be applied to a declaration}} -[[hlsl::raw_buffer]] __hlsl_resource_t res0; - -// expected-error@+1{{'raw_buffer' attribute takes no arguments}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer(3)]] res2; - -// expected-error@+1{{use of undeclared identifier 'gibberish'}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer(gibberish)]] res3; - -// expected-warning@+1{{attribute 'raw_buffer' is already applied}} -__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] [[hlsl::raw_buffer]] res4; - -// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}} -// expected-error@+1{{attribute 'raw_buffer' can be used only on HLSL intangible type '__hlsl_resource_t'}} -float [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] res5; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify + +// expected-error@+1{{'raw_buffer' attribute cannot be applied to a declaration}} +[[hlsl::raw_buffer]] __hlsl_resource_t res0; + +// expected-error@+1{{'raw_buffer' attribute takes no arguments}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer(3)]] res2; + +// expected-error@+1{{use of undeclared identifier 'gibberish'}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer(gibberish)]] res3; + +// expected-warning@+1{{attribute 'raw_buffer' is already applied}} +__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] [[hlsl::raw_buffer]] res4; + +// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}} +// expected-error@+1{{attribute 'raw_buffer' can be used only on HLSL intangible type '__hlsl_resource_t'}} +float [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] res5; diff --git a/clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl b/clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl index 9fee9edddf619..fbada8b4b99f7 100644 --- a/clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl +++ b/clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl @@ -1,37 +1,37 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s - -// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition -// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:51 h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -struct MyBuffer { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] h; -}; - -// CHECK: VarDecl 0x{{[0-9a-f]+}} col:49 res '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] -__hlsl_resource_t [[hlsl::resource_class(SRV)]] res; - -// CHECK: FunctionDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 3]]:6 f 'void () -// CHECK: VarDecl 0x{{[0-9a-f]+}} col:55 r '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]] -void f() { - __hlsl_resource_t [[hlsl::resource_class(Sampler)]] r; -} - -// CHECK: ClassTemplateDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 6]]:29 MyBuffer2 -// CHECK: TemplateTypeParmDecl 0x{{[0-9a-f]+}} col:19 typename depth 0 index 0 T -// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 4]]:29 struct MyBuffer2 definition -// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} col:29 implicit struct MyBuffer2 -// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:51 h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -template struct MyBuffer2 { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] h; -}; - -// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} line:[[# @LINE - 4]]:29 struct MyBuffer2 definition implicit_instantiation -// CHECK: TemplateArgument type 'float' -// CHECK: BuiltinType 0x{{[0-9a-f]+}} 'float' -// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} col:29 implicit struct MyBuffer2 -// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:51 h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -MyBuffer2 myBuffer2; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s + +// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition +// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:51 h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +struct MyBuffer { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] h; +}; + +// CHECK: VarDecl 0x{{[0-9a-f]+}} col:49 res '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +__hlsl_resource_t [[hlsl::resource_class(SRV)]] res; + +// CHECK: FunctionDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 3]]:6 f 'void () +// CHECK: VarDecl 0x{{[0-9a-f]+}} col:55 r '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]] +void f() { + __hlsl_resource_t [[hlsl::resource_class(Sampler)]] r; +} + +// CHECK: ClassTemplateDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 6]]:29 MyBuffer2 +// CHECK: TemplateTypeParmDecl 0x{{[0-9a-f]+}} col:19 typename depth 0 index 0 T +// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} line:[[# @LINE + 4]]:29 struct MyBuffer2 definition +// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} col:29 implicit struct MyBuffer2 +// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:51 h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +template struct MyBuffer2 { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] h; +}; + +// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} line:[[# @LINE - 4]]:29 struct MyBuffer2 definition implicit_instantiation +// CHECK: TemplateArgument type 'float' +// CHECK: BuiltinType 0x{{[0-9a-f]+}} 'float' +// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} col:29 implicit struct MyBuffer2 +// CHECK: FieldDecl 0x{{[0-9a-f]+}} col:51 h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +MyBuffer2 myBuffer2; diff --git a/clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl b/clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl index a0a4da1dc2bf4..63e39daff949b 100644 --- a/clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl +++ b/clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl @@ -1,22 +1,22 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify - -// expected-error@+1{{'resource_class' attribute cannot be applied to a declaration}} -[[hlsl::resource_class(UAV)]] __hlsl_resource_t e0; - -// expected-error@+1{{'resource_class' attribute takes one argument}} -__hlsl_resource_t [[hlsl::resource_class()]] e1; - -// expected-warning@+1{{ResourceClass attribute argument not supported: gibberish}} -__hlsl_resource_t [[hlsl::resource_class(gibberish)]] e2; - -// expected-warning@+1{{attribute 'resource_class' is already applied with different arguments}} -__hlsl_resource_t [[hlsl::resource_class(SRV)]] [[hlsl::resource_class(UAV)]] e3; - -// expected-warning@+1{{attribute 'resource_class' is already applied}} -__hlsl_resource_t [[hlsl::resource_class(SRV)]] [[hlsl::resource_class(SRV)]] e4; - -// expected-error@+1{{'resource_class' attribute takes one argument}} -__hlsl_resource_t [[hlsl::resource_class(SRV, "aa")]] e5; - -// expected-error@+1{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}} -float [[hlsl::resource_class(UAV)]] e6; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify + +// expected-error@+1{{'resource_class' attribute cannot be applied to a declaration}} +[[hlsl::resource_class(UAV)]] __hlsl_resource_t e0; + +// expected-error@+1{{'resource_class' attribute takes one argument}} +__hlsl_resource_t [[hlsl::resource_class()]] e1; + +// expected-warning@+1{{ResourceClass attribute argument not supported: gibberish}} +__hlsl_resource_t [[hlsl::resource_class(gibberish)]] e2; + +// expected-warning@+1{{attribute 'resource_class' is already applied with different arguments}} +__hlsl_resource_t [[hlsl::resource_class(SRV)]] [[hlsl::resource_class(UAV)]] e3; + +// expected-warning@+1{{attribute 'resource_class' is already applied}} +__hlsl_resource_t [[hlsl::resource_class(SRV)]] [[hlsl::resource_class(SRV)]] e4; + +// expected-error@+1{{'resource_class' attribute takes one argument}} +__hlsl_resource_t [[hlsl::resource_class(SRV, "aa")]] e5; + +// expected-error@+1{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}} +float [[hlsl::resource_class(UAV)]] e6; diff --git a/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl b/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl index 8885e39237357..38d27bc21e4aa 100644 --- a/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl +++ b/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl @@ -1,21 +1,21 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s - -// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <> class RWBuffer definition implicit_instantiation -// CHECK: -TemplateArgument type 'float' -// CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float' -// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]] -// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <> Implicit TypedBuffer -RWBuffer Buffer1; - -// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <> class RasterizerOrderedBuffer definition implicit_instantiation -// CHECK: -TemplateArgument type 'vector' -// CHECK: `-ExtVectorType 0x{{[0-9a-f]+}} 'vector' 4 -// CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float' -// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)] -// CHECK-SAME{LITERAL}: [[hlsl::is_rov]] -// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector)]] -// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <> Implicit TypedBuffer -RasterizerOrderedBuffer > BufferArray3[4]; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s + +// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <> class RWBuffer definition implicit_instantiation +// CHECK: -TemplateArgument type 'float' +// CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float' +// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]] +// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <> Implicit TypedBuffer +RWBuffer Buffer1; + +// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <> class RasterizerOrderedBuffer definition implicit_instantiation +// CHECK: -TemplateArgument type 'vector' +// CHECK: `-ExtVectorType 0x{{[0-9a-f]+}} 'vector' 4 +// CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float' +// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)] +// CHECK-SAME{LITERAL}: [[hlsl::is_rov]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector)]] +// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <> Implicit TypedBuffer +RasterizerOrderedBuffer > BufferArray3[4]; diff --git a/clang/test/Preprocessor/embed_zos.c b/clang/test/Preprocessor/embed_zos.c new file mode 100644 index 0000000000000..564a65f42afcd --- /dev/null +++ b/clang/test/Preprocessor/embed_zos.c @@ -0,0 +1,109 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t/media && cp %S/Inputs/media/art.txt %t/media/ +// RUN: chtag -r %t/media/art.txt +// RUN: %clang_cc1 -std=c23 %s -fsyntax-only --embed-dir=%t -verify +// expected-no-diagnostics + +// REQUIRES: shell, system-zos + +const char data[] = { +#embed +}; +const char data2[] = { +#embed +, 0 +}; +const char data3[] = { +#embed suffix(, 0) +}; +const char data4[] = { +#embed suffix(,) +0 +}; +static_assert(sizeof(data) == 274); +static_assert(' ' == data[0]); +static_assert('_' == data[11]); +static_assert('\n' == data[273]); +static_assert(sizeof(data2) == 275); +static_assert(' ' == data2[0]); +static_assert('_' == data2[11]); +static_assert('\n' == data2[273]); +static_assert('\0' == data2[274]); +static_assert(sizeof(data3) == 275); +static_assert(' ' == data3[0]); +static_assert('_' == data3[11]); +static_assert('\n' == data3[273]); +static_assert('\0' == data3[274]); +static_assert(sizeof(data4) == 275); +static_assert(' ' == data4[0]); +static_assert('_' == data4[11]); +static_assert('\n' == data4[273]); +static_assert('\0' == data4[274]); + +const signed char data5[] = { +#embed +}; +const signed char data6[] = { +#embed +, 0 +}; +const signed char data7[] = { +#embed suffix(, 0) +}; +const signed char data8[] = { +#embed suffix(,) +0 +}; +static_assert(sizeof(data5) == 274); +static_assert(' ' == data5[0]); +static_assert('_' == data5[11]); +static_assert('\n' == data5[273]); +static_assert(sizeof(data6) == 275); +static_assert(' ' == data6[0]); +static_assert('_' == data6[11]); +static_assert('\n' == data6[273]); +static_assert('\0' == data6[274]); +static_assert(sizeof(data7) == 275); +static_assert(' ' == data7[0]); +static_assert('_' == data7[11]); +static_assert('\n' == data7[273]); +static_assert('\0' == data7[274]); +static_assert(sizeof(data8) == 275); +static_assert(' ' == data8[0]); +static_assert('_' == data8[11]); +static_assert('\n' == data8[273]); +static_assert('\0' == data8[274]); + +const unsigned char data9[] = { +#embed +}; +const unsigned char data10[] = { +0, +#embed +}; +const unsigned char data11[] = { +#embed prefix(0,) +}; +const unsigned char data12[] = { +0 +#embed prefix(,) +}; +static_assert(sizeof(data9) == 274); +static_assert(' ' == data9[0]); +static_assert('_' == data9[11]); +static_assert('\n' == data9[273]); +static_assert(sizeof(data10) == 275); +static_assert(' ' == data10[1]); +static_assert('_' == data10[12]); +static_assert('\n' == data10[274]); +static_assert('\0' == data10[0]); +static_assert(sizeof(data11) == 275); +static_assert(' ' == data11[1]); +static_assert('_' == data11[12]); +static_assert('\n' == data11[274]); +static_assert('\0' == data11[0]); +static_assert(sizeof(data12) == 275); +static_assert(' ' == data12[1]); +static_assert('_' == data12[12]); +static_assert('\n' == data12[274]); +static_assert('\0' == data12[0]); diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c index 771d56ffb1c1b..8019292e0f10e 100644 --- a/clang/test/Preprocessor/init-loongarch.c +++ b/clang/test/Preprocessor/init-loongarch.c @@ -798,7 +798,7 @@ // LA64-FPU0-LP64S-NOT: #define __loongarch_single_float // LA64-FPU0-LP64S: #define __loongarch_soft_float 1 -/// Check __loongarch_arch{_tune/_frecipe}. +/// Check __loongarch_arch{_tune/_frecipe/_lam_bh}. // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s @@ -819,30 +819,41 @@ // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 -Xclang -target-feature -Xclang -lsx | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 -Xclang -target-feature -Xclang +frecipe | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.0 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lsx | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE,LAM-BH -DARCH=la64v1.1 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 -Xclang -target-feature -Xclang -frecipe | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,LAM-BH -DARCH=la64v1.0 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 -Xclang -target-feature -Xclang -lsx | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=loongarch64 -DTUNE=loongarch64 %s +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE,LAM-BH -DARCH=loongarch64 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +frecipe | \ // RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=loongarch64 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lsx -Xclang -target-feature -Xclang +frecipe | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.0 -DTUNE=loongarch64 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 -Xclang -target-feature -Xclang +lam-bh | \ +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,LAM-BH -DARCH=la64v1.0 -DTUNE=loongarch64 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 -Xclang -target-feature -Xclang -lam-bh | \ +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.0 -DTUNE=loongarch64 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lam-bh | \ +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,LAM-BH -DARCH=loongarch64 -DTUNE=loongarch64 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lsx -Xclang -target-feature -Xclang +lam-bh | \ +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,LAM-BH -DARCH=la64v1.0 -DTUNE=loongarch64 %s +// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 -Xclang -target-feature -Xclang +frecipe -Xclang -target-feature -Xclang +lam-bh | \ +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE -DARCH=la64v1.1 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la664 | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la664 -DTUNE=la664 %s +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE,LAM-BH -DARCH=la664 -DTUNE=la664 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=la664 | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=la664 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -mtune=la664 | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la664 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la664 -mtune=loongarch64 | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la664 -DTUNE=loongarch64 %s +// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE,LAM-BH -DARCH=la664 -DTUNE=loongarch64 %s // ARCH-TUNE: #define __loongarch_arch "[[ARCH]]" // FRECIPE: #define __loongarch_frecipe 1 +// LAM-BH: #define __loongarch_lam_bh 1 // ARCH-TUNE: #define __loongarch_tune "[[TUNE]]" // RUN: %clang --target=loongarch64 -mlsx -x c -E -dM %s -o - \ diff --git a/clang/test/Sema/aarch64-sve-vector-trig-ops.c b/clang/test/Sema/aarch64-sve-vector-trig-ops.c index f853abcd3379f..3fe6834be2e0b 100644 --- a/clang/test/Sema/aarch64-sve-vector-trig-ops.c +++ b/clang/test/Sema/aarch64-sve-vector-trig-ops.c @@ -1,65 +1,65 @@ -// RUN: %clang_cc1 -triple aarch64 -target-feature +sve \ -// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify -// REQUIRES: aarch64-registered-target - -#include - -svfloat32_t test_asin_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_asin(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -svfloat32_t test_acos_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_acos(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -svfloat32_t test_atan_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_atan(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -svfloat32_t test_atan2_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_atan2(v, v); - // expected-error@-1 {{1st argument must be a floating point type}} -} - -svfloat32_t test_sin_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_sin(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -svfloat32_t test_cos_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_cos(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -svfloat32_t test_tan_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_tan(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -svfloat32_t test_sinh_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_sinh(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -svfloat32_t test_cosh_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_cosh(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -svfloat32_t test_tanh_vv_i8mf8(svfloat32_t v) { - - return __builtin_elementwise_tanh(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} +// RUN: %clang_cc1 -triple aarch64 -target-feature +sve \ +// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify +// REQUIRES: aarch64-registered-target + +#include + +svfloat32_t test_asin_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_asin(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +svfloat32_t test_acos_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_acos(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +svfloat32_t test_atan_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_atan(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +svfloat32_t test_atan2_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_atan2(v, v); + // expected-error@-1 {{1st argument must be a floating point type}} +} + +svfloat32_t test_sin_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_sin(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +svfloat32_t test_cos_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_cos(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +svfloat32_t test_tan_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_tan(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +svfloat32_t test_sinh_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_sinh(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +svfloat32_t test_cosh_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_cosh(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +svfloat32_t test_tanh_vv_i8mf8(svfloat32_t v) { + + return __builtin_elementwise_tanh(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} diff --git a/clang/test/Sema/attr-target-clones-aarch64.c b/clang/test/Sema/attr-target-clones-aarch64.c index 2765c06c68fbb..191ca9ba96506 100644 --- a/clang/test/Sema/attr-target-clones-aarch64.c +++ b/clang/test/Sema/attr-target-clones-aarch64.c @@ -22,7 +22,7 @@ int __attribute__((target_clones("rng", "fp16fml+fp", "default"))) redecl4(void) // expected-error@+3 {{'target_clones' attribute does not match previous declaration}} // expected-note@-2 {{previous declaration is here}} // expected-warning@+1 {{version list contains entries that don't impact code generation}} -int __attribute__((target_clones("dgh+memtag+rpres", "ebf16+dpb", "default"))) redecl4(void) { return 1; } +int __attribute__((target_clones("dgh+rpres", "ebf16+dpb", "default"))) redecl4(void) { return 1; } int __attribute__((target_version("flagm2"))) redef2(void) { return 1; } // expected-error@+2 {{multiversioned function redeclarations require identical target attributes}} diff --git a/clang/test/Sema/avr-size-align.c b/clang/test/Sema/avr-size-align.c new file mode 100644 index 0000000000000..9fe94410c91c4 --- /dev/null +++ b/clang/test/Sema/avr-size-align.c @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 %s -triple avr -fsyntax-only + +_Static_assert(sizeof(char) == 1, "sizeof(char) == 1"); +_Static_assert(_Alignof(char) == 1, "_Alignof(char) == 1"); +_Static_assert(__alignof(char) == 1, "__alignof(char) == 1"); + +_Static_assert(sizeof(short) == 2, "sizeof(short) == 2"); +_Static_assert(_Alignof(short) == 1, "_Alignof(short) == 1"); +_Static_assert(__alignof(short) == 1, "__alignof(short) == 1"); + +_Static_assert(sizeof(unsigned short) == 2, "sizeof(unsigned short) == 2"); +_Static_assert(_Alignof(unsigned short) == 1, "_Alignof(unsigned short) == 1"); +_Static_assert(__alignof(unsigned short) == 1, "__alignof(unsigned short) == 1"); + +_Static_assert(sizeof(int) == 2, "sizeof(int) == 2"); +_Static_assert(_Alignof(int) == 1, "_Alignof(int) == 1"); +_Static_assert(__alignof(int) == 1, "__alignof(int) == 1"); + +_Static_assert(sizeof(unsigned int) == 2, "sizeof(unsigned int) == 2"); +_Static_assert(_Alignof(unsigned int) == 1, "_Alignof(unsigned int) == 1"); +_Static_assert(__alignof(unsigned int) == 1, "__alignof(unsigned int) == 1"); + +_Static_assert(sizeof(long) == 4, "sizeof(long) == 4"); +_Static_assert(_Alignof(long) == 1, "_Alignof(long) == 1"); +_Static_assert(__alignof(long) == 1, "__alignof(long) == 1"); + +_Static_assert(sizeof(unsigned long) == 4, "sizeof(unsigned long) == 4"); +_Static_assert(_Alignof(unsigned long) == 1, "_Alignof(unsigned long) == 1"); +_Static_assert(__alignof(unsigned long) == 1, "__alignof(unsigned long) == 1"); + +_Static_assert(sizeof(long long) == 8, "sizeof(long long) == 8"); +_Static_assert(_Alignof(long long) == 1, "_Alignof(long long) == 1"); +_Static_assert(__alignof(long long) == 1, "__alignof(long long) == 1"); + +_Static_assert(sizeof(unsigned long long) == 8, "sizeof(unsigned long long) == 8"); +_Static_assert(_Alignof(unsigned long long) == 1, "_Alignof(unsigned long long) == 1"); +_Static_assert(__alignof(unsigned long long) == 1, "__alignof(unsigned long long) == 1"); + +_Static_assert(sizeof(float) == 4, "sizeof(float) == 4"); +_Static_assert(_Alignof(float) == 1, "_Alignof(float) == 1"); +_Static_assert(__alignof(float) == 1, "__alignof(float) == 1"); + +_Static_assert(sizeof(double) == 4, "sizeof(double) == 4"); +_Static_assert(_Alignof(double) == 1, "_Alignof(double) == 1"); +_Static_assert(__alignof(double) == 1, "__alignof(double) == 1"); + +_Static_assert(sizeof(long double) == 4, "sizeof(long double) == 4"); +_Static_assert(_Alignof(long double) == 1, "_Alignof(long double) == 1"); +_Static_assert(__alignof(long double) == 1, "__alignof(long double) == 1"); diff --git a/clang/test/Sema/riscv-rvv-vector-trig-ops.c b/clang/test/Sema/riscv-rvv-vector-trig-ops.c index 006c136f80332..0aed1b2a09986 100644 --- a/clang/test/Sema/riscv-rvv-vector-trig-ops.c +++ b/clang/test/Sema/riscv-rvv-vector-trig-ops.c @@ -1,67 +1,67 @@ -// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \ -// RUN: -target-feature +v -target-feature +zfh -target-feature +zvfh \ -// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify -// REQUIRES: riscv-registered-target - -#include - -vfloat32mf2_t test_asin_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_asin(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} - } - - vfloat32mf2_t test_acos_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_acos(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} - } - - vfloat32mf2_t test_atan_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_atan(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} - } - -vfloat32mf2_t test_atan2_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_atan2(v, v); - // expected-error@-1 {{1st argument must be a floating point type}} -} - -vfloat32mf2_t test_sin_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_sin(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -vfloat32mf2_t test_cos_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_cos(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -vfloat32mf2_t test_tan_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_tan(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} -} - -vfloat32mf2_t test_sinh_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_sinh(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} - } - - vfloat32mf2_t test_cosh_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_cosh(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} - } - - vfloat32mf2_t test_tanh_vv_i8mf8(vfloat32mf2_t v) { - - return __builtin_elementwise_tanh(v); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} - } - +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \ +// RUN: -target-feature +v -target-feature +zfh -target-feature +zvfh \ +// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify +// REQUIRES: riscv-registered-target + +#include + +vfloat32mf2_t test_asin_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_asin(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} + } + + vfloat32mf2_t test_acos_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_acos(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} + } + + vfloat32mf2_t test_atan_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_atan(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} + } + +vfloat32mf2_t test_atan2_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_atan2(v, v); + // expected-error@-1 {{1st argument must be a floating point type}} +} + +vfloat32mf2_t test_sin_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_sin(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +vfloat32mf2_t test_cos_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_cos(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +vfloat32mf2_t test_tan_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_tan(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} +} + +vfloat32mf2_t test_sinh_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_sinh(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} + } + + vfloat32mf2_t test_cosh_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_cosh(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} + } + + vfloat32mf2_t test_tanh_vv_i8mf8(vfloat32mf2_t v) { + + return __builtin_elementwise_tanh(v); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type}} + } + diff --git a/clang/test/Sema/unbounded-array-bounds.c b/clang/test/Sema/unbounded-array-bounds.c index 41d1972cf5955..b22261a3eaeb5 100644 --- a/clang/test/Sema/unbounded-array-bounds.c +++ b/clang/test/Sema/unbounded-array-bounds.c @@ -14,11 +14,11 @@ struct S s[]; // expected-warning {{tentative array definition}} expected-note { void f1(void) { ++s[3].a; ++s[7073650413200313099].b; - // addr16-warning@-1 {{array index 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 160-bit (20-byte) elements (max possible 3276 elements)}} + // addr16-warning@-1 {{array index 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 152-bit (19-byte) elements (max possible 3449 elements)}} // addr32-warning@-2 {{array index 7073650413200313099 refers past the last possible element for an array in 32-bit address space containing 192-bit (24-byte) elements (max possible 178956970 elements)}} // addr64-warning@-3 {{array index 7073650413200313099 refers past the last possible element for an array in 64-bit address space containing 256-bit (32-byte) elements (max possible 576460752303423488 elements)}} ++s[7073650].c; - // addr16-warning@-1 {{array index 7073650 refers past the last possible element for an array in 16-bit address space containing 160-bit (20-byte) elements (max possible 3276 elements)}} + // addr16-warning@-1 {{array index 7073650 refers past the last possible element for an array in 16-bit address space containing 152-bit (19-byte) elements (max possible 3449 elements)}} } long long ll[]; // expected-warning {{tentative array definition}} expected-note {{declared here}} addr16-note {{declared here}} addr32-note {{declared here}} @@ -37,21 +37,21 @@ void f2(void) { void f3(struct S p[]) { // expected-note {{declared here}} addr16-note {{declared here}} ++p[3].a; ++p[7073650413200313099].b; - // addr16-warning@-1 {{array index 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 160-bit (20-byte) elements (max possible 3276 elements)}} + // addr16-warning@-1 {{array index 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 152-bit (19-byte) elements (max possible 3449 elements)}} // addr32-warning@-2 {{array index 7073650413200313099 refers past the last possible element for an array in 32-bit address space containing 192-bit (24-byte) elements (max possible 178956970 elements)}} // addr64-warning@-3 {{array index 7073650413200313099 refers past the last possible element for an array in 64-bit address space containing 256-bit (32-byte) elements (max possible 576460752303423488 elements)}} ++p[7073650].c; - // addr16-warning@-1 {{array index 7073650 refers past the last possible element for an array in 16-bit address space containing 160-bit (20-byte) elements (max possible 3276 elements)}} + // addr16-warning@-1 {{array index 7073650 refers past the last possible element for an array in 16-bit address space containing 152-bit (19-byte) elements (max possible 3449 elements)}} } void f4(struct S *p) { // expected-note {{declared here}} addr16-note {{declared here}} p += 3; p += 7073650413200313099; - // addr16-warning@-1 {{the pointer incremented by 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 160-bit (20-byte) elements (max possible 3276 elements)}} + // addr16-warning@-1 {{the pointer incremented by 7073650413200313099 refers past the last possible element for an array in 16-bit address space containing 152-bit (19-byte) elements (max possible 3449 elements)}} // addr32-warning@-2 {{the pointer incremented by 7073650413200313099 refers past the last possible element for an array in 32-bit address space containing 192-bit (24-byte) elements (max possible 178956970 elements)}} // addr64-warning@-3 {{the pointer incremented by 7073650413200313099 refers past the last possible element for an array in 64-bit address space containing 256-bit (32-byte) elements (max possible 576460752303423488 elements)}} p += 7073650; - // addr16-warning@-1 {{the pointer incremented by 7073650 refers past the last possible element for an array in 16-bit address space containing 160-bit (20-byte) elements (max possible 3276 elements)}} + // addr16-warning@-1 {{the pointer incremented by 7073650 refers past the last possible element for an array in 16-bit address space containing 152-bit (19-byte) elements (max possible 3449 elements)}} } struct BQ { @@ -63,7 +63,7 @@ struct BQ bq[]; // expected-warning {{tentative array definition}} addr16-note { void f5(void) { ++bq[0].bigblock[0].a; ++bq[1].bigblock[0].a; - // addr16-warning@-1 {{array index 1 refers past the last possible element for an array in 16-bit address space containing 524160-bit (65520-byte) elements (max possible 1 element)}} + // addr16-warning@-1 {{array index 1 refers past the last possible element for an array in 16-bit address space containing 497952-bit (62244-byte) elements (max possible 1 element)}} } void f6(void) { diff --git a/clang/test/SemaCUDA/fp16-arg-return.cu b/clang/test/SemaCUDA/fp16-arg-return.cu index 9347491caa97b..b02c666231849 100644 --- a/clang/test/SemaCUDA/fp16-arg-return.cu +++ b/clang/test/SemaCUDA/fp16-arg-return.cu @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -o - -triple amdgcn-amd-amdhsa -fcuda-is-device -fsyntax-only -verify %s // RUN: %clang_cc1 -o - -triple spirv64-amd-amdhsa -fcuda-is-device -fsyntax-only -verify %s +// RUN: %clang_cc1 -o - -triple x86_64-unknown-gnu-linux -fsyntax-only -verify -xhip %s // expected-no-diagnostics diff --git a/clang/test/SemaCXX/GH95854.cpp b/clang/test/SemaCXX/GH95854.cpp new file mode 100644 index 0000000000000..aa470c6ac8e5b --- /dev/null +++ b/clang/test/SemaCXX/GH95854.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s + +struct A { + union { + int n = 0; + int m; + }; +}; +const A a; + +struct B { + union { + struct { + int n = 5; + int m; + }; + }; +}; +const B b; // expected-error {{default initialization of an object of const type 'const B' without a user-provided default constructor}} + +struct S { + int i; + int j; +}; + +struct T { + T() = default; +}; + +struct C { + union { + S s; + }; +}; + +struct D { + union { + T s; + }; +}; + +const C c; // expected-error {{default initialization of an object of const type 'const C' without a user-provided default constructor}} +const D d; // expected-error {{default initialization of an object of const type 'const D' without a user-provided default constructor}} + +struct E { + union { + int n; + int m=0; + }; +}; +const E e; diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp index d04bbb32433fb..1c5c79777c71c 100644 --- a/clang/test/SemaCXX/attr-lifetimebound.cpp +++ b/clang/test/SemaCXX/attr-lifetimebound.cpp @@ -330,8 +330,8 @@ struct StatusOr { }; void test(StatusOr foo1, StatusOr foo2) { - foo1 = Foo(); // expected-warning {{object backing the pointer foo1 will be destroyed at the end}} - // No warning on non-gsl annotated types. - foo2 = NonAnnotatedFoo(); + foo1 = Foo(); // expected-warning {{object backing foo1 will be destroyed at the end}} + // This warning is triggered by the lifetimebound annotation, regardless of whether the class type is annotated with GSL. + foo2 = NonAnnotatedFoo(); // expected-warning {{object backing foo2 will be destroyed at the end}} } } // namespace GH106372 diff --git a/clang/test/SemaCXX/attr-target-clones-riscv.cpp b/clang/test/SemaCXX/attr-target-clones-riscv.cpp index 4425dd2108a6e..102bb4b9b3d2b 100644 --- a/clang/test/SemaCXX/attr-target-clones-riscv.cpp +++ b/clang/test/SemaCXX/attr-target-clones-riscv.cpp @@ -33,6 +33,9 @@ void __attribute__((target_clones("default;priority=2", "arch=+c"))) UnsupportDe // expected-warning@+1 {{unsupported 'priority=2;default' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} void __attribute__((target_clones("priority=2;default", "arch=+c"))) UnsupportDefaultPriority2() {} +// expected-warning@+1 {{unsupported 'arch=+c;priority=-1' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} +void __attribute__((target_clones("default", "arch=+c;priority=-1"))) UnsupportNegativePriority() {} + // expected-warning@+1 {{unsupported 'arch=+c,zbb' in the 'target_clones' attribute string; 'target_clones' attribute ignored}} void __attribute__((target_clones("default", "arch=+c,zbb"))) WithoutAddSign() {} diff --git a/clang/test/SemaCXX/attr-target-version-riscv.cpp b/clang/test/SemaCXX/attr-target-version-riscv.cpp index 785a3c6abafe8..f7e6811533ac3 100644 --- a/clang/test/SemaCXX/attr-target-version-riscv.cpp +++ b/clang/test/SemaCXX/attr-target-version-riscv.cpp @@ -111,3 +111,9 @@ __attribute__((target_version("default"))) int invalidVerson4(void) { return 2; __attribute__((target_version("priority=1"))) int prioriyWithoutArch(void) { return 2; } // expected-error@+1 {{redefinition of 'prioriyWithoutArch'}} __attribute__((target_version("default"))) int prioriyWithoutArch(void) { return 2; } + +// expected-warning@+2 {{unsupported '-1' in the 'target_version' attribute string; 'target_version' attribute ignored}} +// expected-note@+1 {{previous definition is here}} +__attribute__((target_version("arch=+c;priority=-1"))) int UnsupportNegativePriority(void) { return 2; } +// expected-error@+1 {{redefinition of 'UnsupportNegativePriority'}} +__attribute__((target_version("default"))) int UnsupportNegativePriority(void) { return 2; } diff --git a/clang/test/SemaCXX/c99-variable-length-array.cpp b/clang/test/SemaCXX/c99-variable-length-array.cpp index 82ddb0fd2e233..d9eb65e4355c3 100644 --- a/clang/test/SemaCXX/c99-variable-length-array.cpp +++ b/clang/test/SemaCXX/c99-variable-length-array.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wvla-extension %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wvla-extension %s -fexperimental-new-constant-interpreter struct NonPOD { NonPOD(); }; diff --git a/clang/test/SemaCXX/lambda-pack-expansion.cpp b/clang/test/SemaCXX/lambda-pack-expansion.cpp index 0e60ecd875660..b07126a76d852 100644 --- a/clang/test/SemaCXX/lambda-pack-expansion.cpp +++ b/clang/test/SemaCXX/lambda-pack-expansion.cpp @@ -94,3 +94,47 @@ template void g2(Ts... p1s) { void f1() { g(); } } // namespace GH61460 + +namespace GH112352 { + +template +constexpr bool foo = false; + +template +constexpr bool bar = false; + +template class> +constexpr bool baz = false; + +struct S { + template void foldExpr1() { + (void)[] { + ([] { + Is; + // Propagate up the flag ContainsUnexpandedParameterPack from VarDecl. + S var(foo); + foo; + bar; + int a = Values; + } && + ...); + }; + } + + template class... TTPs> void foldExpr2() { + (void)[] { + ([] { + Is; + baz; + TTPs D; + } && ...); + }; + } +}; + +void use() { + S().foldExpr1(); + S().foldExpr2(); +} + +} // namespace GH112352 diff --git a/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl index b60fba62bdb00..764b9e843f7f1 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl @@ -1,119 +1,119 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \ -// RUN: -fsyntax-only -verify %s - -__attribute__((availability(shadermodel, introduced = 6.5))) -float fx(float); // #fx - -__attribute__((availability(shadermodel, introduced = 6.6))) -half fx(half); // #fx_half - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) -float fy(float); // #fy - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) -float fz(float); // #fz - -float also_alive(float f) { - // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #also_alive_fx_call - // expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #also_alive_fy_call - // expected-error@#also_alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #also_alive_fz_call - return 0; -} - -float alive(float f) { - // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #alive_fx_call - // expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #alive_fy_call - // expected-error@#alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #alive_fz_call - - return also_alive(f); -} - -float also_dead(float f) { - // unreachable code - no errors expected - float A = fx(f); - float B = fy(f); - float C = fz(f); - return 0; -} - -float dead(float f) { - // unreachable code - no errors expected - float A = fx(f); - float B = fy(f); - float C = fz(f); - - return also_dead(f); -} - -template -T aliveTemp(T f) { - // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #aliveTemp_fx_call - // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #aliveTemp_fy_call - // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #aliveTemp_fz_call - return 0; -} - -template T aliveTemp2(T f) { - // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} - // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} - // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - return fx(f); // #aliveTemp2_fx_call -} - -half test(half x) { - return aliveTemp2(x); -} - -float test(float x) { - return aliveTemp2(x); -} - -class MyClass -{ - float F; - float makeF() { - // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(F); // #MyClass_makeF_fx_call - // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(F); // #MyClass_makeF_fy_call - // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(F); // #MyClass_makeF_fz_call - return 0; - } -}; - -[numthreads(4,1,1)] -float main() { - float f = 3; - MyClass C = { 1.0f }; - float a = alive(f); - float b = aliveTemp(f); // #aliveTemp_inst - float c = C.makeF(); - float d = test((float)1.0); - float e = test((half)1.0); - return a * b * c; -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \ +// RUN: -fsyntax-only -verify %s + +__attribute__((availability(shadermodel, introduced = 6.5))) +float fx(float); // #fx + +__attribute__((availability(shadermodel, introduced = 6.6))) +half fx(half); // #fx_half + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) +float fy(float); // #fy + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) +float fz(float); // #fz + +float also_alive(float f) { + // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #also_alive_fx_call + // expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #also_alive_fy_call + // expected-error@#also_alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #also_alive_fz_call + return 0; +} + +float alive(float f) { + // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #alive_fx_call + // expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #alive_fy_call + // expected-error@#alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #alive_fz_call + + return also_alive(f); +} + +float also_dead(float f) { + // unreachable code - no errors expected + float A = fx(f); + float B = fy(f); + float C = fz(f); + return 0; +} + +float dead(float f) { + // unreachable code - no errors expected + float A = fx(f); + float B = fy(f); + float C = fz(f); + + return also_dead(f); +} + +template +T aliveTemp(T f) { + // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #aliveTemp_fx_call + // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #aliveTemp_fy_call + // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #aliveTemp_fz_call + return 0; +} + +template T aliveTemp2(T f) { + // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} + // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} + // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + return fx(f); // #aliveTemp2_fx_call +} + +half test(half x) { + return aliveTemp2(x); +} + +float test(float x) { + return aliveTemp2(x); +} + +class MyClass +{ + float F; + float makeF() { + // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(F); // #MyClass_makeF_fx_call + // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(F); // #MyClass_makeF_fy_call + // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(F); // #MyClass_makeF_fz_call + return 0; + } +}; + +[numthreads(4,1,1)] +float main() { + float f = 3; + MyClass C = { 1.0f }; + float a = alive(f); + float b = aliveTemp(f); // #aliveTemp_inst + float c = C.makeF(); + float d = test((float)1.0); + float e = test((half)1.0); + return a * b * c; +} diff --git a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl index 35b7c384f26cd..6bfc8577670cc 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl @@ -1,180 +1,180 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ -// RUN: -fsyntax-only -verify %s - -__attribute__((availability(shadermodel, introduced = 6.5))) -float fx(float); // #fx - -__attribute__((availability(shadermodel, introduced = 6.6))) -half fx(half); // #fx_half - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) -float fy(float); // #fy - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) -float fz(float); // #fz - -float also_alive(float f) { - // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #also_alive_fx_call - - // expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #also_alive_fy_call - - // expected-error@#also_alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #also_alive_fz_call - - return 0; -} - -float alive(float f) { - // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #alive_fx_call - - // expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #alive_fy_call - - // expected-error@#alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #alive_fz_call - - return also_alive(f); -} - -float also_dead(float f) { - // unreachable code - no errors expected - float A = fx(f); - float B = fy(f); - float C = fz(f); - return 0; -} - -float dead(float f) { - // unreachable code - no errors expected - float A = fx(f); - float B = fy(f); - float C = fz(f); - return also_dead(f); -} - -template -T aliveTemp(T f) { - // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #aliveTemp_fx_call - // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #aliveTemp_fy_call - // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #aliveTemp_fz_call - return 0; -} - -template T aliveTemp2(T f) { - // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} - // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} - // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - return fx(f); // #aliveTemp2_fx_call -} - -half test(half x) { - return aliveTemp2(x); -} - -float test(float x) { - return aliveTemp2(x); -} - -class MyClass -{ - float F; - float makeF() { - // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(F); // #MyClass_makeF_fx_call - // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(F); // #MyClass_makeF_fy_call - // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(F); // #MyClass_makeF_fz_call - return 0; - } -}; - -// Exported function without body, not used -export void exportedFunctionUnused(float f); - -// Exported function with body, without export, not used -void exportedFunctionUnused(float f) { - // expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #exportedFunctionUnused_fx_call - - // API with shader-stage-specific availability in unused exported library function - // - no errors expected because the actual shader stage this function - // will be used in not known at this time - float B = fy(f); - float C = fz(f); -} - -// Exported function with body - called from main() which is a compute shader entry point -export void exportedFunctionUsed(float f) { - // expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #exportedFunctionUsed_fx_call - - // expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #exportedFunctionUsed_fy_call - - // expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #exportedFunctionUsed_fz_call -} - -namespace A { - namespace B { - export { - void exportedFunctionInNS(float x) { - // expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(x); // #exportedFunctionInNS_fx_call - - // API with shader-stage-specific availability in exported library function - // - no errors expected because the actual shader stage this function - // will be used in not known at this time - float B = fy(x); - float C = fz(x); - } - } - } -} - -// Shader entry point without body -[shader("compute")] -[numthreads(4,1,1)] -float main(); - -// Shader entry point with body -[shader("compute")] -[numthreads(4,1,1)] -float main() { - float f = 3; - MyClass C = { 1.0f }; - float a = alive(f); - float b = aliveTemp(f); // #aliveTemp_inst - float c = C.makeF(); - float d = test((float)1.0); - float e = test((half)1.0); - exportedFunctionUsed(1.0f); - return a * b * c; -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ +// RUN: -fsyntax-only -verify %s + +__attribute__((availability(shadermodel, introduced = 6.5))) +float fx(float); // #fx + +__attribute__((availability(shadermodel, introduced = 6.6))) +half fx(half); // #fx_half + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) +float fy(float); // #fy + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) +float fz(float); // #fz + +float also_alive(float f) { + // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #also_alive_fx_call + + // expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #also_alive_fy_call + + // expected-error@#also_alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #also_alive_fz_call + + return 0; +} + +float alive(float f) { + // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #alive_fx_call + + // expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #alive_fy_call + + // expected-error@#alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #alive_fz_call + + return also_alive(f); +} + +float also_dead(float f) { + // unreachable code - no errors expected + float A = fx(f); + float B = fy(f); + float C = fz(f); + return 0; +} + +float dead(float f) { + // unreachable code - no errors expected + float A = fx(f); + float B = fy(f); + float C = fz(f); + return also_dead(f); +} + +template +T aliveTemp(T f) { + // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #aliveTemp_fx_call + // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #aliveTemp_fy_call + // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #aliveTemp_fz_call + return 0; +} + +template T aliveTemp2(T f) { + // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} + // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} + // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + return fx(f); // #aliveTemp2_fx_call +} + +half test(half x) { + return aliveTemp2(x); +} + +float test(float x) { + return aliveTemp2(x); +} + +class MyClass +{ + float F; + float makeF() { + // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(F); // #MyClass_makeF_fx_call + // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(F); // #MyClass_makeF_fy_call + // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(F); // #MyClass_makeF_fz_call + return 0; + } +}; + +// Exported function without body, not used +export void exportedFunctionUnused(float f); + +// Exported function with body, without export, not used +void exportedFunctionUnused(float f) { + // expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUnused_fx_call + + // API with shader-stage-specific availability in unused exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(f); + float C = fz(f); +} + +// Exported function with body - called from main() which is a compute shader entry point +export void exportedFunctionUsed(float f) { + // expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUsed_fx_call + + // expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #exportedFunctionUsed_fy_call + + // expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #exportedFunctionUsed_fz_call +} + +namespace A { + namespace B { + export { + void exportedFunctionInNS(float x) { + // expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(x); // #exportedFunctionInNS_fx_call + + // API with shader-stage-specific availability in exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(x); + float C = fz(x); + } + } + } +} + +// Shader entry point without body +[shader("compute")] +[numthreads(4,1,1)] +float main(); + +// Shader entry point with body +[shader("compute")] +[numthreads(4,1,1)] +float main() { + float f = 3; + MyClass C = { 1.0f }; + float a = alive(f); + float b = aliveTemp(f); // #aliveTemp_inst + float c = C.makeF(); + float d = test((float)1.0); + float e = test((half)1.0); + exportedFunctionUsed(1.0f); + return a * b * c; +} diff --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl index 4068798383930..65836c55821d7 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl @@ -1,119 +1,119 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \ -// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s - -__attribute__((availability(shadermodel, introduced = 6.5))) -float fx(float); // #fx - -__attribute__((availability(shadermodel, introduced = 6.6))) -half fx(half); // #fx_half - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) -float fy(float); // #fy - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) -float fz(float); // #fz - -float also_alive(float f) { - // expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #also_alive_fx_call - // expected-warning@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #also_alive_fy_call - // expected-warning@#also_alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #also_alive_fz_call - return 0; -} - -float alive(float f) { - // expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #alive_fx_call - // expected-warning@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #alive_fy_call - // expected-warning@#alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #alive_fz_call - - return also_alive(f); -} - -float also_dead(float f) { - // unreachable code - no errors expected - float A = fx(f); - float B = fy(f); - float C = fz(f); - return 0; -} - -float dead(float f) { - // unreachable code - no errors expected - float A = fx(f); - float B = fy(f); - float C = fz(f); - - return also_dead(f); -} - -template -T aliveTemp(T f) { - // expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #aliveTemp_fx_call - // expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #aliveTemp_fy_call - // expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #aliveTemp_fz_call - return 0; -} - -template T aliveTemp2(T f) { - // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} - // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} - // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - return fx(f); // #aliveTemp2_fx_call -} - -half test(half x) { - return aliveTemp2(x); -} - -float test(float x) { - return aliveTemp2(x); -} - -class MyClass -{ - float F; - float makeF() { - // expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(F); // #MyClass_makeF_fx_call - // expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(F); // #MyClass_makeF_fy_call - // expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(F); // #MyClass_makeF_fz_call - return 0; - } -}; - -[numthreads(4,1,1)] -float main() { - float f = 3; - MyClass C = { 1.0f }; - float a = alive(f); - float b = aliveTemp(f); // #aliveTemp_inst - float c = C.makeF(); - float d = test((float)1.0); - float e = test((half)1.0); - return a * b * c; -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \ +// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s + +__attribute__((availability(shadermodel, introduced = 6.5))) +float fx(float); // #fx + +__attribute__((availability(shadermodel, introduced = 6.6))) +half fx(half); // #fx_half + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) +float fy(float); // #fy + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) +float fz(float); // #fz + +float also_alive(float f) { + // expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #also_alive_fx_call + // expected-warning@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #also_alive_fy_call + // expected-warning@#also_alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #also_alive_fz_call + return 0; +} + +float alive(float f) { + // expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #alive_fx_call + // expected-warning@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #alive_fy_call + // expected-warning@#alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #alive_fz_call + + return also_alive(f); +} + +float also_dead(float f) { + // unreachable code - no errors expected + float A = fx(f); + float B = fy(f); + float C = fz(f); + return 0; +} + +float dead(float f) { + // unreachable code - no errors expected + float A = fx(f); + float B = fy(f); + float C = fz(f); + + return also_dead(f); +} + +template +T aliveTemp(T f) { + // expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #aliveTemp_fx_call + // expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #aliveTemp_fy_call + // expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #aliveTemp_fz_call + return 0; +} + +template T aliveTemp2(T f) { + // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} + // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} + // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + return fx(f); // #aliveTemp2_fx_call +} + +half test(half x) { + return aliveTemp2(x); +} + +float test(float x) { + return aliveTemp2(x); +} + +class MyClass +{ + float F; + float makeF() { + // expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(F); // #MyClass_makeF_fx_call + // expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(F); // #MyClass_makeF_fy_call + // expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(F); // #MyClass_makeF_fz_call + return 0; + } +}; + +[numthreads(4,1,1)] +float main() { + float f = 3; + MyClass C = { 1.0f }; + float a = alive(f); + float b = aliveTemp(f); // #aliveTemp_inst + float c = C.makeF(); + float d = test((float)1.0); + float e = test((half)1.0); + return a * b * c; +} diff --git a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl index a23e91a546b16..4c9783138f670 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl @@ -1,162 +1,162 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ -// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s - -__attribute__((availability(shadermodel, introduced = 6.5))) -float fx(float); // #fx - -__attribute__((availability(shadermodel, introduced = 6.6))) -half fx(half); // #fx_half - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) -float fy(float); // #fy - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) -float fz(float); // #fz - -float also_alive(float f) { - // expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #also_alive_fx_call - - // expected-warning@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #also_alive_fy_call - - // expected-warning@#also_alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #also_alive_fz_call - - return 0; -} - -float alive(float f) { - // expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #alive_fx_call - - // expected-warning@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #alive_fy_call - - // expected-warning@#alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #alive_fz_call - - return also_alive(f); -} - -float also_dead(float f) { - // unreachable code - no errors expected - float A = fx(f); - float B = fy(f); - float C = fz(f); - return 0; -} - -float dead(float f) { - // unreachable code - no errors expected - float A = fx(f); - float B = fy(f); - float C = fz(f); - return also_dead(f); -} - -template -T aliveTemp(T f) { - // expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #aliveTemp_fx_call - // expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #aliveTemp_fy_call - // expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #aliveTemp_fz_call - return 0; -} - -template T aliveTemp2(T f) { - // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} - // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} - // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - return fx(f); // #aliveTemp2_fx_call -} - -half test(half x) { - return aliveTemp2(x); -} - -float test(float x) { - return aliveTemp2(x); -} - -class MyClass -{ - float F; - float makeF() { - // expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(F); // #MyClass_makeF_fx_call - // expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(F); // #MyClass_makeF_fy_call - // expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(F); // #MyClass_makeF_fz_call - return 0; - } -}; - -// Exported function without body, not used -export void exportedFunctionUnused(float f); - -// Exported function with body, without export, not used -void exportedFunctionUnused(float f) { - // expected-warning@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #exportedFunctionUnused_fx_call - - // API with shader-stage-specific availability in unused exported library function - // - no errors expected because the actual shader stage this function - // will be used in not known at this time - float B = fy(f); - float C = fz(f); -} - -// Exported function with body - called from main() which is a compute shader entry point -export void exportedFunctionUsed(float f) { - // expected-warning@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #exportedFunctionUsed_fx_call - - // expected-warning@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #exportedFunctionUsed_fy_call - - // expected-warning@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #exportedFunctionUsed_fz_call -} - -// Shader entry point without body -[shader("compute")] -[numthreads(4,1,1)] -float main(); - -// Shader entry point with body -[shader("compute")] -[numthreads(4,1,1)] -float main() { - float f = 3; - MyClass C = { 1.0f }; - float a = alive(f); - float b = aliveTemp(f); // #aliveTemp_inst - float c = C.makeF(); - float d = test((float)1.0); - float e = test((half)1.0); - exportedFunctionUsed(1.0f); - return a * b * c; -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ +// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s + +__attribute__((availability(shadermodel, introduced = 6.5))) +float fx(float); // #fx + +__attribute__((availability(shadermodel, introduced = 6.6))) +half fx(half); // #fx_half + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) +float fy(float); // #fy + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) +float fz(float); // #fz + +float also_alive(float f) { + // expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #also_alive_fx_call + + // expected-warning@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #also_alive_fy_call + + // expected-warning@#also_alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #also_alive_fz_call + + return 0; +} + +float alive(float f) { + // expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #alive_fx_call + + // expected-warning@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #alive_fy_call + + // expected-warning@#alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #alive_fz_call + + return also_alive(f); +} + +float also_dead(float f) { + // unreachable code - no errors expected + float A = fx(f); + float B = fy(f); + float C = fz(f); + return 0; +} + +float dead(float f) { + // unreachable code - no errors expected + float A = fx(f); + float B = fy(f); + float C = fz(f); + return also_dead(f); +} + +template +T aliveTemp(T f) { + // expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #aliveTemp_fx_call + // expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #aliveTemp_fy_call + // expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #aliveTemp_fz_call + return 0; +} + +template T aliveTemp2(T f) { + // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} + // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} + // expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + return fx(f); // #aliveTemp2_fx_call +} + +half test(half x) { + return aliveTemp2(x); +} + +float test(float x) { + return aliveTemp2(x); +} + +class MyClass +{ + float F; + float makeF() { + // expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(F); // #MyClass_makeF_fx_call + // expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(F); // #MyClass_makeF_fy_call + // expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(F); // #MyClass_makeF_fz_call + return 0; + } +}; + +// Exported function without body, not used +export void exportedFunctionUnused(float f); + +// Exported function with body, without export, not used +void exportedFunctionUnused(float f) { + // expected-warning@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUnused_fx_call + + // API with shader-stage-specific availability in unused exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(f); + float C = fz(f); +} + +// Exported function with body - called from main() which is a compute shader entry point +export void exportedFunctionUsed(float f) { + // expected-warning@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUsed_fx_call + + // expected-warning@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #exportedFunctionUsed_fy_call + + // expected-warning@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #exportedFunctionUsed_fz_call +} + +// Shader entry point without body +[shader("compute")] +[numthreads(4,1,1)] +float main(); + +// Shader entry point with body +[shader("compute")] +[numthreads(4,1,1)] +float main() { + float f = 3; + MyClass C = { 1.0f }; + float a = alive(f); + float b = aliveTemp(f); // #aliveTemp_inst + float c = C.makeF(); + float d = test((float)1.0); + float e = test((half)1.0); + exportedFunctionUsed(1.0f); + return a * b * c; +} diff --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl index a8783c10cbabc..b67e10c9a9017 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl @@ -1,129 +1,129 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \ -// RUN: -fhlsl-strict-availability -fsyntax-only -verify %s - -__attribute__((availability(shadermodel, introduced = 6.5))) -float fx(float); // #fx - -__attribute__((availability(shadermodel, introduced = 6.6))) -half fx(half); // #fx_half - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) -float fy(float); // #fy - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) -float fz(float); // #fz - -float also_alive(float f) { - // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #also_alive_fx_call - // expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #also_alive_fy_call - // expected-error@#also_alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #also_alive_fz_call - return 0; -} - -float alive(float f) { - // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #alive_fx_call - // expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #alive_fy_call - // expected-error@#alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #alive_fz_call - - return also_alive(f); -} - -float also_dead(float f) { - // expected-error@#also_dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #also_dead_fx_call - // expected-error@#also_dead_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #also_dead_fy_call - // expected-error@#also_dead_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #also_dead_fz_call - return 0; -} - -float dead(float f) { - // expected-error@#dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #dead_fx_call - // expected-error@#dead_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #dead_fy_call - // expected-error@#dead_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #dead_fz_call - - return also_dead(f); -} - -template -T aliveTemp(T f) { - // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp' requested here}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #aliveTemp_fx_call - // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #aliveTemp_fy_call - // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #aliveTemp_fz_call - return 0; -} - -template T aliveTemp2(T f) { - // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} - // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} - // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - return fx(f); // #aliveTemp2_fx_call -} - -half test(half x) { - return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2' requested here}} -} - -float test(float x) { - return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2' requested here}} -} - -class MyClass -{ - float F; - float makeF() { - // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(F); // #MyClass_makeF_fx_call - // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(F); // #MyClass_makeF_fy_call - // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(F); // #MyClass_makeF_fz_call - } -}; - -[numthreads(4,1,1)] -float main() { - float f = 3; - MyClass C = { 1.0f }; - float a = alive(f); - float b = aliveTemp(f); // #aliveTemp_inst - float c = C.makeF(); - float d = test((float)1.0); - float e = test((half)1.0); - return a * b * c; +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \ +// RUN: -fhlsl-strict-availability -fsyntax-only -verify %s + +__attribute__((availability(shadermodel, introduced = 6.5))) +float fx(float); // #fx + +__attribute__((availability(shadermodel, introduced = 6.6))) +half fx(half); // #fx_half + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) +float fy(float); // #fy + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) +float fz(float); // #fz + +float also_alive(float f) { + // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #also_alive_fx_call + // expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #also_alive_fy_call + // expected-error@#also_alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #also_alive_fz_call + return 0; +} + +float alive(float f) { + // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #alive_fx_call + // expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #alive_fy_call + // expected-error@#alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #alive_fz_call + + return also_alive(f); +} + +float also_dead(float f) { + // expected-error@#also_dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #also_dead_fx_call + // expected-error@#also_dead_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #also_dead_fy_call + // expected-error@#also_dead_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #also_dead_fz_call + return 0; +} + +float dead(float f) { + // expected-error@#dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #dead_fx_call + // expected-error@#dead_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #dead_fy_call + // expected-error@#dead_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #dead_fz_call + + return also_dead(f); +} + +template +T aliveTemp(T f) { + // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp' requested here}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #aliveTemp_fx_call + // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #aliveTemp_fy_call + // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #aliveTemp_fz_call + return 0; +} + +template T aliveTemp2(T f) { + // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} + // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} + // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + return fx(f); // #aliveTemp2_fx_call +} + +half test(half x) { + return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2' requested here}} +} + +float test(float x) { + return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2' requested here}} +} + +class MyClass +{ + float F; + float makeF() { + // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(F); // #MyClass_makeF_fx_call + // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(F); // #MyClass_makeF_fy_call + // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(F); // #MyClass_makeF_fz_call + } +}; + +[numthreads(4,1,1)] +float main() { + float f = 3; + MyClass C = { 1.0f }; + float a = alive(f); + float b = aliveTemp(f); // #aliveTemp_inst + float c = C.makeF(); + float d = test((float)1.0); + float e = test((half)1.0); + return a * b * c; } \ No newline at end of file diff --git a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl index 0fffbc96dac19..c7be5afbc2d22 100644 --- a/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl @@ -1,192 +1,192 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ -// RUN: -fhlsl-strict-availability -fsyntax-only -verify %s - -__attribute__((availability(shadermodel, introduced = 6.5))) -float fx(float); // #fx - -__attribute__((availability(shadermodel, introduced = 6.6))) -half fx(half); // #fx_half - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) -float fy(float); // #fy - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) -float fz(float); // #fz - -// FIXME: all diagnostics marked as FUTURE will come alive when HLSL default -// diagnostic mode is implemented in a future PR which will verify calls in -// all functions that are reachable from the shader library entry points - -float also_alive(float f) { - // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #also_alive_fx_call - - // expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #also_alive_fy_call - - // expected-error@#also_alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #also_alive_fz_call - - return 0; -} - -float alive(float f) { - // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #alive_fx_call - - // expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #alive_fy_call - - // expected-error@#alive_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #alive_fz_call - - return also_alive(f); -} - -float also_dead(float f) { - // expected-error@#also_dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #also_dead_fx_call - - // Call to environment-specific function from an unreachable function - // in a shader library - no diagnostic expected. - float B = fy(f); // #also_dead_fy_call - - // Call to environment-specific function from an unreachable function - // in a shader library - no diagnostic expected. - float C = fz(f); // #also_dead_fz_call - return 0; -} - -float dead(float f) { - // expected-error@#dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #dead_fx_call - - // Call to environment-specific function from an unreachable function - // in a shader library - no diagnostic expected. - float B = fy(f); // #dead_fy_call - - // Call to environment-specific function from an unreachable function - // in a shader library - no diagnostic expected. - float C = fz(f); // #dead_fz_call - - return also_dead(f); -} - -template -T aliveTemp(T f) { - // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp' requested here}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #aliveTemp_fx_call - // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #aliveTemp_fy_call - // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #aliveTemp_fz_call - return 0; -} - -template T aliveTemp2(T f) { - // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} - // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} - // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - return fx(f); // #aliveTemp2_fx_call -} - -half test(half x) { - return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2' requested here}} -} - -float test(float x) { - return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2' requested here}} -} - -class MyClass -{ - float F; - float makeF() { - // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(F); // #MyClass_makeF_fx_call - // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(F); // #MyClass_makeF_fy_call - // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(F); // #MyClass_makeF_fz_call - } -}; - -// Exported function without body, not used -export void exportedFunctionUnused(float f); - -// Exported function with body, without export, not used -void exportedFunctionUnused(float f) { - // expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #exportedFunctionUnused_fx_call - - // API with shader-stage-specific availability in unused exported library function - // - no errors expected because the actual shader stage this function - // will be used in not known at this time - float B = fy(f); - float C = fz(f); -} - -// Exported function with body - called from main() which is a compute shader entry point -export void exportedFunctionUsed(float f) { - // expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #exportedFunctionUsed_fx_call - - // expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #exportedFunctionUsed_fy_call - - // expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} - float C = fz(f); // #exportedFunctionUsed_fz_call -} - -namespace A { - namespace B { - export { - void exportedFunctionInNS(float x) { - // expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(x); // #exportedFunctionInNS_fx_call - - // API with shader-stage-specific availability in exported library function - // - no errors expected because the actual shader stage this function - // will be used in not known at this time - float B = fy(x); - float C = fz(x); - } - } - } -} - -[shader("compute")] -[numthreads(4,1,1)] -float main() { - float f = 3; - MyClass C = { 1.0f }; - float a = alive(f);float b = aliveTemp(f); // #aliveTemp_inst - float c = C.makeF(); - float d = test((float)1.0); - float e = test((half)1.0); - exportedFunctionUsed(1.0f); - return a * b * c; -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ +// RUN: -fhlsl-strict-availability -fsyntax-only -verify %s + +__attribute__((availability(shadermodel, introduced = 6.5))) +float fx(float); // #fx + +__attribute__((availability(shadermodel, introduced = 6.6))) +half fx(half); // #fx_half + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) +float fy(float); // #fy + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh))) +float fz(float); // #fz + +// FIXME: all diagnostics marked as FUTURE will come alive when HLSL default +// diagnostic mode is implemented in a future PR which will verify calls in +// all functions that are reachable from the shader library entry points + +float also_alive(float f) { + // expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #also_alive_fx_call + + // expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #also_alive_fy_call + + // expected-error@#also_alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #also_alive_fz_call + + return 0; +} + +float alive(float f) { + // expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #alive_fx_call + + // expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #alive_fy_call + + // expected-error@#alive_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #alive_fz_call + + return also_alive(f); +} + +float also_dead(float f) { + // expected-error@#also_dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #also_dead_fx_call + + // Call to environment-specific function from an unreachable function + // in a shader library - no diagnostic expected. + float B = fy(f); // #also_dead_fy_call + + // Call to environment-specific function from an unreachable function + // in a shader library - no diagnostic expected. + float C = fz(f); // #also_dead_fz_call + return 0; +} + +float dead(float f) { + // expected-error@#dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #dead_fx_call + + // Call to environment-specific function from an unreachable function + // in a shader library - no diagnostic expected. + float B = fy(f); // #dead_fy_call + + // Call to environment-specific function from an unreachable function + // in a shader library - no diagnostic expected. + float C = fz(f); // #dead_fz_call + + return also_dead(f); +} + +template +T aliveTemp(T f) { + // expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp' requested here}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #aliveTemp_fx_call + // expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #aliveTemp_fy_call + // expected-error@#aliveTemp_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #aliveTemp_fz_call + return 0; +} + +template T aliveTemp2(T f) { + // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}} + // expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}} + // expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + return fx(f); // #aliveTemp2_fx_call +} + +half test(half x) { + return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2' requested here}} +} + +float test(float x) { + return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2' requested here}} +} + +class MyClass +{ + float F; + float makeF() { + // expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(F); // #MyClass_makeF_fx_call + // expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(F); // #MyClass_makeF_fy_call + // expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(F); // #MyClass_makeF_fz_call + } +}; + +// Exported function without body, not used +export void exportedFunctionUnused(float f); + +// Exported function with body, without export, not used +void exportedFunctionUnused(float f) { + // expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUnused_fx_call + + // API with shader-stage-specific availability in unused exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(f); + float C = fz(f); +} + +// Exported function with body - called from main() which is a compute shader entry point +export void exportedFunctionUsed(float f) { + // expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #exportedFunctionUsed_fx_call + + // expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #exportedFunctionUsed_fy_call + + // expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}} + float C = fz(f); // #exportedFunctionUsed_fz_call +} + +namespace A { + namespace B { + export { + void exportedFunctionInNS(float x) { + // expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(x); // #exportedFunctionInNS_fx_call + + // API with shader-stage-specific availability in exported library function + // - no errors expected because the actual shader stage this function + // will be used in not known at this time + float B = fy(x); + float C = fz(x); + } + } + } +} + +[shader("compute")] +[numthreads(4,1,1)] +float main() { + float f = 3; + MyClass C = { 1.0f }; + float a = alive(f);float b = aliveTemp(f); // #aliveTemp_inst + float c = C.makeF(); + float d = test((float)1.0); + float e = test((half)1.0); + exportedFunctionUsed(1.0f); + return a * b * c; +} diff --git a/clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl b/clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl index bfefc9b116a64..b56ab8fe4526b 100644 --- a/clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl +++ b/clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl @@ -1,57 +1,57 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ -// RUN: -fsyntax-only -verify %s - -__attribute__((availability(shadermodel, introduced = 6.5))) -float fx(float); // #fx - -__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) -__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) -float fy(float); // #fy - -__attribute__((availability(shadermodel, introduced = 5.0, environment = compute))) -float fz(float); // #fz - - -void F(float f) { - // Make sure we only get this error once, even though this function is scanned twice - once - // in compute shader context and once in pixel shader context. - // expected-error@#fx_call {{'fx' is only available on Shader Model 6.5 or newer}} - // expected-note@#fx {{fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} - float A = fx(f); // #fx_call - - // expected-error@#fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} - // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} - float B = fy(f); // #fy_call - - // expected-error@#fz_call {{'fz' is unavailable}} - // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 5.0 in compute environment here, but the deployment target is Shader Model 6.0 pixel environment}} - float X = fz(f); // #fz_call -} - -void deadCode(float f) { - // no diagnostics expected under default diagnostic mode - float A = fx(f); - float B = fy(f); - float X = fz(f); -} - -// Pixel shader -[shader("pixel")] -void mainPixel() { - F(1.0); -} - -// First Compute shader -[shader("compute")] -[numthreads(4,1,1)] -void mainCompute1() { - F(2.0); -} - -// Second compute shader to make sure we do not get duplicate messages if F is called -// from multiple entry points. -[shader("compute")] -[numthreads(4,1,1)] -void mainCompute2() { - F(3.0); -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \ +// RUN: -fsyntax-only -verify %s + +__attribute__((availability(shadermodel, introduced = 6.5))) +float fx(float); // #fx + +__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel))) +__attribute__((availability(shadermodel, introduced = 6.5, environment = compute))) +float fy(float); // #fy + +__attribute__((availability(shadermodel, introduced = 5.0, environment = compute))) +float fz(float); // #fz + + +void F(float f) { + // Make sure we only get this error once, even though this function is scanned twice - once + // in compute shader context and once in pixel shader context. + // expected-error@#fx_call {{'fx' is only available on Shader Model 6.5 or newer}} + // expected-note@#fx {{fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}} + float A = fx(f); // #fx_call + + // expected-error@#fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}} + // expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}} + float B = fy(f); // #fy_call + + // expected-error@#fz_call {{'fz' is unavailable}} + // expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 5.0 in compute environment here, but the deployment target is Shader Model 6.0 pixel environment}} + float X = fz(f); // #fz_call +} + +void deadCode(float f) { + // no diagnostics expected under default diagnostic mode + float A = fx(f); + float B = fy(f); + float X = fz(f); +} + +// Pixel shader +[shader("pixel")] +void mainPixel() { + F(1.0); +} + +// First Compute shader +[shader("compute")] +[numthreads(4,1,1)] +void mainCompute1() { + F(2.0); +} + +// Second compute shader to make sure we do not get duplicate messages if F is called +// from multiple entry points. +[shader("compute")] +[numthreads(4,1,1)] +void mainCompute2() { + F(3.0); +} diff --git a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl index 1ec56542113d9..a472d5519dc51 100644 --- a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl @@ -1,19 +1,19 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify %s - -typedef vector float3; - -StructuredBuffer Buffer; - -// expected-error@+2 {{class template 'StructuredBuffer' requires template arguments}} -// expected-note@*:* {{template declaration from hidden source: template class StructuredBuffer}} -StructuredBuffer BufferErr1; - -// expected-error@+2 {{too few template arguments for class template 'StructuredBuffer'}} -// expected-note@*:* {{template declaration from hidden source: template class StructuredBuffer}} -StructuredBuffer<> BufferErr2; - -[numthreads(1,1,1)] -void main() { - (void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::StructuredBuffer>'}} - // expected-note@* {{implicitly declared private here}} -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify %s + +typedef vector float3; + +StructuredBuffer Buffer; + +// expected-error@+2 {{class template 'StructuredBuffer' requires template arguments}} +// expected-note@*:* {{template declaration from hidden source: template class StructuredBuffer}} +StructuredBuffer BufferErr1; + +// expected-error@+2 {{too few template arguments for class template 'StructuredBuffer'}} +// expected-note@*:* {{template declaration from hidden source: template class StructuredBuffer}} +StructuredBuffer<> BufferErr2; + +[numthreads(1,1,1)] +void main() { + (void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::StructuredBuffer>'}} + // expected-note@* {{implicitly declared private here}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl index 354e7abb8a31e..423f5bac9471f 100644 --- a/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl @@ -1,43 +1,43 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify - -void test_too_few_arg() -{ - return __builtin_hlsl_cross(); - // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} -} - -void test_too_many_arg(float3 p0) -{ - return __builtin_hlsl_cross(p0, p0, p0); - // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} -} - -bool builtin_bool_to_float_type_promotion(bool p1) -{ - return __builtin_hlsl_cross(p1, p1); - // expected-error@-1 {{passing 'bool' to parameter of incompatible type 'float'}} -} - -bool builtin_cross_int_to_float_promotion(int p1) -{ - return __builtin_hlsl_cross(p1, p1); - // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} -} - -bool2 builtin_cross_int2_to_float2_promotion(int2 p1) -{ - return __builtin_hlsl_cross(p1, p1); - // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} -} - -float2 builtin_cross_float2(float2 p1, float2 p2) -{ - return __builtin_hlsl_cross(p1, p2); - // expected-error@-1 {{too many elements in vector operand (expected 3 elements, have 2)}} -} - -float3 builtin_cross_float3_int3(float3 p1, int3 p2) -{ - return __builtin_hlsl_cross(p1, p2); - // expected-error@-1 {{all arguments to '__builtin_hlsl_cross' must have the same type}} -} +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify + +void test_too_few_arg() +{ + return __builtin_hlsl_cross(); + // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} +} + +void test_too_many_arg(float3 p0) +{ + return __builtin_hlsl_cross(p0, p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +bool builtin_bool_to_float_type_promotion(bool p1) +{ + return __builtin_hlsl_cross(p1, p1); + // expected-error@-1 {{passing 'bool' to parameter of incompatible type 'float'}} +} + +bool builtin_cross_int_to_float_promotion(int p1) +{ + return __builtin_hlsl_cross(p1, p1); + // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} +} + +bool2 builtin_cross_int2_to_float2_promotion(int2 p1) +{ + return __builtin_hlsl_cross(p1, p1); + // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} + +float2 builtin_cross_float2(float2 p1, float2 p2) +{ + return __builtin_hlsl_cross(p1, p2); + // expected-error@-1 {{too many elements in vector operand (expected 3 elements, have 2)}} +} + +float3 builtin_cross_float3_int3(float3 p1, int3 p2) +{ + return __builtin_hlsl_cross(p1, p2); + // expected-error@-1 {{all arguments to '__builtin_hlsl_cross' must have the same type}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors2.hlsl b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors2.hlsl index b876a8e84cb3a..bfbd8b28257a3 100644 --- a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors2.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors2.hlsl @@ -1,13 +1,13 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_atan2 -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_fmod -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_pow - -double test_double_builtin(double p0, double p1) { - return TEST_FUNC(p0, p1); - // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} -} - -double2 test_vec_double_builtin(double2 p0, double2 p1) { - return TEST_FUNC(p0, p1); - // expected-error@-1 {{passing 'double2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} -} +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_atan2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_fmod +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_pow + +double test_double_builtin(double p0, double p1) { + return TEST_FUNC(p0, p1); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} + +double2 test_vec_double_builtin(double2 p0, double2 p1) { + return TEST_FUNC(p0, p1); + // expected-error@-1 {{passing 'double2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl index c5e2ac0b502dc..281faada6f5e9 100644 --- a/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/length-errors.hlsl @@ -1,32 +1,32 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected - - -void test_too_few_arg() -{ - return __builtin_hlsl_length(); - // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} -} - -void test_too_many_arg(float2 p0) -{ - return __builtin_hlsl_length(p0, p0); - // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} -} - -bool builtin_bool_to_float_type_promotion(bool p1) -{ - return __builtin_hlsl_length(p1); - // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} -} - -bool builtin_length_int_to_float_promotion(int p1) -{ - return __builtin_hlsl_length(p1); - // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} -} - -bool2 builtin_length_int2_to_float2_promotion(int2 p1) -{ - return __builtin_hlsl_length(p1); - // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} -} +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected + + +void test_too_few_arg() +{ + return __builtin_hlsl_length(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +void test_too_many_arg(float2 p0) +{ + return __builtin_hlsl_length(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +bool builtin_bool_to_float_type_promotion(bool p1) +{ + return __builtin_hlsl_length(p1); + // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} +} + +bool builtin_length_int_to_float_promotion(int p1) +{ + return __builtin_hlsl_length(p1); + // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} +} + +bool2 builtin_length_int2_to_float2_promotion(int2 p1) +{ + return __builtin_hlsl_length(p1); + // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl index 3720dca9b88a1..fc48c9b2589f7 100644 --- a/clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl @@ -1,31 +1,31 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected - -void test_too_few_arg() -{ - return __builtin_hlsl_normalize(); - // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} -} - -void test_too_many_arg(float2 p0) -{ - return __builtin_hlsl_normalize(p0, p0); - // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} -} - -bool builtin_bool_to_float_type_promotion(bool p1) -{ - return __builtin_hlsl_normalize(p1); - // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} -} - -bool builtin_normalize_int_to_float_promotion(int p1) -{ - return __builtin_hlsl_normalize(p1); - // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} -} - -bool2 builtin_normalize_int2_to_float2_promotion(int2 p1) -{ - return __builtin_hlsl_normalize(p1); - // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} -} +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected + +void test_too_few_arg() +{ + return __builtin_hlsl_normalize(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +void test_too_many_arg(float2 p0) +{ + return __builtin_hlsl_normalize(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +bool builtin_bool_to_float_type_promotion(bool p1) +{ + return __builtin_hlsl_normalize(p1); + // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} +} + +bool builtin_normalize_int_to_float_promotion(int p1) +{ + return __builtin_hlsl_normalize(p1); + // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} +} + +bool2 builtin_normalize_int2_to_float2_promotion(int2 p1) +{ + return __builtin_hlsl_normalize(p1); + // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/step-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/step-errors.hlsl index a76c5ff5dbd2b..823585201ca62 100644 --- a/clang/test/SemaHLSL/BuiltIns/step-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/step-errors.hlsl @@ -1,31 +1,31 @@ -// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected - -void test_too_few_arg() -{ - return __builtin_hlsl_step(); - // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} -} - -void test_too_many_arg(float2 p0) -{ - return __builtin_hlsl_step(p0, p0, p0); - // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} -} - -bool builtin_bool_to_float_type_promotion(bool p1) -{ - return __builtin_hlsl_step(p1, p1); - // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} -} - -bool builtin_step_int_to_float_promotion(int p1) -{ - return __builtin_hlsl_step(p1, p1); - // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} -} - -bool2 builtin_step_int2_to_float2_promotion(int2 p1) -{ - return __builtin_hlsl_step(p1, p1); - // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} -} +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected + +void test_too_few_arg() +{ + return __builtin_hlsl_step(); + // expected-error@-1 {{too few arguments to function call, expected 2, have 0}} +} + +void test_too_many_arg(float2 p0) +{ + return __builtin_hlsl_step(p0, p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 2, have 3}} +} + +bool builtin_bool_to_float_type_promotion(bool p1) +{ + return __builtin_hlsl_step(p1, p1); + // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} +} + +bool builtin_step_int_to_float_promotion(int p1) +{ + return __builtin_hlsl_step(p1, p1); + // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} +} + +bool2 builtin_step_int2_to_float2_promotion(int2 p1) +{ + return __builtin_hlsl_step(p1, p1); + // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl index 1223a131af35c..8c0f8d6f271db 100644 --- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl +++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl @@ -1,81 +1,81 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s -// expected-no-diagnostics - -_Static_assert(__builtin_hlsl_is_intangible(__hlsl_resource_t), ""); -// no need to check array of __hlsl_resource_t, arrays of sizeless types are not supported - -_Static_assert(!__builtin_hlsl_is_intangible(int), ""); -_Static_assert(!__builtin_hlsl_is_intangible(float3), ""); -_Static_assert(!__builtin_hlsl_is_intangible(half[4]), ""); - -typedef __hlsl_resource_t Res; -_Static_assert(__builtin_hlsl_is_intangible(const Res), ""); -// no need to check array of Res, arrays of sizeless types are not supported - -struct ABuffer { - const int i[10]; - __hlsl_resource_t h; -}; -_Static_assert(__builtin_hlsl_is_intangible(ABuffer), ""); -_Static_assert(__builtin_hlsl_is_intangible(ABuffer[10]), ""); - -struct MyStruct { - half2 h2; - int3 i3; -}; -_Static_assert(!__builtin_hlsl_is_intangible(MyStruct), ""); -_Static_assert(!__builtin_hlsl_is_intangible(MyStruct[10]), ""); - -class MyClass { - int3 ivec; - float farray[12]; - MyStruct ms; - ABuffer buf; -}; -_Static_assert(__builtin_hlsl_is_intangible(MyClass), ""); -_Static_assert(__builtin_hlsl_is_intangible(MyClass[2]), ""); - -union U { - double d[4]; - Res buf; -}; -_Static_assert(__builtin_hlsl_is_intangible(U), ""); -_Static_assert(__builtin_hlsl_is_intangible(U[100]), ""); - -class MyClass2 { - int3 ivec; - float farray[12]; - U u; -}; -_Static_assert(__builtin_hlsl_is_intangible(MyClass2), ""); -_Static_assert(__builtin_hlsl_is_intangible(MyClass2[5]), ""); - -class Simple { - int a; -}; - -template struct TemplatedBuffer { - T a; - __hlsl_resource_t h; -}; -_Static_assert(__builtin_hlsl_is_intangible(TemplatedBuffer), ""); - -struct MyStruct2 : TemplatedBuffer { - float x; -}; -_Static_assert(__builtin_hlsl_is_intangible(MyStruct2), ""); - -struct MyStruct3 { - const TemplatedBuffer TB[10]; -}; -_Static_assert(__builtin_hlsl_is_intangible(MyStruct3), ""); - -template struct SimpleTemplate { - T a; -}; -_Static_assert(__builtin_hlsl_is_intangible(SimpleTemplate<__hlsl_resource_t>), ""); -_Static_assert(!__builtin_hlsl_is_intangible(SimpleTemplate), ""); - -_Static_assert(__builtin_hlsl_is_intangible(RWBuffer), ""); -_Static_assert(__builtin_hlsl_is_intangible(StructuredBuffer), ""); +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s +// expected-no-diagnostics + +_Static_assert(__builtin_hlsl_is_intangible(__hlsl_resource_t), ""); +// no need to check array of __hlsl_resource_t, arrays of sizeless types are not supported + +_Static_assert(!__builtin_hlsl_is_intangible(int), ""); +_Static_assert(!__builtin_hlsl_is_intangible(float3), ""); +_Static_assert(!__builtin_hlsl_is_intangible(half[4]), ""); + +typedef __hlsl_resource_t Res; +_Static_assert(__builtin_hlsl_is_intangible(const Res), ""); +// no need to check array of Res, arrays of sizeless types are not supported + +struct ABuffer { + const int i[10]; + __hlsl_resource_t h; +}; +_Static_assert(__builtin_hlsl_is_intangible(ABuffer), ""); +_Static_assert(__builtin_hlsl_is_intangible(ABuffer[10]), ""); + +struct MyStruct { + half2 h2; + int3 i3; +}; +_Static_assert(!__builtin_hlsl_is_intangible(MyStruct), ""); +_Static_assert(!__builtin_hlsl_is_intangible(MyStruct[10]), ""); + +class MyClass { + int3 ivec; + float farray[12]; + MyStruct ms; + ABuffer buf; +}; +_Static_assert(__builtin_hlsl_is_intangible(MyClass), ""); +_Static_assert(__builtin_hlsl_is_intangible(MyClass[2]), ""); + +union U { + double d[4]; + Res buf; +}; +_Static_assert(__builtin_hlsl_is_intangible(U), ""); +_Static_assert(__builtin_hlsl_is_intangible(U[100]), ""); + +class MyClass2 { + int3 ivec; + float farray[12]; + U u; +}; +_Static_assert(__builtin_hlsl_is_intangible(MyClass2), ""); +_Static_assert(__builtin_hlsl_is_intangible(MyClass2[5]), ""); + +class Simple { + int a; +}; + +template struct TemplatedBuffer { + T a; + __hlsl_resource_t h; +}; +_Static_assert(__builtin_hlsl_is_intangible(TemplatedBuffer), ""); + +struct MyStruct2 : TemplatedBuffer { + float x; +}; +_Static_assert(__builtin_hlsl_is_intangible(MyStruct2), ""); + +struct MyStruct3 { + const TemplatedBuffer TB[10]; +}; +_Static_assert(__builtin_hlsl_is_intangible(MyStruct3), ""); + +template struct SimpleTemplate { + T a; +}; +_Static_assert(__builtin_hlsl_is_intangible(SimpleTemplate<__hlsl_resource_t>), ""); +_Static_assert(!__builtin_hlsl_is_intangible(SimpleTemplate), ""); + +_Static_assert(__builtin_hlsl_is_intangible(RWBuffer), ""); +_Static_assert(__builtin_hlsl_is_intangible(StructuredBuffer), ""); diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl index 33614e87640da..de9ac90b895fc 100644 --- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl +++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl @@ -1,12 +1,12 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s - -struct Undefined; // expected-note {{forward declaration of 'Undefined'}} -_Static_assert(!__builtin_hlsl_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}} - -void fn(int X) { // expected-note {{declared here}} - // expected-error@#vla {{variable length arrays are not supported for the current target}} - // expected-error@#vla {{variable length arrays are not supported in '__builtin_hlsl_is_intangible'}} - // expected-warning@#vla {{variable length arrays in C++ are a Clang extension}} - // expected-note@#vla {{function parameter 'X' with unknown value cannot be used in a constant expression}} - _Static_assert(!__builtin_hlsl_is_intangible(int[X]), ""); // #vla -} +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s + +struct Undefined; // expected-note {{forward declaration of 'Undefined'}} +_Static_assert(!__builtin_hlsl_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}} + +void fn(int X) { // expected-note {{declared here}} + // expected-error@#vla {{variable length arrays are not supported for the current target}} + // expected-error@#vla {{variable length arrays are not supported in '__builtin_hlsl_is_intangible'}} + // expected-warning@#vla {{variable length arrays in C++ are a Clang extension}} + // expected-note@#vla {{function parameter 'X' with unknown value cannot be used in a constant expression}} + _Static_assert(!__builtin_hlsl_is_intangible(int[X]), ""); // #vla +} diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_basic.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_basic.hlsl index 4e50f70952ad1..760c057630a7f 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error_basic.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error_basic.hlsl @@ -1,42 +1,42 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify - -// expected-error@+1{{binding type 't' only applies to SRV resources}} -float f1 : register(t0); - -// expected-error@+1 {{binding type 'u' only applies to UAV resources}} -float f2 : register(u0); - -// expected-error@+1{{binding type 'b' only applies to constant buffers. The 'bool constant' binding type is no longer supported}} -float f3 : register(b9); - -// expected-error@+1 {{binding type 's' only applies to sampler state}} -float f4 : register(s0); - -// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}} -float f5 : register(i9); - -// expected-error@+1{{binding type 'x' is invalid}} -float f6 : register(x9); - -cbuffer g_cbuffer1 { -// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}} - float f7 : register(c2); -}; - -tbuffer g_tbuffer1 { -// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}} - float f8 : register(c2); -}; - -cbuffer g_cbuffer2 { -// expected-error@+1{{binding type 'b' only applies to constant buffer resources}} - float f9 : register(b2); -}; - -tbuffer g_tbuffer2 { -// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}} - float f10 : register(i2); -}; - -// expected-error@+1{{binding type 'c' only applies to numeric variables in the global scope}} -RWBuffer f11 : register(c3); +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify + +// expected-error@+1{{binding type 't' only applies to SRV resources}} +float f1 : register(t0); + +// expected-error@+1 {{binding type 'u' only applies to UAV resources}} +float f2 : register(u0); + +// expected-error@+1{{binding type 'b' only applies to constant buffers. The 'bool constant' binding type is no longer supported}} +float f3 : register(b9); + +// expected-error@+1 {{binding type 's' only applies to sampler state}} +float f4 : register(s0); + +// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}} +float f5 : register(i9); + +// expected-error@+1{{binding type 'x' is invalid}} +float f6 : register(x9); + +cbuffer g_cbuffer1 { +// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}} + float f7 : register(c2); +}; + +tbuffer g_tbuffer1 { +// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}} + float f8 : register(c2); +}; + +cbuffer g_cbuffer2 { +// expected-error@+1{{binding type 'b' only applies to constant buffer resources}} + float f9 : register(b2); +}; + +tbuffer g_tbuffer2 { +// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}} + float f10 : register(i2); +}; + +// expected-error@+1{{binding type 'c' only applies to numeric variables in the global scope}} +RWBuffer f11 : register(c3); diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_other.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_other.hlsl index 503c8469666f3..4c9e9a6b44c92 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error_other.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error_other.hlsl @@ -1,9 +1,9 @@ -// RUN: not %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s | FileCheck %s - -// XFAIL: * -// This expectedly fails because RayQuery is an unsupported type. -// When it becomes supported, we should expect an error due to -// the variable type being classified as "other", and according -// to the spec, err_hlsl_unsupported_register_type_and_variable_type -// should be emitted. -RayQuery<0> r1: register(t0); +// RUN: not %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s | FileCheck %s + +// XFAIL: * +// This expectedly fails because RayQuery is an unsupported type. +// When it becomes supported, we should expect an error due to +// the variable type being classified as "other", and according +// to the spec, err_hlsl_unsupported_register_type_and_variable_type +// should be emitted. +RayQuery<0> r1: register(t0); diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_resource.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_resource.hlsl index ea43e27b5b5ac..4b6af47c0ab72 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error_resource.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error_resource.hlsl @@ -1,49 +1,49 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify - -// This test validates the diagnostics that are emitted when a variable with a "resource" type -// is bound to a register using the register annotation - - -template -struct MyTemplatedSRV { - __hlsl_resource_t [[hlsl::resource_class(SRV)]] x; -}; - -struct MySRV { - __hlsl_resource_t [[hlsl::resource_class(SRV)]] x; -}; - -struct MySampler { - __hlsl_resource_t [[hlsl::resource_class(Sampler)]] x; -}; - -struct MyUAV { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] x; -}; - -struct MyCBuffer { - __hlsl_resource_t [[hlsl::resource_class(CBuffer)]] x; -}; - - -// expected-error@+1 {{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}} -MySRV invalid : register(i2); - -// expected-error@+1 {{binding type 't' only applies to SRV resources}} -MyUAV a : register(t2, space1); - -// expected-error@+1 {{binding type 'u' only applies to UAV resources}} -MySampler b : register(u2, space1); - -// expected-error@+1 {{binding type 'b' only applies to constant buffer resources}} -MyTemplatedSRV c : register(b2); - -// expected-error@+1 {{binding type 's' only applies to sampler state}} -MyUAV d : register(s2, space1); - -// empty binding prefix cases: -// expected-error@+1 {{expected identifier}} -MyTemplatedSRV e: register(); - -// expected-error@+1 {{expected identifier}} -MyTemplatedSRV f: register(""); +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify + +// This test validates the diagnostics that are emitted when a variable with a "resource" type +// is bound to a register using the register annotation + + +template +struct MyTemplatedSRV { + __hlsl_resource_t [[hlsl::resource_class(SRV)]] x; +}; + +struct MySRV { + __hlsl_resource_t [[hlsl::resource_class(SRV)]] x; +}; + +struct MySampler { + __hlsl_resource_t [[hlsl::resource_class(Sampler)]] x; +}; + +struct MyUAV { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] x; +}; + +struct MyCBuffer { + __hlsl_resource_t [[hlsl::resource_class(CBuffer)]] x; +}; + + +// expected-error@+1 {{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}} +MySRV invalid : register(i2); + +// expected-error@+1 {{binding type 't' only applies to SRV resources}} +MyUAV a : register(t2, space1); + +// expected-error@+1 {{binding type 'u' only applies to UAV resources}} +MySampler b : register(u2, space1); + +// expected-error@+1 {{binding type 'b' only applies to constant buffer resources}} +MyTemplatedSRV c : register(b2); + +// expected-error@+1 {{binding type 's' only applies to sampler state}} +MyUAV d : register(s2, space1); + +// empty binding prefix cases: +// expected-error@+1 {{expected identifier}} +MyTemplatedSRV e: register(); + +// expected-error@+1 {{expected identifier}} +MyTemplatedSRV f: register(""); diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_silence_diags.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_silence_diags.hlsl index 7f248e30c0709..e63f264452da7 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error_silence_diags.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error_silence_diags.hlsl @@ -1,27 +1,27 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only -Wno-legacy-constant-register-binding %s -verify - -// expected-no-diagnostics -float f2 : register(b9); - -float f3 : register(i9); - -cbuffer g_cbuffer1 { - float f4 : register(c2); -}; - - -struct Eg12{ - RWBuffer a; -}; - -Eg12 e12 : register(c9); - -Eg12 bar : register(i1); - -struct Eg7 { - struct Bar { - float f; - }; - Bar b; -}; -Eg7 e7 : register(t0); +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only -Wno-legacy-constant-register-binding %s -verify + +// expected-no-diagnostics +float f2 : register(b9); + +float f3 : register(i9); + +cbuffer g_cbuffer1 { + float f4 : register(c2); +}; + + +struct Eg12{ + RWBuffer a; +}; + +Eg12 e12 : register(c9); + +Eg12 bar : register(i1); + +struct Eg7 { + struct Bar { + float f; + }; + Bar b; +}; +Eg7 e7 : register(t0); diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_space.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_space.hlsl index 3001dbb1e3ec9..70e64e6ca7528 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error_space.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error_space.hlsl @@ -1,62 +1,62 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify - -// valid -cbuffer cbuf { - RWBuffer r : register(u0, space0); -} - -cbuffer cbuf2 { - struct x { - // this test validates that no diagnostic is emitted on the space parameter, because - // this register annotation is not in the global scope. - // expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} - RWBuffer E : register(u2, space3); - }; -} - -struct MyStruct { - RWBuffer E; -}; - -cbuffer cbuf3 { - // valid - MyStruct E : register(u2, space3); -} - -// valid -MyStruct F : register(u3, space4); - -cbuffer cbuf4 { - // this test validates that no diagnostic is emitted on the space parameter, because - // this register annotation is not in the global scope. - // expected-error@+1 {{binding type 'u' only applies to UAV resources}} - float a : register(u2, space3); -} - -// expected-error@+1 {{invalid space specifier 's2' used; expected 'space' followed by an integer, like space1}} -cbuffer a : register(b0, s2) { - -} - -// expected-error@+1 {{invalid space specifier 'spaces' used; expected 'space' followed by an integer, like space1}} -cbuffer b : register(b2, spaces) { - -} - -// expected-error@+1 {{wrong argument format for hlsl attribute, use space3 instead}} -cbuffer c : register(b2, space 3) {} - -// expected-error@+1 {{register space cannot be specified on global constants}} -int d : register(c2, space3); - -// expected-error@+1 {{register space cannot be specified on global constants}} -int e : register(c2, space0); - -// expected-error@+1 {{register space cannot be specified on global constants}} -int f : register(c2, space00); - -// valid -RWBuffer g : register(u2, space0); - -// valid -RWBuffer h : register(u2, space0); +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify + +// valid +cbuffer cbuf { + RWBuffer r : register(u0, space0); +} + +cbuffer cbuf2 { + struct x { + // this test validates that no diagnostic is emitted on the space parameter, because + // this register annotation is not in the global scope. + // expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} + RWBuffer E : register(u2, space3); + }; +} + +struct MyStruct { + RWBuffer E; +}; + +cbuffer cbuf3 { + // valid + MyStruct E : register(u2, space3); +} + +// valid +MyStruct F : register(u3, space4); + +cbuffer cbuf4 { + // this test validates that no diagnostic is emitted on the space parameter, because + // this register annotation is not in the global scope. + // expected-error@+1 {{binding type 'u' only applies to UAV resources}} + float a : register(u2, space3); +} + +// expected-error@+1 {{invalid space specifier 's2' used; expected 'space' followed by an integer, like space1}} +cbuffer a : register(b0, s2) { + +} + +// expected-error@+1 {{invalid space specifier 'spaces' used; expected 'space' followed by an integer, like space1}} +cbuffer b : register(b2, spaces) { + +} + +// expected-error@+1 {{wrong argument format for hlsl attribute, use space3 instead}} +cbuffer c : register(b2, space 3) {} + +// expected-error@+1 {{register space cannot be specified on global constants}} +int d : register(c2, space3); + +// expected-error@+1 {{register space cannot be specified on global constants}} +int e : register(c2, space0); + +// expected-error@+1 {{register space cannot be specified on global constants}} +int f : register(c2, space00); + +// valid +RWBuffer g : register(u2, space0); + +// valid +RWBuffer h : register(u2, space0); diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_udt.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_udt.hlsl index 235004102a539..40517f393e128 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error_udt.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error_udt.hlsl @@ -1,135 +1,135 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify - -template -struct MyTemplatedUAV { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] x; -}; - -struct MySRV { - __hlsl_resource_t [[hlsl::resource_class(SRV)]] x; -}; - -struct MySampler { - __hlsl_resource_t [[hlsl::resource_class(Sampler)]] x; -}; - -struct MyUAV { - __hlsl_resource_t [[hlsl::resource_class(UAV)]] x; -}; - -struct MyCBuffer { - __hlsl_resource_t [[hlsl::resource_class(CBuffer)]] x; -}; - -// Valid: f is skipped, SRVBuf is bound to t0, UAVBuf is bound to u0 -struct Eg1 { - float f; - MySRV SRVBuf; - MyUAV UAVBuf; - }; -Eg1 e1 : register(t0) : register(u0); - -// Valid: f is skipped, SRVBuf is bound to t0, UAVBuf is bound to u0. -// UAVBuf2 gets automatically assigned to u1 even though there is no explicit binding for u1. -struct Eg2 { - float f; - MySRV SRVBuf; - MyUAV UAVBuf; - MyUAV UAVBuf2; - }; -Eg2 e2 : register(t0) : register(u0); - -// Valid: Bar, the struct within Eg3, has a valid resource that can be bound to t0. -struct Eg3 { - struct Bar { - MyUAV a; - }; - Bar b; -}; -Eg3 e3 : register(u0); - -// Valid: the first sampler state object within 's' is bound to slot 5 -struct Eg4 { - MySampler s[3]; -}; - -Eg4 e4 : register(s5); - - -struct Eg5 { - float f; -}; -// expected-warning@+1{{binding type 't' only applies to types containing SRV resources}} -Eg5 e5 : register(t0); - -struct Eg6 { - float f; -}; -// expected-warning@+1{{binding type 'u' only applies to types containing UAV resources}} -Eg6 e6 : register(u0); - -struct Eg7 { - float f; -}; -// expected-warning@+1{{binding type 'b' only applies to types containing constant buffer resources}} -Eg7 e7 : register(b0); - -struct Eg8 { - float f; -}; -// expected-warning@+1{{binding type 's' only applies to types containing sampler state}} -Eg8 e8 : register(s0); - -struct Eg9 { - MySRV s; -}; -// expected-warning@+1{{binding type 'c' only applies to types containing numeric types}} -Eg9 e9 : register(c0); - -struct Eg10{ - // expected-error@+1{{'register' attribute only applies to cbuffer/tbuffer and external global variables}} - MyTemplatedUAV a : register(u9); -}; -Eg10 e10; - - -template -struct Eg11 { - R b; -}; -// expected-warning@+1{{binding type 'u' only applies to types containing UAV resources}} -Eg11 e11 : register(u0); -// invalid because after template expansion, there are no valid resources inside Eg11 to bind as a UAV, only an SRV - - -struct Eg12{ - MySRV s1; - MySRV s2; -}; -// expected-warning@+2{{binding type 'u' only applies to types containing UAV resources}} -// expected-error@+1{{binding type 'u' cannot be applied more than once}} -Eg12 e12 : register(u9) : register(u10); - -struct Eg13{ - MySRV s1; - MySRV s2; -}; -// expected-warning@+3{{binding type 'u' only applies to types containing UAV resources}} -// expected-error@+2{{binding type 'u' cannot be applied more than once}} -// expected-error@+1{{binding type 'u' cannot be applied more than once}} -Eg13 e13 : register(u9) : register(u10) : register(u11); - -// expected-error@+1{{binding type 't' cannot be applied more than once}} -Eg13 e13_2 : register(t11) : register(t12); - -struct Eg14{ - MyTemplatedUAV r1; -}; -// expected-warning@+1{{binding type 't' only applies to types containing SRV resources}} -Eg14 e14 : register(t9); - -struct Eg15 { - float f[4]; -}; -// expected no error -Eg15 e15 : register(c0); +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify + +template +struct MyTemplatedUAV { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] x; +}; + +struct MySRV { + __hlsl_resource_t [[hlsl::resource_class(SRV)]] x; +}; + +struct MySampler { + __hlsl_resource_t [[hlsl::resource_class(Sampler)]] x; +}; + +struct MyUAV { + __hlsl_resource_t [[hlsl::resource_class(UAV)]] x; +}; + +struct MyCBuffer { + __hlsl_resource_t [[hlsl::resource_class(CBuffer)]] x; +}; + +// Valid: f is skipped, SRVBuf is bound to t0, UAVBuf is bound to u0 +struct Eg1 { + float f; + MySRV SRVBuf; + MyUAV UAVBuf; + }; +Eg1 e1 : register(t0) : register(u0); + +// Valid: f is skipped, SRVBuf is bound to t0, UAVBuf is bound to u0. +// UAVBuf2 gets automatically assigned to u1 even though there is no explicit binding for u1. +struct Eg2 { + float f; + MySRV SRVBuf; + MyUAV UAVBuf; + MyUAV UAVBuf2; + }; +Eg2 e2 : register(t0) : register(u0); + +// Valid: Bar, the struct within Eg3, has a valid resource that can be bound to t0. +struct Eg3 { + struct Bar { + MyUAV a; + }; + Bar b; +}; +Eg3 e3 : register(u0); + +// Valid: the first sampler state object within 's' is bound to slot 5 +struct Eg4 { + MySampler s[3]; +}; + +Eg4 e4 : register(s5); + + +struct Eg5 { + float f; +}; +// expected-warning@+1{{binding type 't' only applies to types containing SRV resources}} +Eg5 e5 : register(t0); + +struct Eg6 { + float f; +}; +// expected-warning@+1{{binding type 'u' only applies to types containing UAV resources}} +Eg6 e6 : register(u0); + +struct Eg7 { + float f; +}; +// expected-warning@+1{{binding type 'b' only applies to types containing constant buffer resources}} +Eg7 e7 : register(b0); + +struct Eg8 { + float f; +}; +// expected-warning@+1{{binding type 's' only applies to types containing sampler state}} +Eg8 e8 : register(s0); + +struct Eg9 { + MySRV s; +}; +// expected-warning@+1{{binding type 'c' only applies to types containing numeric types}} +Eg9 e9 : register(c0); + +struct Eg10{ + // expected-error@+1{{'register' attribute only applies to cbuffer/tbuffer and external global variables}} + MyTemplatedUAV a : register(u9); +}; +Eg10 e10; + + +template +struct Eg11 { + R b; +}; +// expected-warning@+1{{binding type 'u' only applies to types containing UAV resources}} +Eg11 e11 : register(u0); +// invalid because after template expansion, there are no valid resources inside Eg11 to bind as a UAV, only an SRV + + +struct Eg12{ + MySRV s1; + MySRV s2; +}; +// expected-warning@+2{{binding type 'u' only applies to types containing UAV resources}} +// expected-error@+1{{binding type 'u' cannot be applied more than once}} +Eg12 e12 : register(u9) : register(u10); + +struct Eg13{ + MySRV s1; + MySRV s2; +}; +// expected-warning@+3{{binding type 'u' only applies to types containing UAV resources}} +// expected-error@+2{{binding type 'u' cannot be applied more than once}} +// expected-error@+1{{binding type 'u' cannot be applied more than once}} +Eg13 e13 : register(u9) : register(u10) : register(u11); + +// expected-error@+1{{binding type 't' cannot be applied more than once}} +Eg13 e13_2 : register(t11) : register(t12); + +struct Eg14{ + MyTemplatedUAV r1; +}; +// expected-warning@+1{{binding type 't' only applies to types containing SRV resources}} +Eg14 e14 : register(t9); + +struct Eg15 { + float f[4]; +}; +// expected no error +Eg15 e15 : register(c0); diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx9.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx9.cl index c9fd8ab2cae86..7c07632aeb60b 100644 --- a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx9.cl +++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx9.cl @@ -3,7 +3,58 @@ #pragma OPENCL EXTENSION cl_khr_fp16 : enable +typedef int int2 __attribute__((ext_vector_type(2))); + +struct S { + int x; +}; + void test_gfx9_fmed3h(global half *out, half a, half b, half c) { *out = __builtin_amdgcn_fmed3h(a, b, c); // expected-error {{'__builtin_amdgcn_fmed3h' needs target feature gfx9-insts}} } + +void test_mov_dpp(global int* out, int src, int i, int2 i2, struct S s, float _Complex fc) +{ + *out = __builtin_amdgcn_mov_dpp(src, i, 0, 0, false); // expected-error{{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}} + *out = __builtin_amdgcn_mov_dpp(src, 0, i, 0, false); // expected-error{{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}} + *out = __builtin_amdgcn_mov_dpp(src, 0, 0, i, false); // expected-error{{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}} + *out = __builtin_amdgcn_mov_dpp(src, 0, 0, 0, i); // expected-error{{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}} + *out = __builtin_amdgcn_mov_dpp(src, 0.1, 0, 0, false); // expected-error{{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}} + *out = __builtin_amdgcn_mov_dpp(src, 0, 0.1, 0, false); // expected-error{{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}} + *out = __builtin_amdgcn_mov_dpp(src, 0, 0, 0.1, false); // expected-error{{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}} + *out = __builtin_amdgcn_mov_dpp(src, 0, 0, 0, 0.1); // expected-error{{argument to '__builtin_amdgcn_mov_dpp' must be a constant integer}} + *out = __builtin_amdgcn_mov_dpp(src, 0, 0, 0); // expected-error{{too few arguments to function call, expected 5, have 4}} + *out = __builtin_amdgcn_mov_dpp(src, 0, 0, 0, false, 1); // expected-error{{too many arguments to function call, expected at most 5, have 6}} + *out = __builtin_amdgcn_mov_dpp(out, 0, 0, 0, false); // expected-error{{used type '__global int *__private' where integer or floating point type is required}} + *out = __builtin_amdgcn_mov_dpp("aa", 0, 0, 0, false); // expected-error{{used type '__constant char[3]' where integer or floating point type is required}} + *out = __builtin_amdgcn_mov_dpp(i2, 0, 0, 0, false); // expected-error{{used type '__private int2' (vector of 2 'int' values) where integer or floating point type is required}} + *out = __builtin_amdgcn_mov_dpp(s, 0, 0, 0, false); // expected-error{{used type '__private struct S' where integer or floating point type is required}} + *out = __builtin_amdgcn_mov_dpp(fc, 0, 0, 0, false); // expected-error{{used type '__private _Complex float' where integer or floating point type is required}} +} + +void test_update_dpp(global int* out, int arg1, int arg2, int i, int2 i2, long l, struct S s, float _Complex fc) +{ + *out = __builtin_amdgcn_update_dpp(arg1, arg2, i, 0, 0, false); // expected-error{{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, i, 0, false); // expected-error{{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, i, false); // expected-error{{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, 0, i); // expected-error{{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0.1, 0, 0, false); // expected-error{{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0.1, 0, false); // expected-error{{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, 0.1, false); // expected-error{{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, 0, 0.1); // expected-error{{argument to '__builtin_amdgcn_update_dpp' must be a constant integer}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, 0); // expected-error{{too few arguments to function call, expected 6, have 5}} + *out = __builtin_amdgcn_update_dpp(arg1, arg2, 0, 0, 0, false, 1); // expected-error{{too many arguments to function call, expected at most 6, have 7}} + *out = __builtin_amdgcn_update_dpp(out, arg2, 0, 0, 0, false); // expected-error{{used type '__global int *__private' where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(arg1, out, 0, 0, 0, false); // expected-error{{used type '__global int *__private' where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp("aa", arg2, 0, 0, 0, false); // expected-error{{used type '__constant char[3]' where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(arg1, "aa", 0, 0, 0, false); // expected-error{{used type '__constant char[3]' where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(i2, arg2, 0, 0, 0, false); // expected-error{{used type '__private int2' (vector of 2 'int' values) where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(arg1, i2, 0, 0, 0, false); // expected-error{{used type '__private int2' (vector of 2 'int' values) where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(s, arg2, 0, 0, 0, false); // expected-error{{used type '__private struct S' where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(arg1, s, 0, 0, 0, false); // expected-error{{used type '__private struct S' where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(fc, arg2, 0, 0, 0, false); // expected-error{{used type '__private _Complex float' where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(arg1, fc, 0, 0, 0, false); // expected-error{{used type '__private _Complex float' where integer or floating point type is required}} + *out = __builtin_amdgcn_update_dpp(i, l, 0, 0, 0, false); // expected-error{{arguments are of different types ('__private int' vs '__private long')}} + *out = __builtin_amdgcn_update_dpp(0.5f, i, 0, 0, 0, false); // expected-error{{arguments are of different types ('float' vs '__private int')}} +} diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 6aed46328f346..108db7204aa68 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -351,9 +351,6 @@ static void outputReplacementsXML(const Replacements &Replaces) { static bool emitReplacementWarnings(const Replacements &Replaces, StringRef AssumedFileName, const std::unique_ptr &Code) { - if (Replaces.empty()) - return false; - unsigned Errors = 0; if (WarnFormat && !NoWarnFormat) { SourceMgr Mgr; @@ -490,9 +487,11 @@ static bool format(StringRef FileName, bool ErrorOnIncompleteFormat = false) { Replacements Replaces = sortIncludes(*FormatStyle, Code->getBuffer(), Ranges, AssumedFileName, &CursorPosition); + const bool IsJson = FormatStyle->isJson(); + // To format JSON insert a variable to trick the code into thinking its // JavaScript. - if (FormatStyle->isJson() && !FormatStyle->DisableFormat) { + if (IsJson && !FormatStyle->DisableFormat) { auto Err = Replaces.add(tooling::Replacement( tooling::Replacement(AssumedFileName, 0, 0, "x = "))); if (Err) @@ -510,9 +509,11 @@ static bool format(StringRef FileName, bool ErrorOnIncompleteFormat = false) { Replacements FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status); Replaces = Replaces.merge(FormatChanges); - if (OutputXML || DryRun) { - if (DryRun) - return emitReplacementWarnings(Replaces, AssumedFileName, Code); + if (DryRun) { + return Replaces.size() > (IsJson ? 1 : 0) && + emitReplacementWarnings(Replaces, AssumedFileName, Code); + } + if (OutputXML) { outputXML(Replaces, FormatChanges, Status, Cursor, CursorPosition); } else { IntrusiveRefCntPtr InMemoryFileSystem( diff --git a/clang/tools/clang-format/clang-format.el b/clang/tools/clang-format/clang-format.el index f3da5415f8672..fb943b7b722f8 100644 --- a/clang/tools/clang-format/clang-format.el +++ b/clang/tools/clang-format/clang-format.el @@ -70,6 +70,20 @@ in such buffers." :safe #'stringp) (make-variable-buffer-local 'clang-format-fallback-style) +(defcustom clang-format-on-save-p 'clang-format-on-save-check-config-exists + "Only reformat on save if this function returns non-nil. + +You may wish to choose one of the following options: +- `always': To always format on save. +- `clang-format-on-save-check-config-exists': + Only reformat when \".clang-format\" exists. + +Otherwise you can set this to a user defined function." + :group 'clang-format + :type 'function + :risky t) +(make-variable-buffer-local 'clang-format-on-save-p) + (defun clang-format--extract (xml-node) "Extract replacements and cursor information from XML-NODE." (unless (and (listp xml-node) (eq (xml-node-name xml-node) 'replacements)) @@ -217,5 +231,48 @@ the function `buffer-file-name'." ;;;###autoload (defalias 'clang-format 'clang-format-region) +;; Format on save minor mode. + +(defun clang-format--on-save-buffer-hook () + "The hook to run on buffer saving to format the buffer." + ;; Demote errors as this is user configurable, we can't be sure it wont error. + (when (with-demoted-errors "clang-format: Error %S" + (funcall clang-format-on-save-p)) + (clang-format-buffer)) + ;; Continue to save. + nil) + +(defun clang-format--on-save-enable () + "Disable the minor mode." + (add-hook 'before-save-hook #'clang-format--on-save-buffer-hook nil t)) + +(defun clang-format--on-save-disable () + "Enable the minor mode." + (remove-hook 'before-save-hook #'clang-format--on-save-buffer-hook t)) + +;; Default value for `clang-format-on-save-p'. +(defun clang-format-on-save-check-config-exists () + "Return non-nil when `.clang-format' is found in a parent directory." + ;; Unlikely but possible this is nil. + (let ((filepath buffer-file-name)) + (cond + (filepath + (not (null (locate-dominating-file (file-name-directory filepath) ".clang-format")))) + (t + nil)))) + +;;;###autoload +(define-minor-mode clang-format-on-save-mode + "Clang-format on save minor mode." + :global nil + :lighter "" + :keymap nil + + (cond + (clang-format-on-save-mode + (clang-format--on-save-enable)) + (t + (clang-format--on-save-disable)))) + (provide 'clang-format) ;;; clang-format.el ends here diff --git a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp index b4b376fe0d114..b9767a7a03d0b 100644 --- a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp +++ b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp @@ -344,7 +344,7 @@ Expected> createLTO(const ArgList &Args) { Conf.RemarksHotnessThreshold = RemarksHotnessThreshold; Conf.RemarksFormat = RemarksFormat; - Conf.MAttrs = {Args.getLastArgValue(OPT_feature, "").str()}; + Conf.MAttrs = llvm::codegen::getMAttrs(); std::optional CGOptLevelOrNone = CodeGenOpt::parseLevel(Args.getLastArgValue(OPT_O, "2")[0]); assert(CGOptLevelOrNone && "Invalid optimization level"); diff --git a/clang/tools/clang-nvlink-wrapper/NVLinkOpts.td b/clang/tools/clang-nvlink-wrapper/NVLinkOpts.td index eeb9d1a622824..a80c5937b4299 100644 --- a/clang/tools/clang-nvlink-wrapper/NVLinkOpts.td +++ b/clang/tools/clang-nvlink-wrapper/NVLinkOpts.td @@ -47,9 +47,6 @@ def arch : Separate<["--", "-"], "arch">, def : Joined<["--", "-"], "plugin-opt=mcpu=">, Flags<[HelpHidden, WrapperOnlyOption]>, Alias; -def feature : Separate<["--", "-"], "feature">, Flags<[WrapperOnlyOption]>, - HelpText<"Specify the '+ptx' freature to use for LTO.">; - def g : Flag<["-"], "g">, HelpText<"Specify that this was a debug compile.">; def debug : Flag<["--"], "debug">, Alias; diff --git a/clang/tools/scan-build/bin/scan-build.bat b/clang/tools/scan-build/bin/scan-build.bat index f765f205b8ec5..77be6746318f1 100644 --- a/clang/tools/scan-build/bin/scan-build.bat +++ b/clang/tools/scan-build/bin/scan-build.bat @@ -1 +1 @@ -perl -S scan-build %* +perl -S scan-build %* diff --git a/clang/tools/scan-build/libexec/c++-analyzer.bat b/clang/tools/scan-build/libexec/c++-analyzer.bat index 83c7172456a51..69f048a91671f 100644 --- a/clang/tools/scan-build/libexec/c++-analyzer.bat +++ b/clang/tools/scan-build/libexec/c++-analyzer.bat @@ -1 +1 @@ -perl -S c++-analyzer %* +perl -S c++-analyzer %* diff --git a/clang/tools/scan-build/libexec/ccc-analyzer.bat b/clang/tools/scan-build/libexec/ccc-analyzer.bat index fdd36f3bdd043..2a85376eb82b1 100644 --- a/clang/tools/scan-build/libexec/ccc-analyzer.bat +++ b/clang/tools/scan-build/libexec/ccc-analyzer.bat @@ -1 +1 @@ -perl -S ccc-analyzer %* +perl -S ccc-analyzer %* diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp index 877bfce8b2709..0209703395bc1 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp @@ -1342,7 +1342,8 @@ class UncheckedOptionalAccessTest Diagnoser = UncheckedOptionalAccessDiagnoser(Options)]( ASTContext &Ctx, const CFGElement &Elt, - const TransferStateForDiagnostics + const TransferStateForDiagnostics< + UncheckedOptionalAccessLattice> &State) mutable { auto EltDiagnostics = Diagnoser(Elt, Ctx, State); llvm::move(EltDiagnostics, std::back_inserter(Diagnostics)); @@ -2166,6 +2167,26 @@ TEST_P(UncheckedOptionalAccessTest, OptionalReturnedFromFuntionCall) { )"); } +TEST_P(UncheckedOptionalAccessTest, OptionalFieldModified) { + ExpectDiagnosticsFor( + R"( + #include "unchecked_optional_access_test.h" + + struct Foo { + $ns::$optional opt; + void clear(); // assume this may modify the opt field's state + }; + + void target(Foo& foo) { + if (foo.opt) { + foo.opt.value(); + foo.clear(); + foo.opt.value(); // [[unsafe]] + } + } + )"); +} + TEST_P(UncheckedOptionalAccessTest, StdSwap) { ExpectDiagnosticsFor( R"( @@ -3549,6 +3570,180 @@ TEST_P(UncheckedOptionalAccessTest, ClassDerivedFromOptionalValueConstructor) { )"); } +TEST_P(UncheckedOptionalAccessTest, ConstRefAccessor) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + const $ns::$optional& get() const { return x; } + $ns::$optional x; + }; + + void target(A& a) { + if (a.get().has_value()) { + a.get().value(); + } + } + )cc"); +} + +TEST_P(UncheckedOptionalAccessTest, ConstRefAccessorWithModInBetween) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + const $ns::$optional& get() const { return x; } + void clear(); + $ns::$optional x; + }; + + void target(A& a) { + if (a.get().has_value()) { + a.clear(); + a.get().value(); // [[unsafe]] + } + } + )cc"); +} + +TEST_P(UncheckedOptionalAccessTest, ConstRefAccessorWithModReturningOptional) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + const $ns::$optional& get() const { return x; } + $ns::$optional take(); + $ns::$optional x; + }; + + void target(A& a) { + if (a.get().has_value()) { + $ns::$optional other = a.take(); + a.get().value(); // [[unsafe]] + if (other.has_value()) { + other.value(); + } + } + } + )cc"); +} + +TEST_P(UncheckedOptionalAccessTest, ConstRefAccessorDifferentObjects) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + const $ns::$optional& get() const { return x; } + $ns::$optional x; + }; + + void target(A& a1, A& a2) { + if (a1.get().has_value()) { + a2.get().value(); // [[unsafe]] + } + } + )cc"); +} + +TEST_P(UncheckedOptionalAccessTest, ConstRefAccessorLoop) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + const $ns::$optional& get() const { return x; } + $ns::$optional x; + }; + + void target(A& a, int N) { + for (int i = 0; i < N; ++i) { + if (a.get().has_value()) { + a.get().value(); + } + } + } + )cc"); +} + +TEST_P(UncheckedOptionalAccessTest, ConstByValueAccessor) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + $ns::$optional get() const { return x; } + $ns::$optional x; + }; + + void target(A& a) { + if (a.get().has_value()) { + a.get().value(); + } + } + )cc"); +} + +TEST_P(UncheckedOptionalAccessTest, ConstByValueAccessorWithModInBetween) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + $ns::$optional get() const { return x; } + void clear(); + $ns::$optional x; + }; + + void target(A& a) { + if (a.get().has_value()) { + a.clear(); + a.get().value(); // [[unsafe]] + } + } + )cc"); +} + +TEST_P(UncheckedOptionalAccessTest, ConstBoolAccessor) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + bool isFoo() const { return f; } + bool f; + }; + + void target(A& a) { + std::optional opt; + if (a.isFoo()) { + opt = 1; + } + if (a.isFoo()) { + opt.value(); + } + } + )cc"); +} + +TEST_P(UncheckedOptionalAccessTest, ConstBoolAccessorWithModInBetween) { + ExpectDiagnosticsFor(R"cc( + #include "unchecked_optional_access_test.h" + + struct A { + bool isFoo() const { return f; } + void clear(); + bool f; + }; + + void target(A& a) { + std::optional opt; + if (a.isFoo()) { + opt = 1; + } + a.clear(); + if (a.isFoo()) { + opt.value(); // [[unsafe]] + } + } + )cc"); +} + // FIXME: Add support for: // - constructors (copy, move) // - assignment operators (default, copy, move) diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp index 691d74f697f27..d8d23e3b67009 100644 --- a/clang/unittests/Basic/DiagnosticTest.cpp +++ b/clang/unittests/Basic/DiagnosticTest.cpp @@ -16,6 +16,11 @@ using namespace llvm; using namespace clang; +// Declare DiagnosticsTestHelper to avoid GCC warning +namespace clang { +void DiagnosticsTestHelper(DiagnosticsEngine &diag); +} + void clang::DiagnosticsTestHelper(DiagnosticsEngine &diag) { EXPECT_FALSE(diag.DiagStates.empty()); EXPECT_TRUE(diag.DiagStatesByLoc.empty()); diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp index 3b04238b9b48b..151f7072e0c65 100644 --- a/clang/unittests/Format/FormatTestCSharp.cpp +++ b/clang/unittests/Format/FormatTestCSharp.cpp @@ -1688,6 +1688,28 @@ TEST_F(FormatTestCSharp, BrokenBrackets) { EXPECT_NE("", format("int where b <")); // reduced from crasher } +TEST_F(FormatTestCSharp, GotoCaseLabel) { + verifyFormat("switch (i)\n" + "{\n" + "case 0:\n" + " goto case 1;\n" + "case 1:\n" + " j = 0;\n" + " {\n" + " break;\n" + " }\n" + "}", + "switch (i) {\n" + "case 0:\n" + " goto case 1;\n" + "case 1:\n" + " j = 0;\n" + " {\n" + " break;\n" + " }\n" + "}"); +} + } // namespace } // namespace test } // namespace format diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 60deae0c9b112..da195ccb6f6db 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1318,6 +1318,15 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) { Tokens = annotate("bool x = t && requires(Foo x) { x.foo(); };"); ASSERT_EQ(Tokens.size(), 25u) << Tokens; EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression); + + // Second function definition is required due to lookahead + Tokens = annotate("void f() &\n" + " requires(n == 1)\n" + "{}\n" + "void g();"); + ASSERT_EQ(Tokens.size(), 19u) << Tokens; + EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference); + EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause); } TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) { diff --git a/clang/utils/ClangVisualizers/clang.natvis b/clang/utils/ClangVisualizers/clang.natvis index 611c20dacce17..a7c70186bc46d 100644 --- a/clang/utils/ClangVisualizers/clang.natvis +++ b/clang/utils/ClangVisualizers/clang.natvis @@ -1,1089 +1,1089 @@ - - - - - - - LocInfoType - {(clang::Type::TypeClass)TypeBits.TC, en}Type - - {*(clang::BuiltinType *)this} - {*(clang::PointerType *)this} - {*(clang::ParenType *)this} - {(clang::BitIntType *)this} - {*(clang::LValueReferenceType *)this} - {*(clang::RValueReferenceType *)this} - {(clang::ConstantArrayType *)this,na} - {(clang::ConstantArrayType *)this,view(left)na} - {(clang::ConstantArrayType *)this,view(right)na} - {(clang::VariableArrayType *)this,na} - {(clang::VariableArrayType *)this,view(left)na} - {(clang::VariableArrayType *)this,view(right)na} - {(clang::IncompleteArrayType *)this,na} - {(clang::IncompleteArrayType *)this,view(left)na} - {(clang::IncompleteArrayType *)this,view(right)na} - {(clang::TypedefType *)this,na} - {(clang::TypedefType *)this,view(cpp)na} - {*(clang::AttributedType *)this} - {(clang::DecayedType *)this,na} - {(clang::DecayedType *)this,view(left)na} - {(clang::DecayedType *)this,view(right)na} - {(clang::ElaboratedType *)this,na} - {(clang::ElaboratedType *)this,view(left)na} - {(clang::ElaboratedType *)this,view(right)na} - {*(clang::TemplateTypeParmType *)this} - {*(clang::TemplateTypeParmType *)this,view(cpp)} - {*(clang::SubstTemplateTypeParmType *)this} - {*(clang::RecordType *)this} - {*(clang::RecordType *)this,view(cpp)} - {(clang::FunctionProtoType *)this,na} - {(clang::FunctionProtoType *)this,view(left)na} - {(clang::FunctionProtoType *)this,view(right)na} - {*(clang::TemplateSpecializationType *)this} - {*(clang::DeducedTemplateSpecializationType *)this} - {*(clang::DeducedTemplateSpecializationType *)this,view(cpp)} - {*(clang::InjectedClassNameType *)this} - {*(clang::DependentNameType *)this} - {*(clang::PackExpansionType *)this} - {(clang::LocInfoType *)this,na} - {(clang::LocInfoType *)this,view(cpp)na} - {this,view(poly)na} - {*this,view(cpp)} - - No visualizer yet for {(clang::Type::TypeClass)TypeBits.TC,en}Type - Dependence{" ",en} - - CachedLinkage: {(clang::Linkage)TypeBits.CachedLinkage,en} CachedLocalOrUnnamed - CachedLinkage: {(clang::Linkage)TypeBits.CachedLinkage,en}{" ",sb} - - FromAST - - - No TypeBits set beyond TypeClass - - {*this, view(Dependence)}{*this, view(Cache)}{*this, view(FromAST)} - {*this,view(cmn)} {{{*this,view(poly)}}} - - (clang::Type::TypeClass)TypeBits.TC - this,view(flags)na - CanonicalType - *(clang::BuiltinType *)this - *(clang::PointerType *)this - *(clang::ParenType*)this - *(clang::BitIntType*)this - *(clang::LValueReferenceType *)this - *(clang::RValueReferenceType *)this - (clang::ConstantArrayType *)this - (clang::VariableArrayType *)this - (clang::IncompleteArrayType *)this - *(clang::AttributedType *)this - (clang::DecayedType *)this - (clang::ElaboratedType *)this - (clang::TemplateTypeParmType *)this - (clang::SubstTemplateTypeParmType *)this - (clang::RecordType *)this - (clang::FunctionProtoType *)this - (clang::TemplateSpecializationType *)this - (clang::DeducedTemplateSpecializationType *)this - (clang::InjectedClassNameType *)this - (clang::DependentNameType *)this - (clang::PackExpansionType *)this - (clang::LocInfoType *)this - - - - - ElementType - - - - {ElementType,view(cpp)} - [{Size}] - {ElementType,view(cpp)}[{Size}] - - Size - (clang::ArrayType *)this - - - - {ElementType,view(cpp)} - [] - {ElementType,view(cpp)}[] - - (clang::ArrayType *)this - - - - {ElementType,view(cpp)} - [*] - {ElementType,view(cpp)}[*] - - (clang::Expr *)SizeExpr - (clang::ArrayType *)this - - - - {Decl,view(name)nd} - {Decl} - - Decl - *(clang::Type *)this, view(cmn) - - - - {PointeeType, view(cpp)} * - - PointeeType - *(clang::Type *)this, view(cmn) - - - - {Inner, view(cpp)} - - Inner - *(clang::Type *)this, view(cmn) - - - - signed _BitInt({NumBits}) - unsigned _BitInt({NumBits})( - - NumBits - (clang::Type *)this, view(cmn) - - - - - {((clang::ReferenceType *)this)->PointeeType,view(cpp)} & - - *(clang::Type *)this, view(cmn) - PointeeType - - - - {((clang::ReferenceType *)this)->PointeeType,view(cpp)} && - - *(clang::Type *)this, view(cmn) - PointeeType - - - - {ModifiedType} Attribute={(clang::AttributedType::Kind)AttributedTypeBits.AttrKind} - - - - - {(clang::Decl::Kind)DeclContextBits.DeclKind,en}Decl - - (clang::Decl::Kind)DeclContextBits.DeclKind,en - - - - - FirstDecl - (clang::Decl *)(*(intptr_t *)NextInContextAndBits.Value.Data & ~3) - *this - - - - - - - Field {{{*(clang::DeclaratorDecl *)this,view(cpp)nd}}} - - - {*(clang::FunctionDecl *)this,nd} - Method {{{*this,view(cpp)}}} - - - Constructor {{{Name,view(cpp)}({*(clang::FunctionDecl *)this,view(parm0)nd})}} - - - Destructor {{~{Name,view(cpp)}()}} - - - typename - class - (not yet known if parameter pack) - ... - - {(TypeSourceInfo *)(*(uintptr_t *)DefaultArgument.ValueOrInherited.Val.Value.Data&~3LL),view(cpp)} - {{InheritedInitializer}} - = {this,view(DefaultArg)na} - - {*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)} {this,view(Initializer)na} - - - {*TemplatedDecl,view(cpp)} - template{TemplateParams,na} {*TemplatedDecl}; - - TemplateParams,na - TemplatedDecl,na - - - - - {(clang::TypeSourceInfo *)(*(uintptr_t *)MaybeModedTInfo.Value.Data & ~7LL),view(cpp)na} - {(clang::TypedefNameDecl::ModedTInfo *)(*(uintptr_t *)MaybeModedTInfo.Value.Data & ~7LL),view(cpp)na} - {(TypeDecl *)this,view(cpp)nand} - typedef {this,view(type)na} {this,view(name)na}; - - "Not yet calculated",sb - (bool)(*(uintptr_t *)MaybeModedTInfo.Value.Data & 2) - (clang::TypeSourceInfo *)(*(uintptr_t *)MaybeModedTInfo.Value.Data & ~7LL) - (clang::TypedefNameDecl::ModedTInfo *)(*(uintptr_t *)MaybeModedTInfo.Value.Data & ~7LL) - (TypeDecl *)this,nd - - - - {(TypedefNameDecl *)this,view(name)nand} - using {(TypedefNameDecl *)this,view(name)nand} = {(TypedefNameDecl *)this,view(type)nand} - - - {Name} - - - Kind={(UncommonTemplateNameStorage::Kind)Kind,en}, Size={Size} - - (UncommonTemplateNameStorage::Kind)Kind - Size - - - - {Bits}, - {this,view(cmn)na},{(OverloadedTemplateStorage*)this,na} - {this,view(cmn)na},{(AssumedTemplateStorage*)this,na} - {this,view(cmn)na},{(SubstTemplateTemplateParmStorage*)this,na} - {this,view(cmn)na},{(SubstTemplateTemplateParmPackStorage*)this,na} - {this,view(cmn)na} - - Bits - (OverloadedTemplateStorage*)this - (AssumedTemplateStorage*)this - (SubstTemplateTemplateParmStorage*)this - (SubstTemplateTemplateParmPackStorage*)this - - - - - - - {(clang::TemplateDecl *)(Val.Value & ~3LL),view(cpp)na} - - - {(clang::TemplateDecl *)(Val.Value & ~3LL),na} - - - {(clang::UncommonTemplateNameStorage *)(Val.Value & ~3LL),view(cpp)na} - - - {(clang::UncommonTemplateNameStorage *)(Val.Value & ~3LL),na} - - - {(clang::QualifiedTemplateName *)(Val.Value & ~3LL),view(cpp)na} - - - {(clang::QualifiedTemplateName *)(Val.Value & ~3LL),na} - - - {(clang::DependentTemplateName *)(Val.Value & ~3LL),view(cpp)na} - - - {(clang::DependentTemplateName *)(Val.Value & ~3LL),na} - - - "TemplateDecl",s8b - - (clang::TemplateDecl *)(Val.Value & ~3LL) - - "UncommonTemplateNameStorage",s8b - - (clang::UncommonTemplateNameStorage *)(Val.Value & ~3LL) - - "QualifiedTemplateName",s8b - - (clang::QualifiedTemplateName *)(Val.Value & ~3LL) - - "DependentTemplateName",s8b - - (clang::DependentTemplateName *)(Val.Value & ~3LL) - - Val - - - - - {Storage,view(cpp)na} - {Storage,na} - - Storage - - - - {Name,view(cpp)} - {Name} - - - implicit{" ",sb} - - {*this,view(implicit)nd} - {*this,view(modifiers)}{Name,view(cpp)} - {*this,view(modifiers)nd}struct {Name,view(cpp)} - {*this,view(modifiers)nd}interface {Name,view(cpp)} - {*this,view(modifiers)nd}union {Name,view(cpp)} - {*this,view(modifiers)nd}class {Name,view(cpp)} - {*this,view(modifiers)nd}enum {Name,view(cpp)} - - (clang::DeclContext *)this - - - - {decl,view(cpp)na} - {*decl} - - *(clang::Type *)this, view(cmn) - decl - - - - {(clang::TagType *)this,view(cpp)na} - {(clang::TagType *)this,na} - - *(clang::TagType *)this - - - - {{{*Replaced,view(cpp)} <= {CanonicalType,view(cpp)}}} - - *(clang::Type *)this, view(cmn) - *Replaced - - - - - - {ResultType,view(cpp)} - - {*(clang::QualType *)(this+1),view(cpp)}{*this,view(parm1)} - - , {*((clang::QualType *)(this+1)+1),view(cpp)}{*this,view(parm2)} - - , {*((clang::QualType *)(this+1)+2),view(cpp)}{*this,view(parm3)} - - , {*((clang::QualType *)(this+1)+3),view(cpp)}{*this,view(parm4)} - - , {*((clang::QualType *)(this+1)+4),view(cpp)}{*this,view(parm5)} - - , /* expand for more params */ - ({*this,view(parm0)}) -> {ResultType,view(cpp)} - ({*this,view(parm0)}) - {this,view(left)na}{this,view(right)na} - - ResultType - - {*this,view(parm0)} - - - FunctionTypeBits.NumParams - (clang::QualType *)(this+1) - - - - *(clang::Type *)this, view(cmn) - - - - - {OriginalTy} adjusted to {AdjustedTy} - - OriginalTy - AdjustedTy - - - - {OriginalTy,view(left)} - {OriginalTy,view(right)} - {OriginalTy} - - (clang::AdjustedType *)this - - - - {NamedType,view(left)} - {NamedType,view(right)} - {NamedType} - - (clang::ElaboratedTypeKeyword)TypeWithKeywordBits.Keyword - NNS - NamedType,view(cmn) - - - - {TTPDecl->Name,view(cpp)} - Non-canonical: {*TTPDecl} - Canonical: {CanTTPTInfo} - - *(clang::Type *)this, view(cmn) - - - - {Decl,view(cpp)} - - Decl - InjectedType - *(clang::Type *)this, view(cmn) - - - - {NNS}{Name,view(cpp)na} - - NNS - Name - *(clang::Type *)this, view(cmn) - - - - - {(IdentifierInfo*)Specifier,view(cpp)na}:: - {(NamedDecl*)Specifier,view(cpp)na}:: - {(Type*)Specifier,view(cpp)na}:: - - (NestedNameSpecifier::StoredSpecifierKind)((*(uintptr_t *)Prefix.Value.Data>>1)&3) - - - - {Pattern} - - Pattern - NumExpansions - *(clang::Type *)this, view(cmn) - - - - {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,view(poly)}{*this,view(fastQuals)} - {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,view(cpp)}{*this,view(fastQuals)} - {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,view(left)}{*this,view(fastQuals)} - {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,view(right)}{*this,view(fastQuals)} - - - {" ",sb}const - {" ",sb}restrict - {" ",sb}const restrict - {" ",sb}volatile - {" ",sb}const volatile - {" ",sb}volatile restrict - {" ",sb}const volatile restrict - Cannot visualize non-fast qualifiers - Null - {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,na}{*this,view(fastQuals)} - - *this,view(fastQuals) - ((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType - - - - - {DeclInfo,view(cpp)na} - {DeclInfo,na} - - DeclInfo - *(clang::Type *)this, view(cmn) - - - - {Ty,view(cpp)} - {Ty} - - Ty - - - - {(QualType *)&Ty,na} - - (QualType *)&Ty - Data - - - - Not building anything - Building a {LastTy} - - - {Argument,view(cpp)} - {Argument} - - - {*(clang::QualType *)&TypeOrValue.V,view(cpp)} - {(clang::TemplateArgument::ArgKind)TypeOrValue.Kind,en} template argument: {*(clang::QualType *)&TypeOrValue.V} - - {Args.Args[0]}{*this,view(arg1)} - - , {Args.Args[1]}{*this,view(arg2)} - - , {Args.Args[2]}, ... - - {Args.Args[0],view(cpp)}{*this,view(arg1cpp)} - - , {Args.Args[1],view(cpp)}{*this,view(arg2cpp)} - - , {Args.Args[2],view(cpp)}, ... - {*this,view(arg0cpp)} - {*this,view(arg0)} - {(clang::Expr *)TypeOrValue.V,view(cpp)na} - {(clang::TemplateArgument::ArgKind)TypeOrValue.Kind,en} - - *(clang::QualType *)&TypeOrValue.V - (clang::Expr *)TypeOrValue.V - - Args.NumArgs - Args.Args - - - - - - - {((TemplateArgumentLoc*)Arguments.BeginX)[0],view(cpp)}{*this,view(elt1)} - - , {((TemplateArgumentLoc*)Arguments.BeginX)[1],view(cpp)}{*this,view(elt2)} - - , {((TemplateArgumentLoc*)Arguments.BeginX)[2],view(cpp)}{*this,view(elt3)} - - , {((TemplateArgumentLoc*)Arguments.BeginX)[3],view(cpp)}{*this,view(elt4)} - - , ... - empty - <{*this,view(elt0)}> - Uninitialized - - - - {Arguments[0],view(cpp)}{*this,view(arg1)} - - , {Arguments[1],view(cpp)}{*this,view(arg2)} - - , {Arguments[1],view(cpp)}, ... - <{*this,view(arg0)}> - - NumArguments - - NumArguments - Arguments - - - - - - {Data[0],view(cpp)}{*this,view(arg1)} - - , {Data[1],view(cpp)}{*this,view(arg2)} - - , {Data[2],view(cpp)}, ... - <{*this,view(arg0)}> - - Length - - - - Length - Data - - - - - - - - {((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[0],view(cpp)}{*this,view(level1)} - - ::{((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[1],view(cpp)}{*this,view(level2)} - - ::{((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[2],view(cpp)}, ... - {*this,view(level0)} - - TemplateArgumentLists - - - - {(clang::QualType *)Arg,view(cpp)na} - Type template argument: {*(clang::QualType *)Arg} - Non-type template argument: {*(clang::Expr *)Arg} - Template template argument: {*(clang::TemplateName *)Arg - - Kind,en - (clang::QualType *)Arg - (clang::Expr *)Arg - (clang::TemplateName *)Arg - - - - - void - bool - char - unsigned char - wchar_t - char16_t - char32_t - unsigned short - unsigned int - unsigned long - unsigned long long - __uint128_t - char - signed char - wchar_t - short - int - long - long long - __int128_t - __fp16 - float - double - long double - nullptr_t - {(clang::BuiltinType::Kind)BuiltinTypeBits.Kind, en} - - (clang::BuiltinType::Kind)BuiltinTypeBits.Kind - - - - - - {((clang::TemplateArgument *)(this+1))[0],view(cpp)}{*this,view(arg1)} - - , {((clang::TemplateArgument *)(this+1))[1],view(cpp)}{*this,view(arg2)} - - , {((clang::TemplateArgument *)(this+1))[2],view(cpp)}{*this,view(arg3)} - - {*((clang::TemplateDecl *)(Template.Storage.Val.Value))->TemplatedDecl,view(cpp)}<{*this,view(arg0)}> - - Can't visualize this TemplateSpecializationType - - Template.Storage - - TemplateSpecializationTypeBits.NumArgs - (clang::TemplateArgument *)(this+1) - - *(clang::Type *)this, view(cmn) - - - - - (CanonicalType.Value.Value != this) || TypeBits.Dependent - *(clang::Type *)this,view(cmn) - - - - {CanonicalType,view(cpp)} - {Template,view(cpp)} - {Template} - - Template - CanonicalType,view(cpp) - (clang::DeducedType *)this - Template - - - - {*(CXXRecordDecl *)this,nd}{*TemplateArgs} - - (CXXRecordDecl *)this,nd - TemplateArgs - - - - {((llvm::StringMapEntry<clang::IdentifierInfo *>*)Entry)+1,sb} - - ((llvm::StringMapEntry<clang::IdentifierInfo *>*)Entry)+1,s - (clang::tok::TokenKind)TokenID - - - - - Empty - {*(clang::IdentifierInfo *)(Ptr & ~PtrMask)} - {{Identifier ({*(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}} - {{ObjC Zero Arg Selector (*{(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}} - {{ObjC One Arg Selector (*{(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}} - {(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),view(cpp)na} - C++ Constructor {{{(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),view(cpp)na}}} - C++ Destructor {{*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask)}} - C++ Conversion function {{*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask)}} - C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr & ~PtrMask)}} - {*(clang::detail::DeclarationNameExtra *)(Ptr & ~PtrMask),view(cpp)} - {{Extra ({*(clang::detail::DeclarationNameExtra *)(Ptr & ~PtrMask)})}} - - StoredNameKind(Ptr & PtrMask),en - *(clang::IdentifierInfo *)(Ptr & ~PtrMask),na - *(clang::IdentifierInfo *)(Ptr & ~PtrMask),na - *(clang::IdentifierInfo *)(Ptr & ~PtrMask),na - *(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na - *(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na - *(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na - *(clang::detail::CXXOperatorIdName *)(Ptr & ~PtrMask),na - (clang::detail::DeclarationNameExtra *)(Ptr & ~PtrMask),na - - - - - {(CXXDeductionGuideNameExtra *)this,view(cpp)nand} - - - {(CXXDeductionGuideNameExtra *)this,nand} - - C++ Literal operator - C++ Using directive - Objective-C MultiArg selector - {(clang::detail::DeclarationNameExtra::ExtraKind)ExtraKindOrNumArgs,en}{" ",sb}{*this,view(cpp)} - - (CXXDeductionGuideNameExtra *)this - ExtraKindOrNumArgs - - - - {Template->TemplatedDecl,view(cpp)} - C++ Deduction guide for {Template->TemplatedDecl,view(cpp)na} - - - {Type,view(cpp)} - {Type} - - - {Name} - - - - {(ParsedTemplateArgument *)(this+1),view(cpp)na}{this,view(arg1)na} - - , {((ParsedTemplateArgument *)(this+1))+1,view(cpp)na}{this,view(arg2)na} - - , ... - {Name,na}<{this,view(arg0)na}> - - Name - - {this,view(arg0)na} - - - NumArgs - (ParsedTemplateArgument *)(this+1) - - - - Operator - - - - {{annot_template_id ({(clang::TemplateIdAnnotation *)(PtrData),na})}} - {{Identifier ({(clang::IdentifierInfo *)(PtrData),na})}} - {(clang::tok::TokenKind)Kind,en} - - - {BufferPtr,nasb} - - - {TheLexer._Mypair._Myval2,na} - Expanding Macro: {TheTokenLexer._Mypair._Myval2,na} - - - - - [{(Token *)(CachedTokens.BeginX) + CachedLexPos,na}] {IncludeMacroStack._Mypair._Myval2._Mylast - 1,na} - - {IncludeMacroStack._Mypair._Myval2._Mylast - 1,na} - {CurLexer._Mypair._Myval2,na} - Expanding Macro: {CurTokenLexer._Mypair._Myval2,na} - - - {this,view(cached)} - - CLK_LexAfterModuleImport - - - [{Tok}] {PP,na} - - - this - *this - {Id} - &{Id} - No visualizer for {Kind} - - - - =, - &, - - {(LambdaCapture *)(Captures.BeginX),na}{this,view(capture1)na} - - ,{(LambdaCapture *)(Captures.BeginX)+1,na}{this,view(capture2)na} - - ,{(LambdaCapture *)(Captures.BeginX)+2,na}{this,view(capture3)na} - - ,... - [{this,view(default)na}{this,view(capture0)na}] - - - - , [{TypeRep}] - - - , [{ExprRep}] - - - , [{DeclRep}] - - - [{(clang::DeclSpec::SCS)StorageClassSpec,en}], [{(clang::TypeSpecifierType)TypeSpecType,en}]{this,view(extra)na} - - (clang::DeclSpec::SCS)StorageClassSpec - (clang::TypeSpecifierType)TypeSpecType - - TypeRep - - - ExprRep - - - DeclRep - - - - - - {Name,s} - - - {RealPathName,s} - - - {Name,s} - - - - (clang::StorageClass)SClass - (clang::ThreadStorageClassSpecifier)TSCSpec - (clang::VarDecl::InitializationStyle)InitStyle - - - - {DeclType,view(left)} {Name,view(cpp)}{DeclType,view(right)} - - Name - DeclType - - - - {(DeclaratorDecl*)this,nand} - - (DeclaratorDecl*)this,nd - Init - VarDeclBits - - - - {*(VarDecl*)this,nd} - - ParmVarDeclBits - *(VarDecl*)this,nd - - - - {"explicit ",sb} - - explicit({ExplicitSpec,view(ptr)na}) - {ExplicitSpec,view(int)en} - {ExplicitSpec,view(int)en} : {ExplicitSpec,view(ptr)na} - - - {ExplicitSpec,view(cpp)}{Name,view(cpp)nd}({(FunctionDecl*)this,view(parm0)nand}) -> {((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->ResultType,view(cpp)} - - ExplicitSpec - (bool)FunctionDeclBits.IsCopyDeductionCandidate - (FunctionDecl*)this,nd - - - - {((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)DeclType.Value.Value.Data) & ~15))->BaseType)->ResultType,view(cpp)} - - {ParamInfo[0],na}{*this,view(parm1)nd} - - , {ParamInfo[1],na}{*this,view(parm2)nd} - - , {ParamInfo[2],na}{*this,view(parm3)nd} - - , {ParamInfo[3],na}{*this,view(parm4)nd} - - , {ParamInfo[4],na}{*this,view(parm5)nd} - - , /* expand for more params */ - - auto {Name,view(cpp)nd}({*this,view(parm0)nd}) -> {((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)DeclType.Value.Value.Data) & ~15))->BaseType)->ResultType,view(cpp)} - - {this,view(retType)nand} {Name,view(cpp)nd}({*this,view(parm0)nd}) - - (clang::DeclaratorDecl *)this,nd - ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)DeclType.Value.Value.Data) & ~15))->BaseType)->ResultType - - {*this,view(parm0)nd} - - - ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)DeclType.Value.Value.Data) & ~15))->BaseType)->FunctionTypeBits.NumParams - ParamInfo - - - - TemplateOrSpecialization - - - - {*($T1*)&Ptr} - - ($T1*)&Ptr - - - - {($T1 *)Ptr} - - ($T1 *)Ptr - - - - - {*((NamedDecl **)(this+1))[0],view(cpp)}{*this,view(parm1)} - - , {*((NamedDecl **)(this+1))[1],view(cpp)}{*this,view(parm2)} - - , {*((NamedDecl **)(this+1))[2],view(cpp)}{*this,view(parm3)} - - , {*((NamedDecl **)(this+1))[3],view(cpp)}{*this,view(parm4)} - - , {*((NamedDecl **)(this+1))[4],view(cpp)}{*this,view(parm5)} - - , /* Expand for more params */ - <{*this,view(parm0)}> - - - NumParams - (NamedDecl **)(this+1) - - - - - {(clang::Stmt::StmtClass)StmtBits.sClass,en} - - (clang::Stmt::StmtClass)StmtBits.sClass,en - - - - {*(clang::StringLiteral *)this} - Expression of class {(clang::Stmt::StmtClass)StmtBits.sClass,en} and type {TR,view(cpp)} - - - - *(unsigned *)(((clang::StringLiteral *)this)+1) - (const char *)(((clang::StringLiteral *)this)+1)+4+4,[*(unsigned *)(((clang::StringLiteral *)this)+1)]s8 - - - - public - protected - private - - {*(clang::NamedDecl *)(Ptr&~Mask)} - {*this,view(access)} {*this,view(decl)} - - (clang::AccessSpecifier)(Ptr&Mask),en - *(clang::NamedDecl *)(Ptr&~Mask) - - - - [IK_Identifier] {*Identifier} - [IK_OperatorFunctionId] {OperatorFunctionId} - [IK_ConversionFunctionId] {ConversionFunctionId} - [IK_ConstructorName] {ConstructorName} - [IK_DestructorName] {DestructorName} - [IK_DeductionGuideName] {TemplateName} - [IK_TemplateId] {TemplateId} - [IK_ConstructorTemplateId] {TemplateId} - Kind - - Identifier - OperatorFunctionId - ConversionFunctionId - ConstructorName - DestructorName - TemplateName - TemplateId - TemplateId - - - - NumDecls={NumDecls} - - - NumDecls - (Decl **)(this+1) - - - - - {*D} - {*(DeclGroup *)((uintptr_t)D&~1)} - - D - (DeclGroup *)((uintptr_t)D&~1) - - - - {DS} {Name} - - - {Decls} - - Decls - - - - {Ambiguity,en}: {Decls} - {ResultKind,en}: {Decls} - - - Invalid - Unset - {Val} - - - Invalid - Unset - {($T1)(Value&~1)} - - (bool)(Value&1) - ($T1)(Value&~1) - - - + + + + + + + LocInfoType + {(clang::Type::TypeClass)TypeBits.TC, en}Type + + {*(clang::BuiltinType *)this} + {*(clang::PointerType *)this} + {*(clang::ParenType *)this} + {(clang::BitIntType *)this} + {*(clang::LValueReferenceType *)this} + {*(clang::RValueReferenceType *)this} + {(clang::ConstantArrayType *)this,na} + {(clang::ConstantArrayType *)this,view(left)na} + {(clang::ConstantArrayType *)this,view(right)na} + {(clang::VariableArrayType *)this,na} + {(clang::VariableArrayType *)this,view(left)na} + {(clang::VariableArrayType *)this,view(right)na} + {(clang::IncompleteArrayType *)this,na} + {(clang::IncompleteArrayType *)this,view(left)na} + {(clang::IncompleteArrayType *)this,view(right)na} + {(clang::TypedefType *)this,na} + {(clang::TypedefType *)this,view(cpp)na} + {*(clang::AttributedType *)this} + {(clang::DecayedType *)this,na} + {(clang::DecayedType *)this,view(left)na} + {(clang::DecayedType *)this,view(right)na} + {(clang::ElaboratedType *)this,na} + {(clang::ElaboratedType *)this,view(left)na} + {(clang::ElaboratedType *)this,view(right)na} + {*(clang::TemplateTypeParmType *)this} + {*(clang::TemplateTypeParmType *)this,view(cpp)} + {*(clang::SubstTemplateTypeParmType *)this} + {*(clang::RecordType *)this} + {*(clang::RecordType *)this,view(cpp)} + {(clang::FunctionProtoType *)this,na} + {(clang::FunctionProtoType *)this,view(left)na} + {(clang::FunctionProtoType *)this,view(right)na} + {*(clang::TemplateSpecializationType *)this} + {*(clang::DeducedTemplateSpecializationType *)this} + {*(clang::DeducedTemplateSpecializationType *)this,view(cpp)} + {*(clang::InjectedClassNameType *)this} + {*(clang::DependentNameType *)this} + {*(clang::PackExpansionType *)this} + {(clang::LocInfoType *)this,na} + {(clang::LocInfoType *)this,view(cpp)na} + {this,view(poly)na} + {*this,view(cpp)} + + No visualizer yet for {(clang::Type::TypeClass)TypeBits.TC,en}Type + Dependence{" ",en} + + CachedLinkage: {(clang::Linkage)TypeBits.CachedLinkage,en} CachedLocalOrUnnamed + CachedLinkage: {(clang::Linkage)TypeBits.CachedLinkage,en}{" ",sb} + + FromAST + + + No TypeBits set beyond TypeClass + + {*this, view(Dependence)}{*this, view(Cache)}{*this, view(FromAST)} + {*this,view(cmn)} {{{*this,view(poly)}}} + + (clang::Type::TypeClass)TypeBits.TC + this,view(flags)na + CanonicalType + *(clang::BuiltinType *)this + *(clang::PointerType *)this + *(clang::ParenType*)this + *(clang::BitIntType*)this + *(clang::LValueReferenceType *)this + *(clang::RValueReferenceType *)this + (clang::ConstantArrayType *)this + (clang::VariableArrayType *)this + (clang::IncompleteArrayType *)this + *(clang::AttributedType *)this + (clang::DecayedType *)this + (clang::ElaboratedType *)this + (clang::TemplateTypeParmType *)this + (clang::SubstTemplateTypeParmType *)this + (clang::RecordType *)this + (clang::FunctionProtoType *)this + (clang::TemplateSpecializationType *)this + (clang::DeducedTemplateSpecializationType *)this + (clang::InjectedClassNameType *)this + (clang::DependentNameType *)this + (clang::PackExpansionType *)this + (clang::LocInfoType *)this + + + + + ElementType + + + + {ElementType,view(cpp)} + [{Size}] + {ElementType,view(cpp)}[{Size}] + + Size + (clang::ArrayType *)this + + + + {ElementType,view(cpp)} + [] + {ElementType,view(cpp)}[] + + (clang::ArrayType *)this + + + + {ElementType,view(cpp)} + [*] + {ElementType,view(cpp)}[*] + + (clang::Expr *)SizeExpr + (clang::ArrayType *)this + + + + {Decl,view(name)nd} + {Decl} + + Decl + *(clang::Type *)this, view(cmn) + + + + {PointeeType, view(cpp)} * + + PointeeType + *(clang::Type *)this, view(cmn) + + + + {Inner, view(cpp)} + + Inner + *(clang::Type *)this, view(cmn) + + + + signed _BitInt({NumBits}) + unsigned _BitInt({NumBits})( + + NumBits + (clang::Type *)this, view(cmn) + + + + + {((clang::ReferenceType *)this)->PointeeType,view(cpp)} & + + *(clang::Type *)this, view(cmn) + PointeeType + + + + {((clang::ReferenceType *)this)->PointeeType,view(cpp)} && + + *(clang::Type *)this, view(cmn) + PointeeType + + + + {ModifiedType} Attribute={(clang::AttributedType::Kind)AttributedTypeBits.AttrKind} + + + + + {(clang::Decl::Kind)DeclContextBits.DeclKind,en}Decl + + (clang::Decl::Kind)DeclContextBits.DeclKind,en + + + + + FirstDecl + (clang::Decl *)(*(intptr_t *)NextInContextAndBits.Value.Data & ~3) + *this + + + + + + + Field {{{*(clang::DeclaratorDecl *)this,view(cpp)nd}}} + + + {*(clang::FunctionDecl *)this,nd} + Method {{{*this,view(cpp)}}} + + + Constructor {{{Name,view(cpp)}({*(clang::FunctionDecl *)this,view(parm0)nd})}} + + + Destructor {{~{Name,view(cpp)}()}} + + + typename + class + (not yet known if parameter pack) + ... + + {(TypeSourceInfo *)(*(uintptr_t *)DefaultArgument.ValueOrInherited.Val.Value.Data&~3LL),view(cpp)} + {{InheritedInitializer}} + = {this,view(DefaultArg)na} + + {*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)} {this,view(Initializer)na} + + + {*TemplatedDecl,view(cpp)} + template{TemplateParams,na} {*TemplatedDecl}; + + TemplateParams,na + TemplatedDecl,na + + + + + {(clang::TypeSourceInfo *)(*(uintptr_t *)MaybeModedTInfo.Value.Data & ~7LL),view(cpp)na} + {(clang::TypedefNameDecl::ModedTInfo *)(*(uintptr_t *)MaybeModedTInfo.Value.Data & ~7LL),view(cpp)na} + {(TypeDecl *)this,view(cpp)nand} + typedef {this,view(type)na} {this,view(name)na}; + + "Not yet calculated",sb + (bool)(*(uintptr_t *)MaybeModedTInfo.Value.Data & 2) + (clang::TypeSourceInfo *)(*(uintptr_t *)MaybeModedTInfo.Value.Data & ~7LL) + (clang::TypedefNameDecl::ModedTInfo *)(*(uintptr_t *)MaybeModedTInfo.Value.Data & ~7LL) + (TypeDecl *)this,nd + + + + {(TypedefNameDecl *)this,view(name)nand} + using {(TypedefNameDecl *)this,view(name)nand} = {(TypedefNameDecl *)this,view(type)nand} + + + {Name} + + + Kind={(UncommonTemplateNameStorage::Kind)Kind,en}, Size={Size} + + (UncommonTemplateNameStorage::Kind)Kind + Size + + + + {Bits}, + {this,view(cmn)na},{(OverloadedTemplateStorage*)this,na} + {this,view(cmn)na},{(AssumedTemplateStorage*)this,na} + {this,view(cmn)na},{(SubstTemplateTemplateParmStorage*)this,na} + {this,view(cmn)na},{(SubstTemplateTemplateParmPackStorage*)this,na} + {this,view(cmn)na} + + Bits + (OverloadedTemplateStorage*)this + (AssumedTemplateStorage*)this + (SubstTemplateTemplateParmStorage*)this + (SubstTemplateTemplateParmPackStorage*)this + + + + + + + {(clang::TemplateDecl *)(Val.Value & ~3LL),view(cpp)na} + + + {(clang::TemplateDecl *)(Val.Value & ~3LL),na} + + + {(clang::UncommonTemplateNameStorage *)(Val.Value & ~3LL),view(cpp)na} + + + {(clang::UncommonTemplateNameStorage *)(Val.Value & ~3LL),na} + + + {(clang::QualifiedTemplateName *)(Val.Value & ~3LL),view(cpp)na} + + + {(clang::QualifiedTemplateName *)(Val.Value & ~3LL),na} + + + {(clang::DependentTemplateName *)(Val.Value & ~3LL),view(cpp)na} + + + {(clang::DependentTemplateName *)(Val.Value & ~3LL),na} + + + "TemplateDecl",s8b + + (clang::TemplateDecl *)(Val.Value & ~3LL) + + "UncommonTemplateNameStorage",s8b + + (clang::UncommonTemplateNameStorage *)(Val.Value & ~3LL) + + "QualifiedTemplateName",s8b + + (clang::QualifiedTemplateName *)(Val.Value & ~3LL) + + "DependentTemplateName",s8b + + (clang::DependentTemplateName *)(Val.Value & ~3LL) + + Val + + + + + {Storage,view(cpp)na} + {Storage,na} + + Storage + + + + {Name,view(cpp)} + {Name} + + + implicit{" ",sb} + + {*this,view(implicit)nd} + {*this,view(modifiers)}{Name,view(cpp)} + {*this,view(modifiers)nd}struct {Name,view(cpp)} + {*this,view(modifiers)nd}interface {Name,view(cpp)} + {*this,view(modifiers)nd}union {Name,view(cpp)} + {*this,view(modifiers)nd}class {Name,view(cpp)} + {*this,view(modifiers)nd}enum {Name,view(cpp)} + + (clang::DeclContext *)this + + + + {decl,view(cpp)na} + {*decl} + + *(clang::Type *)this, view(cmn) + decl + + + + {(clang::TagType *)this,view(cpp)na} + {(clang::TagType *)this,na} + + *(clang::TagType *)this + + + + {{{*Replaced,view(cpp)} <= {CanonicalType,view(cpp)}}} + + *(clang::Type *)this, view(cmn) + *Replaced + + + + + + {ResultType,view(cpp)} + + {*(clang::QualType *)(this+1),view(cpp)}{*this,view(parm1)} + + , {*((clang::QualType *)(this+1)+1),view(cpp)}{*this,view(parm2)} + + , {*((clang::QualType *)(this+1)+2),view(cpp)}{*this,view(parm3)} + + , {*((clang::QualType *)(this+1)+3),view(cpp)}{*this,view(parm4)} + + , {*((clang::QualType *)(this+1)+4),view(cpp)}{*this,view(parm5)} + + , /* expand for more params */ + ({*this,view(parm0)}) -> {ResultType,view(cpp)} + ({*this,view(parm0)}) + {this,view(left)na}{this,view(right)na} + + ResultType + + {*this,view(parm0)} + + + FunctionTypeBits.NumParams + (clang::QualType *)(this+1) + + + + *(clang::Type *)this, view(cmn) + + + + + {OriginalTy} adjusted to {AdjustedTy} + + OriginalTy + AdjustedTy + + + + {OriginalTy,view(left)} + {OriginalTy,view(right)} + {OriginalTy} + + (clang::AdjustedType *)this + + + + {NamedType,view(left)} + {NamedType,view(right)} + {NamedType} + + (clang::ElaboratedTypeKeyword)TypeWithKeywordBits.Keyword + NNS + NamedType,view(cmn) + + + + {TTPDecl->Name,view(cpp)} + Non-canonical: {*TTPDecl} + Canonical: {CanTTPTInfo} + + *(clang::Type *)this, view(cmn) + + + + {Decl,view(cpp)} + + Decl + InjectedType + *(clang::Type *)this, view(cmn) + + + + {NNS}{Name,view(cpp)na} + + NNS + Name + *(clang::Type *)this, view(cmn) + + + + + {(IdentifierInfo*)Specifier,view(cpp)na}:: + {(NamedDecl*)Specifier,view(cpp)na}:: + {(Type*)Specifier,view(cpp)na}:: + + (NestedNameSpecifier::StoredSpecifierKind)((*(uintptr_t *)Prefix.Value.Data>>1)&3) + + + + {Pattern} + + Pattern + NumExpansions + *(clang::Type *)this, view(cmn) + + + + {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,view(poly)}{*this,view(fastQuals)} + {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,view(cpp)}{*this,view(fastQuals)} + {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,view(left)}{*this,view(fastQuals)} + {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,view(right)}{*this,view(fastQuals)} + + + {" ",sb}const + {" ",sb}restrict + {" ",sb}const restrict + {" ",sb}volatile + {" ",sb}const volatile + {" ",sb}volatile restrict + {" ",sb}const volatile restrict + Cannot visualize non-fast qualifiers + Null + {((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType,na}{*this,view(fastQuals)} + + *this,view(fastQuals) + ((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)Value.Value.Data) & ~(uintptr_t)((1U << clang::TypeAlignmentInBits) - 1U)))->BaseType + + + + + {DeclInfo,view(cpp)na} + {DeclInfo,na} + + DeclInfo + *(clang::Type *)this, view(cmn) + + + + {Ty,view(cpp)} + {Ty} + + Ty + + + + {(QualType *)&Ty,na} + + (QualType *)&Ty + Data + + + + Not building anything + Building a {LastTy} + + + {Argument,view(cpp)} + {Argument} + + + {*(clang::QualType *)&TypeOrValue.V,view(cpp)} + {(clang::TemplateArgument::ArgKind)TypeOrValue.Kind,en} template argument: {*(clang::QualType *)&TypeOrValue.V} + + {Args.Args[0]}{*this,view(arg1)} + + , {Args.Args[1]}{*this,view(arg2)} + + , {Args.Args[2]}, ... + + {Args.Args[0],view(cpp)}{*this,view(arg1cpp)} + + , {Args.Args[1],view(cpp)}{*this,view(arg2cpp)} + + , {Args.Args[2],view(cpp)}, ... + {*this,view(arg0cpp)} + {*this,view(arg0)} + {(clang::Expr *)TypeOrValue.V,view(cpp)na} + {(clang::TemplateArgument::ArgKind)TypeOrValue.Kind,en} + + *(clang::QualType *)&TypeOrValue.V + (clang::Expr *)TypeOrValue.V + + Args.NumArgs + Args.Args + + + + + + + {((TemplateArgumentLoc*)Arguments.BeginX)[0],view(cpp)}{*this,view(elt1)} + + , {((TemplateArgumentLoc*)Arguments.BeginX)[1],view(cpp)}{*this,view(elt2)} + + , {((TemplateArgumentLoc*)Arguments.BeginX)[2],view(cpp)}{*this,view(elt3)} + + , {((TemplateArgumentLoc*)Arguments.BeginX)[3],view(cpp)}{*this,view(elt4)} + + , ... + empty + <{*this,view(elt0)}> + Uninitialized + + + + {Arguments[0],view(cpp)}{*this,view(arg1)} + + , {Arguments[1],view(cpp)}{*this,view(arg2)} + + , {Arguments[1],view(cpp)}, ... + <{*this,view(arg0)}> + + NumArguments + + NumArguments + Arguments + + + + + + {Data[0],view(cpp)}{*this,view(arg1)} + + , {Data[1],view(cpp)}{*this,view(arg2)} + + , {Data[2],view(cpp)}, ... + <{*this,view(arg0)}> + + Length + + + + Length + Data + + + + + + + + {((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[0],view(cpp)}{*this,view(level1)} + + ::{((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[1],view(cpp)}{*this,view(level2)} + + ::{((llvm::ArrayRef<clang::TemplateArgument> *)TemplateArgumentLists.BeginX)[2],view(cpp)}, ... + {*this,view(level0)} + + TemplateArgumentLists + + + + {(clang::QualType *)Arg,view(cpp)na} + Type template argument: {*(clang::QualType *)Arg} + Non-type template argument: {*(clang::Expr *)Arg} + Template template argument: {*(clang::TemplateName *)Arg + + Kind,en + (clang::QualType *)Arg + (clang::Expr *)Arg + (clang::TemplateName *)Arg + + + + + void + bool + char + unsigned char + wchar_t + char16_t + char32_t + unsigned short + unsigned int + unsigned long + unsigned long long + __uint128_t + char + signed char + wchar_t + short + int + long + long long + __int128_t + __fp16 + float + double + long double + nullptr_t + {(clang::BuiltinType::Kind)BuiltinTypeBits.Kind, en} + + (clang::BuiltinType::Kind)BuiltinTypeBits.Kind + + + + + + {((clang::TemplateArgument *)(this+1))[0],view(cpp)}{*this,view(arg1)} + + , {((clang::TemplateArgument *)(this+1))[1],view(cpp)}{*this,view(arg2)} + + , {((clang::TemplateArgument *)(this+1))[2],view(cpp)}{*this,view(arg3)} + + {*((clang::TemplateDecl *)(Template.Storage.Val.Value))->TemplatedDecl,view(cpp)}<{*this,view(arg0)}> + + Can't visualize this TemplateSpecializationType + + Template.Storage + + TemplateSpecializationTypeBits.NumArgs + (clang::TemplateArgument *)(this+1) + + *(clang::Type *)this, view(cmn) + + + + + (CanonicalType.Value.Value != this) || TypeBits.Dependent + *(clang::Type *)this,view(cmn) + + + + {CanonicalType,view(cpp)} + {Template,view(cpp)} + {Template} + + Template + CanonicalType,view(cpp) + (clang::DeducedType *)this + Template + + + + {*(CXXRecordDecl *)this,nd}{*TemplateArgs} + + (CXXRecordDecl *)this,nd + TemplateArgs + + + + {((llvm::StringMapEntry<clang::IdentifierInfo *>*)Entry)+1,sb} + + ((llvm::StringMapEntry<clang::IdentifierInfo *>*)Entry)+1,s + (clang::tok::TokenKind)TokenID + + + + + Empty + {*(clang::IdentifierInfo *)(Ptr & ~PtrMask)} + {{Identifier ({*(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}} + {{ObjC Zero Arg Selector (*{(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}} + {{ObjC One Arg Selector (*{(clang::IdentifierInfo *)(Ptr & ~PtrMask)})}} + {(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),view(cpp)na} + C++ Constructor {{{(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),view(cpp)na}}} + C++ Destructor {{*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask)}} + C++ Conversion function {{*(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask)}} + C++ Operator {{*(clang::detail::CXXOperatorIdName *)(Ptr & ~PtrMask)}} + {*(clang::detail::DeclarationNameExtra *)(Ptr & ~PtrMask),view(cpp)} + {{Extra ({*(clang::detail::DeclarationNameExtra *)(Ptr & ~PtrMask)})}} + + StoredNameKind(Ptr & PtrMask),en + *(clang::IdentifierInfo *)(Ptr & ~PtrMask),na + *(clang::IdentifierInfo *)(Ptr & ~PtrMask),na + *(clang::IdentifierInfo *)(Ptr & ~PtrMask),na + *(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na + *(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na + *(clang::detail::CXXSpecialNameExtra *)(Ptr & ~PtrMask),na + *(clang::detail::CXXOperatorIdName *)(Ptr & ~PtrMask),na + (clang::detail::DeclarationNameExtra *)(Ptr & ~PtrMask),na + + + + + {(CXXDeductionGuideNameExtra *)this,view(cpp)nand} + + + {(CXXDeductionGuideNameExtra *)this,nand} + + C++ Literal operator + C++ Using directive + Objective-C MultiArg selector + {(clang::detail::DeclarationNameExtra::ExtraKind)ExtraKindOrNumArgs,en}{" ",sb}{*this,view(cpp)} + + (CXXDeductionGuideNameExtra *)this + ExtraKindOrNumArgs + + + + {Template->TemplatedDecl,view(cpp)} + C++ Deduction guide for {Template->TemplatedDecl,view(cpp)na} + + + {Type,view(cpp)} + {Type} + + + {Name} + + + + {(ParsedTemplateArgument *)(this+1),view(cpp)na}{this,view(arg1)na} + + , {((ParsedTemplateArgument *)(this+1))+1,view(cpp)na}{this,view(arg2)na} + + , ... + {Name,na}<{this,view(arg0)na}> + + Name + + {this,view(arg0)na} + + + NumArgs + (ParsedTemplateArgument *)(this+1) + + + + Operator + + + + {{annot_template_id ({(clang::TemplateIdAnnotation *)(PtrData),na})}} + {{Identifier ({(clang::IdentifierInfo *)(PtrData),na})}} + {(clang::tok::TokenKind)Kind,en} + + + {BufferPtr,nasb} + + + {TheLexer._Mypair._Myval2,na} + Expanding Macro: {TheTokenLexer._Mypair._Myval2,na} + + + + + [{(Token *)(CachedTokens.BeginX) + CachedLexPos,na}] {IncludeMacroStack._Mypair._Myval2._Mylast - 1,na} + + {IncludeMacroStack._Mypair._Myval2._Mylast - 1,na} + {CurLexer._Mypair._Myval2,na} + Expanding Macro: {CurTokenLexer._Mypair._Myval2,na} + + + {this,view(cached)} + + CLK_LexAfterModuleImport + + + [{Tok}] {PP,na} + + + this + *this + {Id} + &{Id} + No visualizer for {Kind} + + + + =, + &, + + {(LambdaCapture *)(Captures.BeginX),na}{this,view(capture1)na} + + ,{(LambdaCapture *)(Captures.BeginX)+1,na}{this,view(capture2)na} + + ,{(LambdaCapture *)(Captures.BeginX)+2,na}{this,view(capture3)na} + + ,... + [{this,view(default)na}{this,view(capture0)na}] + + + + , [{TypeRep}] + + + , [{ExprRep}] + + + , [{DeclRep}] + + + [{(clang::DeclSpec::SCS)StorageClassSpec,en}], [{(clang::TypeSpecifierType)TypeSpecType,en}]{this,view(extra)na} + + (clang::DeclSpec::SCS)StorageClassSpec + (clang::TypeSpecifierType)TypeSpecType + + TypeRep + + + ExprRep + + + DeclRep + + + + + + {Name,s} + + + {RealPathName,s} + + + {Name,s} + + + + (clang::StorageClass)SClass + (clang::ThreadStorageClassSpecifier)TSCSpec + (clang::VarDecl::InitializationStyle)InitStyle + + + + {DeclType,view(left)} {Name,view(cpp)}{DeclType,view(right)} + + Name + DeclType + + + + {(DeclaratorDecl*)this,nand} + + (DeclaratorDecl*)this,nd + Init + VarDeclBits + + + + {*(VarDecl*)this,nd} + + ParmVarDeclBits + *(VarDecl*)this,nd + + + + {"explicit ",sb} + + explicit({ExplicitSpec,view(ptr)na}) + {ExplicitSpec,view(int)en} + {ExplicitSpec,view(int)en} : {ExplicitSpec,view(ptr)na} + + + {ExplicitSpec,view(cpp)}{Name,view(cpp)nd}({(FunctionDecl*)this,view(parm0)nand}) -> {((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->ResultType,view(cpp)} + + ExplicitSpec + (bool)FunctionDeclBits.IsCopyDeductionCandidate + (FunctionDecl*)this,nd + + + + {((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)DeclType.Value.Value.Data) & ~15))->BaseType)->ResultType,view(cpp)} + + {ParamInfo[0],na}{*this,view(parm1)nd} + + , {ParamInfo[1],na}{*this,view(parm2)nd} + + , {ParamInfo[2],na}{*this,view(parm3)nd} + + , {ParamInfo[3],na}{*this,view(parm4)nd} + + , {ParamInfo[4],na}{*this,view(parm5)nd} + + , /* expand for more params */ + + auto {Name,view(cpp)nd}({*this,view(parm0)nd}) -> {((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)DeclType.Value.Value.Data) & ~15))->BaseType)->ResultType,view(cpp)} + + {this,view(retType)nand} {Name,view(cpp)nd}({*this,view(parm0)nd}) + + (clang::DeclaratorDecl *)this,nd + ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)DeclType.Value.Value.Data) & ~15))->BaseType)->ResultType + + {*this,view(parm0)nd} + + + ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)((*(uintptr_t *)DeclType.Value.Value.Data) & ~15))->BaseType)->FunctionTypeBits.NumParams + ParamInfo + + + + TemplateOrSpecialization + + + + {*($T1*)&Ptr} + + ($T1*)&Ptr + + + + {($T1 *)Ptr} + + ($T1 *)Ptr + + + + + {*((NamedDecl **)(this+1))[0],view(cpp)}{*this,view(parm1)} + + , {*((NamedDecl **)(this+1))[1],view(cpp)}{*this,view(parm2)} + + , {*((NamedDecl **)(this+1))[2],view(cpp)}{*this,view(parm3)} + + , {*((NamedDecl **)(this+1))[3],view(cpp)}{*this,view(parm4)} + + , {*((NamedDecl **)(this+1))[4],view(cpp)}{*this,view(parm5)} + + , /* Expand for more params */ + <{*this,view(parm0)}> + + + NumParams + (NamedDecl **)(this+1) + + + + + {(clang::Stmt::StmtClass)StmtBits.sClass,en} + + (clang::Stmt::StmtClass)StmtBits.sClass,en + + + + {*(clang::StringLiteral *)this} + Expression of class {(clang::Stmt::StmtClass)StmtBits.sClass,en} and type {TR,view(cpp)} + + + + *(unsigned *)(((clang::StringLiteral *)this)+1) + (const char *)(((clang::StringLiteral *)this)+1)+4+4,[*(unsigned *)(((clang::StringLiteral *)this)+1)]s8 + + + + public + protected + private + + {*(clang::NamedDecl *)(Ptr&~Mask)} + {*this,view(access)} {*this,view(decl)} + + (clang::AccessSpecifier)(Ptr&Mask),en + *(clang::NamedDecl *)(Ptr&~Mask) + + + + [IK_Identifier] {*Identifier} + [IK_OperatorFunctionId] {OperatorFunctionId} + [IK_ConversionFunctionId] {ConversionFunctionId} + [IK_ConstructorName] {ConstructorName} + [IK_DestructorName] {DestructorName} + [IK_DeductionGuideName] {TemplateName} + [IK_TemplateId] {TemplateId} + [IK_ConstructorTemplateId] {TemplateId} + Kind + + Identifier + OperatorFunctionId + ConversionFunctionId + ConstructorName + DestructorName + TemplateName + TemplateId + TemplateId + + + + NumDecls={NumDecls} + + + NumDecls + (Decl **)(this+1) + + + + + {*D} + {*(DeclGroup *)((uintptr_t)D&~1)} + + D + (DeclGroup *)((uintptr_t)D&~1) + + + + {DS} {Name} + + + {Decls} + + Decls + + + + {Ambiguity,en}: {Decls} + {ResultKind,en}: {Decls} + + + Invalid + Unset + {Val} + + + Invalid + Unset + {($T1)(Value&~1)} + + (bool)(Value&1) + ($T1)(Value&~1) + + + diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 6f3cc8247d2e2..82ba9b370ba59 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -5579,7 +5579,7 @@

C++ defect report implementation status

960 CD2 Covariant functions and lvalue/rvalue references - Unknown + Clang 3.0 961 @@ -16736,7 +16736,7 @@

C++ defect report implementation status

2815 - drafting + tentatively ready Overload resolution for references/pointers to noexcept functions Not resolved @@ -17124,7 +17124,7 @@

C++ defect report implementation status

2879 - drafting + review Undesired outcomes with const_cast Not resolved @@ -17296,7 +17296,7 @@

C++ defect report implementation status

2907 - open + tentatively ready Constant lvalue-to-rvalue conversion on uninitialized std::nullptr_t Not resolved @@ -17308,19 +17308,19 @@

C++ defect report implementation status

2909 - open + review Subtle difference between constant-initialized and constexpr Not resolved 2910 - open + tentatively ready Effect of requirement-parameter-lists on odr-usability Not resolved 2911 - open + tentatively ready Unclear meaning of expressions "appearing within" subexpressions Not resolved @@ -17374,7 +17374,7 @@

C++ defect report implementation status

2918 - review + tentatively ready Consideration of constraints for address of overloaded function Not resolved @@ -17426,13 +17426,13 @@

C++ defect report implementation status

2926 - tentatively ready + open Lookup context for dependent qualified names Not resolved 2927 - review + tentatively ready Unclear status of translation unit with module keyword Not resolved @@ -17444,25 +17444,25 @@

C++ defect report implementation status

2929 - open + tentatively ready Lifetime of trivially-destructible static or thread-local objects Not resolved 2930 - open + tentatively ready Unclear term "copy/move operation" in specification of copy elision Not resolved 2931 - open + tentatively ready Restrictions on operator functions that are explicit object member functions Not resolved 2932 - open + review Value range of empty enumeration Not resolved @@ -17489,6 +17489,24 @@

C++ defect report implementation status

open Local classes of templated functions should be part of the current instantiation Not resolved + + + 2937 + open + Grammar for preprocessing-file has no normative effect + Not resolved + + + 2938 + open + Inheriting linkage from a previous declaration + Not resolved + + + 2939 + open + Do not allow reinterpret_cast from prvalue to rvalue reference + Not resolved diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index d00d39518104b..fb4dfa7bd09df 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -104,6 +104,7 @@ else() set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} powerpc64le ${HEXAGON} ${LOONGARCH64}) endif() +set(ALL_XRAY_DSO_SUPPORTED_ARCH ${X86_64}) set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64}) if (UNIX) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index a494e0532a50b..431f544e8ad6a 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -668,6 +668,9 @@ if(APPLE) list_intersect(XRAY_SUPPORTED_ARCH ALL_XRAY_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) + list_intersect(XRAY_DSO_SUPPORTED_ARCH + ALL_XRAY_DSO_SUPPORTED_ARCH + SANITIZER_COMMON_SUPPORTED_ARCH) list_intersect(SHADOWCALLSTACK_SUPPORTED_ARCH ALL_SHADOWCALLSTACK_SUPPORTED_ARCH SANITIZER_COMMON_SUPPORTED_ARCH) @@ -702,6 +705,7 @@ else() filter_available_targets(CFI_SUPPORTED_ARCH ${ALL_CFI_SUPPORTED_ARCH}) filter_available_targets(SCUDO_STANDALONE_SUPPORTED_ARCH ${ALL_SCUDO_STANDALONE_SUPPORTED_ARCH}) filter_available_targets(XRAY_SUPPORTED_ARCH ${ALL_XRAY_SUPPORTED_ARCH}) + filter_available_targets(XRAY_DSO_SUPPORTED_ARCH ${ALL_XRAY_DSO_SUPPORTED_ARCH}) filter_available_targets(SHADOWCALLSTACK_SUPPORTED_ARCH ${ALL_SHADOWCALLSTACK_SUPPORTED_ARCH}) filter_available_targets(GWP_ASAN_SUPPORTED_ARCH ${ALL_GWP_ASAN_SUPPORTED_ARCH}) diff --git a/compiler-rt/include/xray/xray_interface.h b/compiler-rt/include/xray/xray_interface.h index 727431c04e4f7..675ea0cbc48c8 100644 --- a/compiler-rt/include/xray/xray_interface.h +++ b/compiler-rt/include/xray/xray_interface.h @@ -93,31 +93,78 @@ enum XRayPatchingStatus { FAILED = 3, }; -/// This tells XRay to patch the instrumentation points. See XRayPatchingStatus -/// for possible result values. +/// This tells XRay to patch the instrumentation points in all currently loaded +/// objects. See XRayPatchingStatus for possible result values. extern XRayPatchingStatus __xray_patch(); +/// This tells XRay to patch the instrumentation points in the given object. +/// See XRayPatchingStatus for possible result values. +extern XRayPatchingStatus __xray_patch_object(int32_t ObjId); + /// Reverses the effect of __xray_patch(). See XRayPatchingStatus for possible /// result values. extern XRayPatchingStatus __xray_unpatch(); -/// This patches a specific function id. See XRayPatchingStatus for possible +/// Reverses the effect of __xray_patch_object. See XRayPatchingStatus for +/// possible result values. +extern XRayPatchingStatus __xray_unpatch_object(int32_t ObjId); + +/// This unpacks the given (packed) function id and patches +/// the corresponding function. See XRayPatchingStatus for possible /// result values. extern XRayPatchingStatus __xray_patch_function(int32_t FuncId); -/// This unpatches a specific function id. See XRayPatchingStatus for possible +/// This patches a specific function in the given object. See XRayPatchingStatus +/// for possible result values. +extern XRayPatchingStatus __xray_patch_function_in_object(int32_t FuncId, + int32_t ObjId); + +/// This unpacks the given (packed) function id and unpatches +/// the corresponding function. See XRayPatchingStatus for possible /// result values. extern XRayPatchingStatus __xray_unpatch_function(int32_t FuncId); -/// This function returns the address of the function provided a valid function -/// id. We return 0 if we encounter any error, even if 0 may be a valid function -/// address. +/// This unpatches a specific function in the given object. +/// See XRayPatchingStatus for possible result values. +extern XRayPatchingStatus __xray_unpatch_function_in_object(int32_t FuncId, + int32_t ObjId); + +/// This function unpacks the given (packed) function id and returns the address +/// of the corresponding function. We return 0 if we encounter any error, even +/// if 0 may be a valid function address. extern uintptr_t __xray_function_address(int32_t FuncId); -/// This function returns the maximum valid function id. Returns 0 if we -/// encounter errors (when there are no instrumented functions, etc.). +/// This function returns the address of the function in the given object +/// provided valid function and object ids. We return 0 if we encounter any +/// error, even if 0 may be a valid function address. +extern uintptr_t __xray_function_address_in_object(int32_t FuncId, + int32_t ObjId); + +/// This function returns the maximum valid function id for the main executable +/// (object id = 0). Returns 0 if we encounter errors (when there are no +/// instrumented functions, etc.). extern size_t __xray_max_function_id(); +/// This function returns the maximum valid function id for the given object. +/// Returns 0 if we encounter errors (when there are no instrumented functions, +/// etc.). +extern size_t __xray_max_function_id_in_object(int32_t ObjId); + +/// This function returns the number of previously registered objects +/// (executable + loaded DSOs). Returns 0 if XRay has not been initialized. +extern size_t __xray_num_objects(); + +/// Unpacks the function id from the given packed id. +extern int32_t __xray_unpack_function_id(int32_t PackedId); + +/// Unpacks the object id from the given packed id. +extern int32_t __xray_unpack_object_id(int32_t PackedId); + +/// Creates and returns a packed id from the given function and object ids. +/// If the ids do not fit within the reserved number of bits for each part, the +/// high bits are truncated. +extern int32_t __xray_pack_id(int32_t FuncId, int32_t ObjId); + /// Initialize the required XRay data structures. This is useful in cases where /// users want to control precisely when the XRay instrumentation data /// structures are initialized, for example when the XRay library is built with diff --git a/compiler-rt/lib/builtins/cpu_model/AArch64CPUFeatures.inc b/compiler-rt/lib/builtins/cpu_model/AArch64CPUFeatures.inc index bb1875fe9f72c..7af7f42517d1f 100644 --- a/compiler-rt/lib/builtins/cpu_model/AArch64CPUFeatures.inc +++ b/compiler-rt/lib/builtins/cpu_model/AArch64CPUFeatures.inc @@ -65,7 +65,7 @@ enum CPUFeatures { FEAT_SVE_SHA3, FEAT_SVE_SM4, FEAT_SME, - FEAT_MEMTAG, + RESERVED_FEAT_MEMTAG, // previously used and now ABI legacy FEAT_MEMTAG2, FEAT_MEMTAG3, FEAT_SB, diff --git a/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/mrs.inc b/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/mrs.inc index a9befd7f3e56d..0f1e9dd85303c 100644 --- a/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/mrs.inc +++ b/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/mrs.inc @@ -45,10 +45,8 @@ static void __init_cpu_features_constructor(unsigned long hwcap, setCPUFeature(FEAT_SB); if (hwcap & HWCAP_SSBS) setCPUFeature(FEAT_SSBS2); - if (hwcap2 & HWCAP2_MTE) { - setCPUFeature(FEAT_MEMTAG); + if (hwcap2 & HWCAP2_MTE) setCPUFeature(FEAT_MEMTAG2); - } if (hwcap2 & HWCAP2_MTE3) setCPUFeature(FEAT_MEMTAG3); if (hwcap2 & HWCAP2_SVEAES) diff --git a/compiler-rt/lib/builtins/cpu_model/x86.c b/compiler-rt/lib/builtins/cpu_model/x86.c index 23f8fa3e1fd49..7fa4b9e2b6608 100644 --- a/compiler-rt/lib/builtins/cpu_model/x86.c +++ b/compiler-rt/lib/builtins/cpu_model/x86.c @@ -475,6 +475,8 @@ static const char *getIntelProcessorTypeAndSubtype(unsigned Family, // Arrowlake: case 0xc5: + // Arrowlake U: + case 0xb5: CPU = "arrowlake"; *Type = INTEL_COREI7; *Subtype = INTEL_COREI7_ARROWLAKE; diff --git a/compiler-rt/lib/hwasan/CMakeLists.txt b/compiler-rt/lib/hwasan/CMakeLists.txt index 086079c7536e5..afafa0c4a9276 100644 --- a/compiler-rt/lib/hwasan/CMakeLists.txt +++ b/compiler-rt/lib/hwasan/CMakeLists.txt @@ -24,16 +24,19 @@ foreach(arch ${HWASAN_SUPPORTED_ARCH}) if(${arch} MATCHES "aarch64") list(APPEND HWASAN_RTL_SOURCES hwasan_setjmp_aarch64.S - hwasan_tag_mismatch_aarch64.S) + hwasan_tag_mismatch_aarch64.S + ) endif() if(${arch} MATCHES "riscv64") list(APPEND HWASAN_RTL_SOURCES hwasan_setjmp_riscv64.S - hwasan_tag_mismatch_riscv64.S) + hwasan_tag_mismatch_riscv64.S + ) endif() if(${arch} MATCHES "x86_64") list(APPEND HWASAN_RTL_SOURCES - hwasan_setjmp_x86_64.S) + hwasan_setjmp_x86_64.S + ) endif() endforeach() diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index 4f60d4251303d..077a536dd2a31 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -769,6 +769,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { switch (*(u32*)(address)) { case 0x1ab60f44: // 44 0f b6 1a : movzx r11d, BYTE PTR [rdx] + return 4; case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX] case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 721db7872cce8..5c44c000ae577 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -288,23 +288,54 @@ static inline bool MaybeUserPointer(uptr p) { # endif } +namespace { +struct DirectMemoryAccessor { + void Init(uptr begin, uptr end) {}; + void *LoadPtr(uptr p) const { return *reinterpret_cast(p); } +}; + +struct CopyMemoryAccessor { + void Init(uptr begin, uptr end) { + this->begin = begin; + buffer.clear(); + buffer.resize(end - begin); + MemCpyAccessible(buffer.data(), reinterpret_cast(begin), + buffer.size()); + }; + + void *LoadPtr(uptr p) const { + uptr offset = p - begin; + CHECK_LE(offset + sizeof(void *), reinterpret_cast(buffer.size())); + return *reinterpret_cast(offset + + reinterpret_cast(buffer.data())); + } + + private: + uptr begin; + InternalMmapVector buffer; +}; +} // namespace + // Scans the memory range, looking for byte patterns that point into allocator // chunks. Marks those chunks with |tag| and adds them to |frontier|. // There are two usage modes for this function: finding reachable chunks // (|tag| = kReachable) and finding indirectly leaked chunks // (|tag| = kIndirectlyLeaked). In the second case, there's no flood fill, // so |frontier| = 0. -void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier, - const char *region_type, ChunkTag tag) { +template +void ScanForPointers(uptr begin, uptr end, Frontier *frontier, + const char *region_type, ChunkTag tag, + Accessor &accessor) { CHECK(tag == kReachable || tag == kIndirectlyLeaked); const uptr alignment = flags()->pointer_alignment(); LOG_POINTERS("Scanning %s range %p-%p.\n", region_type, (void *)begin, (void *)end); + accessor.Init(begin, end); uptr pp = begin; if (pp % alignment) pp = pp + alignment - pp % alignment; for (; pp + sizeof(void *) <= end; pp += alignment) { - void *p = *reinterpret_cast(pp); + void *p = accessor.LoadPtr(pp); # if SANITIZER_APPLE p = TransformPointer(p); # endif @@ -339,6 +370,12 @@ void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier, } } +void ScanRangeForPointers(uptr begin, uptr end, Frontier *frontier, + const char *region_type, ChunkTag tag) { + DirectMemoryAccessor accessor; + ScanForPointers(begin, end, frontier, region_type, tag, accessor); +} + // Scans a global range for pointers void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) { uptr allocator_begin = 0, allocator_end = 0; @@ -356,14 +393,21 @@ void ScanGlobalRange(uptr begin, uptr end, Frontier *frontier) { } } -void ScanExtraStackRanges(const InternalMmapVector &ranges, - Frontier *frontier) { +template +void ScanRanges(const InternalMmapVector &ranges, Frontier *frontier, + const char *region_type, Accessor &accessor) { for (uptr i = 0; i < ranges.size(); i++) { - ScanRangeForPointers(ranges[i].begin, ranges[i].end, frontier, "FAKE STACK", - kReachable); + ScanForPointers(ranges[i].begin, ranges[i].end, frontier, region_type, + kReachable, accessor); } } +void ScanExtraStackRanges(const InternalMmapVector &ranges, + Frontier *frontier) { + DirectMemoryAccessor accessor; + ScanRanges(ranges, frontier, "FAKE STACK", accessor); +} + # if SANITIZER_FUCHSIA // Fuchsia handles all threads together with its own callback. @@ -399,10 +443,11 @@ static void ProcessThreadRegistry(Frontier *frontier) { } // Scans thread data (stacks and TLS) for heap pointers. +template static void ProcessThread(tid_t os_id, uptr sp, const InternalMmapVector ®isters, InternalMmapVector &extra_ranges, - Frontier *frontier) { + Frontier *frontier, Accessor &accessor) { // `extra_ranges` is outside of the function and the loop to reused mapped // memory. CHECK(extra_ranges.empty()); @@ -426,8 +471,8 @@ static void ProcessThread(tid_t os_id, uptr sp, uptr registers_begin = reinterpret_cast(registers.data()); uptr registers_end = reinterpret_cast(registers.data() + registers.size()); - ScanRangeForPointers(registers_begin, registers_end, frontier, "REGISTERS", - kReachable); + ScanForPointers(registers_begin, registers_end, frontier, "REGISTERS", + kReachable, accessor); } if (flags()->use_stacks) { @@ -451,9 +496,10 @@ static void ProcessThread(tid_t os_id, uptr sp, // Shrink the stack range to ignore out-of-scope values. stack_begin = sp; } - ScanRangeForPointers(stack_begin, stack_end, frontier, "STACK", kReachable); + ScanForPointers(stack_begin, stack_end, frontier, "STACK", kReachable, + accessor); GetThreadExtraStackRangesLocked(os_id, &extra_ranges); - ScanExtraStackRanges(extra_ranges, frontier); + ScanRanges(extra_ranges, frontier, "FAKE STACK", accessor); } if (flags()->use_tls) { @@ -463,23 +509,26 @@ static void ProcessThread(tid_t os_id, uptr sp, // otherwise, only scan the non-overlapping portions if (cache_begin == cache_end || tls_end < cache_begin || tls_begin > cache_end) { - ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable); + ScanForPointers(tls_begin, tls_end, frontier, "TLS", kReachable, + accessor); } else { if (tls_begin < cache_begin) - ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS", - kReachable); + ScanForPointers(tls_begin, cache_begin, frontier, "TLS", kReachable, + accessor); if (tls_end > cache_end) - ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable); + ScanForPointers(cache_end, tls_end, frontier, "TLS", kReachable, + accessor); } } # if SANITIZER_ANDROID + extra_ranges.clear(); auto *cb = +[](void *dtls_begin, void *dtls_end, uptr /*dso_idd*/, void *arg) -> void { - ScanRangeForPointers( - reinterpret_cast(dtls_begin), reinterpret_cast(dtls_end), - reinterpret_cast(arg), "DTLS", kReachable); + reinterpret_cast *>(arg)->push_back( + {reinterpret_cast(dtls_begin), + reinterpret_cast(dtls_end)}); }; - + ScanRanges(extra_ranges, frontier, "DTLS", accessor); // FIXME: There might be a race-condition here (and in Bionic) if the // thread is suspended in the middle of updating its DTLS. IOWs, we // could scan already freed memory. (probably fine for now) @@ -492,8 +541,8 @@ static void ProcessThread(tid_t os_id, uptr sp, if (dtls_beg < dtls_end) { LOG_THREADS("DTLS %d at %p-%p.\n", id, (void *)dtls_beg, (void *)dtls_end); - ScanRangeForPointers(dtls_beg, dtls_end, frontier, "DTLS", - kReachable); + ScanForPointers(dtls_beg, dtls_end, frontier, "DTLS", kReachable, + accessor); } }); } else { @@ -508,6 +557,7 @@ static void ProcessThread(tid_t os_id, uptr sp, static void ProcessThreads(SuspendedThreadsList const &suspended_threads, Frontier *frontier, tid_t caller_tid, uptr caller_sp) { + InternalMmapVector done_threads; InternalMmapVector registers; InternalMmapVector extra_ranges; for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) { @@ -530,7 +580,27 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads, if (os_id == caller_tid) sp = caller_sp; - ProcessThread(os_id, sp, registers, extra_ranges, frontier); + DirectMemoryAccessor accessor; + ProcessThread(os_id, sp, registers, extra_ranges, frontier, accessor); + if (flags()->use_detached) + done_threads.push_back(os_id); + } + + if (flags()->use_detached) { + CopyMemoryAccessor accessor; + InternalMmapVector known_threads; + GetRunningThreadsLocked(&known_threads); + Sort(done_threads.data(), done_threads.size()); + for (tid_t os_id : known_threads) { + registers.clear(); + extra_ranges.clear(); + + uptr i = InternalLowerBound(done_threads, os_id); + if (i >= done_threads.size() || done_threads[i] != os_id) { + uptr sp = (os_id == caller_tid) ? caller_sp : 0; + ProcessThread(os_id, sp, registers, extra_ranges, frontier, accessor); + } + } } // Add pointers reachable from ThreadContexts diff --git a/compiler-rt/lib/lsan/lsan_flags.inc b/compiler-rt/lib/lsan/lsan_flags.inc index c97b021ba5c02..e0b4aa4a3299e 100644 --- a/compiler-rt/lib/lsan/lsan_flags.inc +++ b/compiler-rt/lib/lsan/lsan_flags.inc @@ -41,6 +41,8 @@ LSAN_FLAG(bool, use_ld_allocations, true, LSAN_FLAG(bool, use_unaligned, false, "Consider unaligned pointers valid.") LSAN_FLAG(bool, use_poisoned, false, "Consider pointers found in poisoned memory to be valid.") +LSAN_FLAG(bool, use_detached, false, + "Scan threads even if attaching to them failed.") LSAN_FLAG(bool, log_pointers, false, "Debug logging") LSAN_FLAG(bool, log_threads, false, "Debug logging") LSAN_FLAG(int, tries, 1, "Debug option to repeat leak checking multiple times") diff --git a/compiler-rt/lib/profile/InstrProfilingUtil.c b/compiler-rt/lib/profile/InstrProfilingUtil.c index 95ec4080ba250..c637b9d0b893c 100644 --- a/compiler-rt/lib/profile/InstrProfilingUtil.c +++ b/compiler-rt/lib/profile/InstrProfilingUtil.c @@ -152,7 +152,8 @@ COMPILER_RT_VISIBILITY int lprofLockFd(int fd) { } } return 0; -#elif defined(COMPILER_RT_HAS_FLOCK) +#elif defined(COMPILER_RT_HAS_FLOCK) || defined(_WIN32) + // Windows doesn't have flock but WindowsMMap.h provides a shim flock(fd, LOCK_EX); return 0; #else @@ -179,7 +180,8 @@ COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) { } } return 0; -#elif defined(COMPILER_RT_HAS_FLOCK) +#elif defined(COMPILER_RT_HAS_FLOCK) || defined(_WIN32) + // Windows doesn't have flock but WindowsMMap.h provides a shim flock(fd, LOCK_UN); return 0; #else diff --git a/compiler-rt/lib/rtsan/CMakeLists.txt b/compiler-rt/lib/rtsan/CMakeLists.txt index f8dd4d735bc2a..a4413d9992b62 100644 --- a/compiler-rt/lib/rtsan/CMakeLists.txt +++ b/compiler-rt/lib/rtsan/CMakeLists.txt @@ -5,7 +5,7 @@ set(RTSAN_CXX_SOURCES rtsan_context.cpp rtsan_diagnostics.cpp rtsan_flags.cpp - rtsan_interceptors.cpp + rtsan_interceptors_posix.cpp rtsan_stats.cpp rtsan_suppressions.cpp ) diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp similarity index 100% rename from compiler-rt/lib/rtsan/rtsan_interceptors.cpp rename to compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp diff --git a/compiler-rt/lib/rtsan/tests/CMakeLists.txt b/compiler-rt/lib/rtsan/tests/CMakeLists.txt index 139eea785fcdc..0cf07b307d461 100644 --- a/compiler-rt/lib/rtsan/tests/CMakeLists.txt +++ b/compiler-rt/lib/rtsan/tests/CMakeLists.txt @@ -16,7 +16,7 @@ set(RTSAN_UNITTEST_CFLAGS set(RTSAN_INST_TEST_SOURCES rtsan_test_functional.cpp - rtsan_test_interceptors.cpp + rtsan_test_interceptors_posix.cpp rtsan_test_main.cpp) set(RTSAN_NOINST_TEST_SOURCES diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp similarity index 100% rename from compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp rename to compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp index c2ace46c94658..acbf3ebfc95c0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp @@ -523,7 +523,6 @@ uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { uptr MainThreadStackBase, MainThreadStackSize; bool GetRandom(void *buffer, uptr length, bool blocking) { - CHECK_LE(length, ZX_CPRNG_DRAW_MAX_LEN); _zx_cprng_draw(buffer, length); return true; } diff --git a/compiler-rt/lib/xray/CMakeLists.txt b/compiler-rt/lib/xray/CMakeLists.txt index cf7b5062aae32..f38c07420c9ab 100644 --- a/compiler-rt/lib/xray/CMakeLists.txt +++ b/compiler-rt/lib/xray/CMakeLists.txt @@ -10,6 +10,10 @@ set(XRAY_SOURCES xray_utils.cpp ) +set(XRAY_DSO_SOURCES + xray_dso_init.cpp + ) + # Implementation files for all XRay modes. set(XRAY_FDR_MODE_SOURCES xray_fdr_flags.cpp @@ -33,6 +37,11 @@ set(x86_64_SOURCES xray_trampoline_x86_64.S ) +set(x86_64_DSO_SOURCES + xray_trampoline_x86_64.S + ) + + set(arm_SOURCES xray_arm.cpp xray_trampoline_arm.S @@ -128,10 +137,12 @@ set(XRAY_IMPL_HEADERS # consumption by tests. set(XRAY_ALL_SOURCE_FILES ${XRAY_SOURCES} + ${XRAY_DSO_SOURCES} ${XRAY_FDR_MODE_SOURCES} ${XRAY_BASIC_MODE_SOURCES} ${XRAY_PROFILING_MODE_SOURCES} ${x86_64_SOURCES} + ${x86_64_DSO_SOURCES} ${arm_SOURCES} ${armhf_SOURCES} ${hexagon_SOURCES} @@ -162,6 +173,9 @@ set(XRAY_CFLAGS ${COMPILER_RT_CXX_CFLAGS}) set(XRAY_COMMON_DEFINITIONS SANITIZER_COMMON_NO_REDEFINE_BUILTINS XRAY_HAS_EXCEPTIONS=1) +# DSO trampolines need to be compiled with GOT addressing +set(XRAY_COMMON_DEFINITIONS_DSO ${XRAY_COMMON_DEFINITIONS} XRAY_PIC) + # Too many existing bugs, needs cleanup. append_list_if(COMPILER_RT_HAS_WNO_FORMAT -Wno-format XRAY_CFLAGS) @@ -201,7 +215,16 @@ if (APPLE) CFLAGS ${XRAY_CFLAGS} DEFS ${XRAY_COMMON_DEFINITIONS} DEPS ${XRAY_DEPS}) + add_compiler_rt_object_libraries(RTXrayDSO + OS ${XRAY_SUPPORTED_OS} + ARCHS ${XRAY_DSO_SUPPORTED_ARCH} + SOURCES ${XRAY_DSO_SOURCES} + ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} + CFLAGS ${XRAY_CFLAGS} + DEFS ${XRAY_COMMON_DEFINITIONS_DSO} + DEPS ${XRAY_DEPS}) set(XRAY_RTXRAY_ARCH_LIBS "") + set(XRAY_DSO_RTXRAY_ARCH_LIBS "") foreach(arch ${XRAY_SUPPORTED_ARCH}) if(NOT ${arch} IN_LIST XRAY_SOURCE_ARCHS) continue() @@ -215,6 +238,17 @@ if (APPLE) DEFS ${XRAY_COMMON_DEFINITIONS} DEPS ${XRAY_DEPS}) list(APPEND XRAY_RTXRAY_ARCH_LIBS RTXray_${arch}) + if (${arch} IN_LIST XRAY_DSO_SUPPORTED_ARCH) + add_compiler_rt_object_libraries(RTXrayDSO_${arch} + OS ${XRAY_SUPPORTED_OS} + ARCHS ${XRAY_DSO_SUPPORTED_ARCH} + SOURCES ${${arch}_DSO_SOURCES} + ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} + CFLAGS ${XRAY_CFLAGS} + DEFS ${XRAY_COMMON_DEFINITIONS_DSO} + DEPS ${XRAY_DEPS}) + list(APPEND XRAY_DSO_RTXRAY_ARCH_LIBS RTXrayDSO_${arch}) + endif() endforeach() add_compiler_rt_object_libraries(RTXrayFDR OS ${XRAY_SUPPORTED_OS} @@ -252,6 +286,17 @@ if (APPLE) LINK_FLAGS ${XRAY_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} LINK_LIBS ${XRAY_LINK_LIBS} PARENT_TARGET xray) + add_compiler_rt_runtime(clang_rt.xray-dso + STATIC + OS ${XRAY_SUPPORTED_OS} + ARCHS ${XRAY_DSO_SUPPORTED_ARCH} + OBJECT_LIBS RTXrayDSO ${XRAY_DSO_RTXRAY_ARCH_LIBS} + CFLAGS ${XRAY_CFLAGS} + DEFS ${XRAY_COMMON_DEFINITIONS} + LINK_FLAGS ${XRAY_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} + LINK_LIBS ${XRAY_LINK_LIBS} + PARENT_TARGET xray) + add_compiler_rt_runtime(clang_rt.xray-fdr STATIC OS ${XRAY_SUPPORTED_OS} @@ -346,16 +391,37 @@ else() # not Apple DEFS ${XRAY_COMMON_DEFINITIONS} OBJECT_LIBS RTXrayBASIC PARENT_TARGET xray) - # Profiler Mode runtime - add_compiler_rt_runtime(clang_rt.xray-profiling - STATIC - ARCHS ${arch} - CFLAGS ${XRAY_CFLAGS} - LINK_FLAGS ${XRAY_LINK_FLAGS} - LINK_LIBS ${XRAY_LINK_LIBS} - DEFS ${XRAY_COMMON_DEFINITIONS} - OBJECT_LIBS RTXrayPROFILING - PARENT_TARGET xray) + # Profiler Mode runtime + add_compiler_rt_runtime(clang_rt.xray-profiling + STATIC + ARCHS ${arch} + CFLAGS ${XRAY_CFLAGS} + LINK_FLAGS ${XRAY_LINK_FLAGS} + LINK_LIBS ${XRAY_LINK_LIBS} + DEFS ${XRAY_COMMON_DEFINITIONS} + OBJECT_LIBS RTXrayPROFILING + PARENT_TARGET xray) + + if (${arch} IN_LIST XRAY_DSO_SUPPORTED_ARCH) + # TODO: Only implemented for X86 at the moment + add_compiler_rt_object_libraries(RTXrayDSO + ARCHS ${arch} + SOURCES ${XRAY_DSO_SOURCES} ${${arch}_DSO_SOURCES} + ADDITIONAL_HEADERS ${XRAY_IMPL_HEADERS} + CFLAGS ${XRAY_CFLAGS} + DEFS ${XRAY_COMMON_DEFINITIONS_DSO} + DEPS ${XRAY_DEPS}) + # DSO runtime archive + add_compiler_rt_runtime(clang_rt.xray-dso + STATIC + ARCHS ${arch} + CFLAGS ${XRAY_CFLAGS} + LINK_FLAGS ${XRAY_LINK_FLAGS} + LINK_LIBS ${XRAY_LINK_LIBS} + DEFS ${XRAY_COMMON_DEFINITIONS} + OBJECT_LIBS RTXrayDSO + PARENT_TARGET xray) + endif() endforeach() endif() # not Apple diff --git a/compiler-rt/lib/xray/xray_AArch64.cpp b/compiler-rt/lib/xray/xray_AArch64.cpp index c1d77758946ed..2b151162ce4b9 100644 --- a/compiler-rt/lib/xray/xray_AArch64.cpp +++ b/compiler-rt/lib/xray/xray_AArch64.cpp @@ -89,18 +89,23 @@ inline static bool patchSled(const bool Enable, const uint32_t FuncId, bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRayTrampolines &Trampolines, + bool LogArgs) XRAY_NEVER_INSTRUMENT { + auto Trampoline = + LogArgs ? Trampolines.LogArgsTrampoline : Trampolines.EntryTrampoline; return patchSled(Enable, FuncId, Sled, Trampoline); } -bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); +bool patchFunctionExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } -bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionTailExit); +bool patchFunctionTailExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.TailExitTrampoline); } // AArch64AsmPrinter::LowerPATCHABLE_EVENT_CALL generates this code sequence: diff --git a/compiler-rt/lib/xray/xray_arm.cpp b/compiler-rt/lib/xray/xray_arm.cpp index e1818555906c3..e318bb7070e80 100644 --- a/compiler-rt/lib/xray/xray_arm.cpp +++ b/compiler-rt/lib/xray/xray_arm.cpp @@ -128,18 +128,23 @@ inline static bool patchSled(const bool Enable, const uint32_t FuncId, bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRayTrampolines &Trampolines, + bool LogArgs) XRAY_NEVER_INSTRUMENT { + auto Trampoline = + LogArgs ? Trampolines.LogArgsTrampoline : Trampolines.EntryTrampoline; return patchSled(Enable, FuncId, Sled, Trampoline); } -bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); +bool patchFunctionExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } -bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionTailExit); +bool patchFunctionTailExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.TailExitTrampoline); } bool patchCustomEvent(const bool Enable, const uint32_t FuncId, diff --git a/compiler-rt/lib/xray/xray_dso_init.cpp b/compiler-rt/lib/xray/xray_dso_init.cpp new file mode 100644 index 0000000000000..eb754db54c64f --- /dev/null +++ b/compiler-rt/lib/xray/xray_dso_init.cpp @@ -0,0 +1,62 @@ +//===-- xray_init.cpp -------------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file is a part of XRay, a dynamic runtime instrumentation system. +// +// XRay initialisation logic for DSOs. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_atomic.h" +#include "xray_defs.h" +#include "xray_flags.h" +#include "xray_interface_internal.h" + +using namespace __sanitizer; + +extern "C" { +extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak)) +__attribute__((visibility("hidden"))); +extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak)) +__attribute__((visibility("hidden"))); +extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak)) +__attribute__((visibility("hidden"))); +extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak)) +__attribute__((visibility("hidden"))); + +#if SANITIZER_APPLE +// HACK: This is a temporary workaround to make XRay build on +// Darwin, but it will probably not work at runtime. +extern const XRaySledEntry __start_xray_instr_map[] = {}; +extern const XRaySledEntry __stop_xray_instr_map[] = {}; +extern const XRayFunctionSledIndex __start_xray_fn_idx[] = {}; +extern const XRayFunctionSledIndex __stop_xray_fn_idx[] = {}; +#endif +} + +// Handler functions to call in the patched entry/exit sled. +extern atomic_uintptr_t XRayPatchedFunction; +extern atomic_uintptr_t XRayArgLogger; +extern atomic_uintptr_t XRayPatchedCustomEvent; +extern atomic_uintptr_t XRayPatchedTypedEvent; + +static int __xray_object_id{-1}; + +// Note: .preinit_array initialization does not work for DSOs +__attribute__((constructor(0))) static void +__xray_init_dso() XRAY_NEVER_INSTRUMENT { + // Register sleds in main XRay runtime. + __xray_object_id = + __xray_register_dso(__start_xray_instr_map, __stop_xray_instr_map, + __start_xray_fn_idx, __stop_xray_fn_idx, {}); +} + +__attribute__((destructor(0))) static void +__xray_finalize_dso() XRAY_NEVER_INSTRUMENT { + // Inform the main runtime that this DSO is no longer used. + __xray_deregister_dso(__xray_object_id); +} diff --git a/compiler-rt/lib/xray/xray_hexagon.cpp b/compiler-rt/lib/xray/xray_hexagon.cpp index 7f127b2b499cd..1c07bb0469036 100644 --- a/compiler-rt/lib/xray/xray_hexagon.cpp +++ b/compiler-rt/lib/xray/xray_hexagon.cpp @@ -135,18 +135,23 @@ inline static bool patchSled(const bool Enable, const uint32_t FuncId, bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRayTrampolines &Trampolines, + bool LogArgs) XRAY_NEVER_INSTRUMENT { + auto Trampoline = + LogArgs ? Trampolines.LogArgsTrampoline : Trampolines.EntryTrampoline; return patchSled(Enable, FuncId, Sled, Trampoline); } -bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); +bool patchFunctionExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } -bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); +bool patchFunctionTailExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.TailExitTrampoline); } bool patchCustomEvent(const bool Enable, const uint32_t FuncId, diff --git a/compiler-rt/lib/xray/xray_init.cpp b/compiler-rt/lib/xray/xray_init.cpp index f22a31b95686d..020bfe52b5320 100644 --- a/compiler-rt/lib/xray/xray_init.cpp +++ b/compiler-rt/lib/xray/xray_init.cpp @@ -16,6 +16,8 @@ #include #include "sanitizer_common/sanitizer_common.h" +#include "xray/xray_interface.h" +#include "xray_allocator.h" #include "xray_defs.h" #include "xray_flags.h" #include "xray_interface_internal.h" @@ -28,7 +30,7 @@ extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak)); extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak)); #if SANITIZER_APPLE -// HACK: This is a temporary workaround to make XRay build on +// HACK: This is a temporary workaround to make XRay build on // Darwin, but it will probably not work at runtime. const XRaySledEntry __start_xray_instr_map[] = {}; extern const XRaySledEntry __stop_xray_instr_map[] = {}; @@ -43,14 +45,16 @@ using namespace __xray; // the weak symbols defined above (__start_xray_inst_map and // __stop_xray_instr_map) to initialise the instrumentation map that XRay uses // for runtime patching/unpatching of instrumentation points. -// -// FIXME: Support DSO instrumentation maps too. The current solution only works -// for statically linked executables. atomic_uint8_t XRayInitialized{0}; // This should always be updated before XRayInitialized is updated. SpinMutex XRayInstrMapMutex; -XRaySledMap XRayInstrMap; + +// Contains maps for the main executable as well as DSOs. +XRaySledMap *XRayInstrMaps; + +// Number of binary objects registered. +atomic_uint32_t XRayNumObjects{0}; // Global flag to determine whether the flags have been initialized. atomic_uint8_t XRayFlagsInitialized{0}; @@ -58,6 +62,63 @@ atomic_uint8_t XRayFlagsInitialized{0}; // A mutex to allow only one thread to initialize the XRay data structures. SpinMutex XRayInitMutex; +// Registers XRay sleds and trampolines coming from the main executable or one +// of the linked DSOs. +// Returns the object ID if registration is successful, -1 otherwise. +int32_t +__xray_register_sleds(const XRaySledEntry *SledsBegin, + const XRaySledEntry *SledsEnd, + const XRayFunctionSledIndex *FnIndexBegin, + const XRayFunctionSledIndex *FnIndexEnd, bool FromDSO, + XRayTrampolines Trampolines) XRAY_NEVER_INSTRUMENT { + if (!SledsBegin || !SledsEnd) { + Report("Invalid XRay sleds.\n"); + return -1; + } + XRaySledMap SledMap; + SledMap.FromDSO = FromDSO; + SledMap.Loaded = true; + SledMap.Trampolines = Trampolines; + SledMap.Sleds = SledsBegin; + SledMap.Entries = SledsEnd - SledsBegin; + if (FnIndexBegin != nullptr) { + SledMap.SledsIndex = FnIndexBegin; + SledMap.Functions = FnIndexEnd - FnIndexBegin; + } else { + size_t CountFunctions = 0; + uint64_t LastFnAddr = 0; + + for (std::size_t I = 0; I < SledMap.Entries; I++) { + const auto &Sled = SledMap.Sleds[I]; + const auto Function = Sled.function(); + if (Function != LastFnAddr) { + CountFunctions++; + LastFnAddr = Function; + } + } + SledMap.SledsIndex = nullptr; + SledMap.Functions = CountFunctions; + } + if (SledMap.Functions >= XRayMaxFunctions) { + Report("Too many functions! Maximum is %ld\n", XRayMaxFunctions); + return -1; + } + + if (Verbosity()) + Report("Registering %d new functions!\n", SledMap.Functions); + + { + SpinMutexLock Guard(&XRayInstrMapMutex); + auto Idx = atomic_fetch_add(&XRayNumObjects, 1, memory_order_acq_rel); + if (Idx >= XRayMaxObjects) { + Report("Too many objects registered! Maximum is %ld\n", XRayMaxObjects); + return -1; + } + XRayInstrMaps[Idx] = std::move(SledMap); + return Idx; + } +} + // __xray_init() will do the actual loading of the current process' memory map // and then proceed to look for the .xray_instr_map section/segment. void __xray_init() XRAY_NEVER_INSTRUMENT { @@ -80,29 +141,21 @@ void __xray_init() XRAY_NEVER_INSTRUMENT { return; } - { - SpinMutexLock Guard(&XRayInstrMapMutex); - XRayInstrMap.Sleds = __start_xray_instr_map; - XRayInstrMap.Entries = __stop_xray_instr_map - __start_xray_instr_map; - if (__start_xray_fn_idx != nullptr) { - XRayInstrMap.SledsIndex = __start_xray_fn_idx; - XRayInstrMap.Functions = __stop_xray_fn_idx - __start_xray_fn_idx; - } else { - size_t CountFunctions = 0; - uint64_t LastFnAddr = 0; - - for (std::size_t I = 0; I < XRayInstrMap.Entries; I++) { - const auto &Sled = XRayInstrMap.Sleds[I]; - const auto Function = Sled.function(); - if (Function != LastFnAddr) { - CountFunctions++; - LastFnAddr = Function; - } - } + atomic_store(&XRayNumObjects, 0, memory_order_release); - XRayInstrMap.Functions = CountFunctions; - } + // Pre-allocation takes up approx. 5kB for XRayMaxObjects=64. + XRayInstrMaps = allocateBuffer(XRayMaxObjects); + + int MainBinaryId = + __xray_register_sleds(__start_xray_instr_map, __stop_xray_instr_map, + __start_xray_fn_idx, __stop_xray_fn_idx, false, {}); + + // The executable should always get ID 0. + if (MainBinaryId != 0) { + Report("Registering XRay sleds failed.\n"); + return; } + atomic_store(&XRayInitialized, true, memory_order_release); #ifndef XRAY_NO_PREINIT @@ -111,6 +164,84 @@ void __xray_init() XRAY_NEVER_INSTRUMENT { #endif } +// Registers XRay sleds and trampolines of an instrumented DSO. +// Returns the object ID if registration is successful, -1 otherwise. +// +// Default visibility is hidden, so we have to explicitly make it visible to +// DSO. +SANITIZER_INTERFACE_ATTRIBUTE int32_t __xray_register_dso( + const XRaySledEntry *SledsBegin, const XRaySledEntry *SledsEnd, + const XRayFunctionSledIndex *FnIndexBegin, + const XRayFunctionSledIndex *FnIndexEnd, + XRayTrampolines Trampolines) XRAY_NEVER_INSTRUMENT { + // Make sure XRay has been initialized in the main executable. + __xray_init(); + + if (__xray_num_objects() == 0) { + if (Verbosity()) + Report("No XRay instrumentation map in main executable. Not initializing " + "XRay for DSO.\n"); + return -1; + } + + // Register sleds in global map. + int ObjId = __xray_register_sleds(SledsBegin, SledsEnd, FnIndexBegin, + FnIndexEnd, true, Trampolines); + +#ifndef XRAY_NO_PREINIT + if (ObjId >= 0 && flags()->patch_premain) + __xray_patch_object(ObjId); +#endif + + return ObjId; +} + +// Deregisters a DSO from the main XRay runtime. +// Called from the DSO-local runtime when the library is unloaded (e.g. if +// dlclose is called). +// Returns true if the object ID is valid and the DSO was successfully +// deregistered. +SANITIZER_INTERFACE_ATTRIBUTE bool +__xray_deregister_dso(int32_t ObjId) XRAY_NEVER_INSTRUMENT { + + if (!atomic_load(&XRayInitialized, memory_order_acquire)) { + if (Verbosity()) + Report("XRay has not been initialized. Cannot deregister DSO.\n"); + return false; + } + + if (ObjId <= 0 || static_cast(ObjId) >= __xray_num_objects()) { + if (Verbosity()) + Report("Can't deregister object with ID %d: ID is invalid.\n", ObjId); + return false; + } + + { + SpinMutexLock Guard(&XRayInstrMapMutex); + auto &Entry = XRayInstrMaps[ObjId]; + if (!Entry.FromDSO) { + if (Verbosity()) + Report("Can't deregister object with ID %d: object does not correspond " + "to a shared library.\n", + ObjId); + return false; + } + if (!Entry.Loaded) { + if (Verbosity()) + Report("Can't deregister object with ID %d: object is not loaded.\n", + ObjId); + return true; + } + // Mark DSO as unloaded. No need to unpatch. + Entry.Loaded = false; + } + + if (Verbosity()) + Report("Deregistered object with ID %d.\n", ObjId); + + return true; +} + // FIXME: Make check-xray tests work on FreeBSD without // SANITIZER_CAN_USE_PREINIT_ARRAY. // See sanitizer_internal_defs.h where the macro is defined. diff --git a/compiler-rt/lib/xray/xray_interface.cpp b/compiler-rt/lib/xray/xray_interface.cpp index 5839043fcb93a..c965eda1659f8 100644 --- a/compiler-rt/lib/xray/xray_interface.cpp +++ b/compiler-rt/lib/xray/xray_interface.cpp @@ -36,7 +36,8 @@ extern __sanitizer::SpinMutex XRayInstrMapMutex; extern __sanitizer::atomic_uint8_t XRayInitialized; -extern __xray::XRaySledMap XRayInstrMap; +extern __xray::XRaySledMap *XRayInstrMaps; +extern __sanitizer::atomic_uint32_t XRayNumObjects; namespace __xray { @@ -61,16 +62,16 @@ static const int16_t cSledLength = 20; #endif /* CPU architecture */ // This is the function to call when we encounter the entry or exit sleds. -atomic_uintptr_t XRayPatchedFunction{0}; +atomic_uintptr_t XRayPatchedFunction SANITIZER_INTERFACE_ATTRIBUTE{0}; // This is the function to call from the arg1-enabled sleds/trampolines. -atomic_uintptr_t XRayArgLogger{0}; +atomic_uintptr_t XRayArgLogger SANITIZER_INTERFACE_ATTRIBUTE{0}; // This is the function to call when we encounter a custom event log call. -atomic_uintptr_t XRayPatchedCustomEvent{0}; +atomic_uintptr_t XRayPatchedCustomEvent SANITIZER_INTERFACE_ATTRIBUTE{0}; // This is the function to call when we encounter a typed event log call. -atomic_uintptr_t XRayPatchedTypedEvent{0}; +atomic_uintptr_t XRayPatchedTypedEvent SANITIZER_INTERFACE_ATTRIBUTE{0}; // This is the global status to determine whether we are currently // patching/unpatching. @@ -150,21 +151,32 @@ class MProtectHelper { namespace { -bool patchSled(const XRaySledEntry &Sled, bool Enable, - int32_t FuncId) XRAY_NEVER_INSTRUMENT { +bool isObjectLoaded(int32_t ObjId) { + SpinMutexLock Guard(&XRayInstrMapMutex); + if (ObjId < 0 || static_cast(ObjId) >= + atomic_load(&XRayNumObjects, memory_order_acquire)) { + return false; + } + return XRayInstrMaps[ObjId].Loaded; +} + +bool patchSled(const XRaySledEntry &Sled, bool Enable, int32_t FuncId, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { bool Success = false; switch (Sled.Kind) { case XRayEntryType::ENTRY: - Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry); + Success = patchFunctionEntry(Enable, FuncId, Sled, Trampolines, + /*LogArgs=*/false); break; case XRayEntryType::EXIT: - Success = patchFunctionExit(Enable, FuncId, Sled); + Success = patchFunctionExit(Enable, FuncId, Sled, Trampolines); break; case XRayEntryType::TAIL: - Success = patchFunctionTailExit(Enable, FuncId, Sled); + Success = patchFunctionTailExit(Enable, FuncId, Sled, Trampolines); break; case XRayEntryType::LOG_ARGS_ENTRY: - Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry); + Success = + patchFunctionEntry(Enable, FuncId, Sled, Trampolines, /*LogArgs=*/true); break; case XRayEntryType::CUSTOM_EVENT: Success = patchCustomEvent(Enable, FuncId, Sled); @@ -205,10 +217,9 @@ findFunctionSleds(int32_t FuncId, return Index; } -XRayPatchingStatus patchFunction(int32_t FuncId, +XRayPatchingStatus patchFunction(int32_t FuncId, int32_t ObjId, bool Enable) XRAY_NEVER_INSTRUMENT { - if (!atomic_load(&XRayInitialized, - memory_order_acquire)) + if (!atomic_load(&XRayInitialized, memory_order_acquire)) return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. uint8_t NotPatching = false; @@ -220,13 +231,24 @@ XRayPatchingStatus patchFunction(int32_t FuncId, XRaySledMap InstrMap; { SpinMutexLock Guard(&XRayInstrMapMutex); - InstrMap = XRayInstrMap; + if (ObjId < 0 || static_cast(ObjId) >= + atomic_load(&XRayNumObjects, memory_order_acquire)) { + Report("Unable to patch function: invalid sled map index: %d", ObjId); + return XRayPatchingStatus::FAILED; + } + InstrMap = XRayInstrMaps[ObjId]; } // If we don't have an index, we can't patch individual functions. if (InstrMap.Functions == 0) return XRayPatchingStatus::NOT_INITIALIZED; + // Check if the corresponding DSO has been unloaded. + if (!InstrMap.Loaded) { + Report("Invalid function id provided: %d\n", FuncId); + return XRayPatchingStatus::NOT_INITIALIZED; + } + // FuncId must be a positive number, less than the number of functions // instrumented. if (FuncId <= 0 || static_cast(FuncId) > InstrMap.Functions) { @@ -234,6 +256,8 @@ XRayPatchingStatus patchFunction(int32_t FuncId, return XRayPatchingStatus::FAILED; } + auto PackedId = __xray::MakePackedId(FuncId, ObjId); + // Now we patch ths sleds for this specific function. XRayFunctionSledIndex SledRange; if (InstrMap.SledsIndex) { @@ -242,13 +266,13 @@ XRayPatchingStatus patchFunction(int32_t FuncId, } else { SledRange = findFunctionSleds(FuncId, InstrMap); } + auto *f = SledRange.Begin; bool SucceedOnce = false; for (size_t i = 0; i != SledRange.Size; ++i) - SucceedOnce |= patchSled(f[i], Enable, FuncId); + SucceedOnce |= patchSled(f[i], Enable, PackedId, InstrMap.Trampolines); - atomic_store(&XRayPatching, false, - memory_order_release); + atomic_store(&XRayPatching, false, memory_order_release); if (!SucceedOnce) { Report("Failed patching any sled for function '%d'.", FuncId); @@ -261,32 +285,31 @@ XRayPatchingStatus patchFunction(int32_t FuncId, // controlPatching implements the common internals of the patching/unpatching // implementation. |Enable| defines whether we're enabling or disabling the // runtime XRay instrumentation. -XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT { - if (!atomic_load(&XRayInitialized, - memory_order_acquire)) - return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. - - uint8_t NotPatching = false; - if (!atomic_compare_exchange_strong( - &XRayPatching, &NotPatching, true, memory_order_acq_rel)) - return XRayPatchingStatus::ONGOING; // Already patching. - - uint8_t PatchingSuccess = false; - auto XRayPatchingStatusResetter = - at_scope_exit([&PatchingSuccess] { - if (!PatchingSuccess) - atomic_store(&XRayPatching, false, - memory_order_release); - }); - +// This function should only be called after ensuring that XRay is initialized +// and no other thread is currently patching. +XRayPatchingStatus controlPatchingObjectUnchecked(bool Enable, int32_t ObjId) { XRaySledMap InstrMap; { SpinMutexLock Guard(&XRayInstrMapMutex); - InstrMap = XRayInstrMap; + if (ObjId < 0 || static_cast(ObjId) >= + atomic_load(&XRayNumObjects, memory_order_acquire)) { + Report("Unable to patch functions: invalid sled map index: %d\n", ObjId); + return XRayPatchingStatus::FAILED; + } + InstrMap = XRayInstrMaps[ObjId]; } if (InstrMap.Entries == 0) return XRayPatchingStatus::NOT_INITIALIZED; + if (Verbosity()) + Report("Patching object %d with %d functions.\n", ObjId, InstrMap.Entries); + + // Check if the corresponding DSO has been unloaded. + if (!InstrMap.Loaded) { + Report("Object is not loaded at index: %d\n", ObjId); + return XRayPatchingStatus::FAILED; + } + uint32_t FuncId = 1; uint64_t CurFun = 0; @@ -336,20 +359,94 @@ XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT { ++FuncId; CurFun = F; } - patchSled(Sled, Enable, FuncId); + auto PackedId = __xray::MakePackedId(FuncId, ObjId); + patchSled(Sled, Enable, PackedId, InstrMap.Trampolines); } - atomic_store(&XRayPatching, false, - memory_order_release); - PatchingSuccess = true; + atomic_store(&XRayPatching, false, memory_order_release); return XRayPatchingStatus::SUCCESS; } -XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, +// Controls patching for all registered objects. +// Returns: SUCCESS, if patching succeeds for all objects. +// NOT_INITIALIZED, if one or more objects returned NOT_INITIALIZED +// but none failed. +// FAILED, if patching of one or more objects failed. +XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT { + if (!atomic_load(&XRayInitialized, memory_order_acquire)) + return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. + + uint8_t NotPatching = false; + if (!atomic_compare_exchange_strong(&XRayPatching, &NotPatching, true, + memory_order_acq_rel)) + return XRayPatchingStatus::ONGOING; // Already patching. + + auto XRayPatchingStatusResetter = at_scope_exit( + [] { atomic_store(&XRayPatching, false, memory_order_release); }); + + unsigned NumObjects = __xray_num_objects(); + + XRayPatchingStatus CombinedStatus{NOT_INITIALIZED}; + for (unsigned I = 0; I < NumObjects; ++I) { + if (!isObjectLoaded(I)) + continue; + auto LastStatus = controlPatchingObjectUnchecked(Enable, I); + switch (LastStatus) { + case SUCCESS: + if (CombinedStatus == NOT_INITIALIZED) + CombinedStatus = SUCCESS; + break; + case FAILED: + // Report failure, but try to patch the remaining objects + CombinedStatus = FAILED; + break; + case NOT_INITIALIZED: + // XRay has been initialized but there are no sleds available for this + // object. Try to patch remaining objects. + if (CombinedStatus != FAILED) + CombinedStatus = NOT_INITIALIZED; + break; + case ONGOING: + UNREACHABLE("Status ONGOING should not appear at this point"); + } + } + return CombinedStatus; +} + +// Controls patching for one object. +XRayPatchingStatus controlPatching(bool Enable, + int32_t ObjId) XRAY_NEVER_INSTRUMENT { + + if (!atomic_load(&XRayInitialized, memory_order_acquire)) + return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. + + uint8_t NotPatching = false; + if (!atomic_compare_exchange_strong(&XRayPatching, &NotPatching, true, + memory_order_acq_rel)) + return XRayPatchingStatus::ONGOING; // Already patching. + + auto XRayPatchingStatusResetter = at_scope_exit( + [] { atomic_store(&XRayPatching, false, memory_order_release); }); + + return controlPatchingObjectUnchecked(Enable, ObjId); +} + +XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, int32_t ObjId, bool Enable) XRAY_NEVER_INSTRUMENT { XRaySledMap InstrMap; { SpinMutexLock Guard(&XRayInstrMapMutex); - InstrMap = XRayInstrMap; + if (ObjId < 0 || static_cast(ObjId) >= + atomic_load(&XRayNumObjects, memory_order_acquire)) { + Report("Unable to patch function: invalid sled map index: %d\n", ObjId); + return XRayPatchingStatus::FAILED; + } + InstrMap = XRayInstrMaps[ObjId]; + } + + // Check if the corresponding DSO has been unloaded. + if (!InstrMap.Loaded) { + Report("Object is not loaded at index: %d\n", ObjId); + return XRayPatchingStatus::FAILED; } // FuncId must be a positive number, less than the number of functions @@ -398,7 +495,7 @@ XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, Report("Failed mprotect: %d\n", errno); return XRayPatchingStatus::FAILED; } - return patchFunction(FuncId, Enable); + return patchFunction(FuncId, ObjId, Enable); } } // namespace @@ -412,12 +509,10 @@ using namespace __xray; int __xray_set_handler(void (*entry)(int32_t, XRayEntryType)) XRAY_NEVER_INSTRUMENT { - if (atomic_load(&XRayInitialized, - memory_order_acquire)) { + if (atomic_load(&XRayInitialized, memory_order_acquire)) { atomic_store(&__xray::XRayPatchedFunction, - reinterpret_cast(entry), - memory_order_release); + reinterpret_cast(entry), memory_order_release); return 1; } return 0; @@ -425,11 +520,9 @@ int __xray_set_handler(void (*entry)(int32_t, int __xray_set_customevent_handler(void (*entry)(void *, size_t)) XRAY_NEVER_INSTRUMENT { - if (atomic_load(&XRayInitialized, - memory_order_acquire)) { + if (atomic_load(&XRayInitialized, memory_order_acquire)) { atomic_store(&__xray::XRayPatchedCustomEvent, - reinterpret_cast(entry), - memory_order_release); + reinterpret_cast(entry), memory_order_release); return 1; } return 0; @@ -437,11 +530,9 @@ int __xray_set_customevent_handler(void (*entry)(void *, size_t)) int __xray_set_typedevent_handler(void (*entry)(size_t, const void *, size_t)) XRAY_NEVER_INSTRUMENT { - if (atomic_load(&XRayInitialized, - memory_order_acquire)) { + if (atomic_load(&XRayInitialized, memory_order_acquire)) { atomic_store(&__xray::XRayPatchedTypedEvent, - reinterpret_cast(entry), - memory_order_release); + reinterpret_cast(entry), memory_order_release); return 1; } return 0; @@ -474,39 +565,78 @@ XRayPatchingStatus __xray_patch() XRAY_NEVER_INSTRUMENT { return controlPatching(true); } +XRayPatchingStatus __xray_patch_object(int32_t ObjId) XRAY_NEVER_INSTRUMENT { + return controlPatching(true, ObjId); +} + XRayPatchingStatus __xray_unpatch() XRAY_NEVER_INSTRUMENT { return controlPatching(false); } +XRayPatchingStatus __xray_unpatch_object(int32_t ObjId) XRAY_NEVER_INSTRUMENT { + return controlPatching(false, ObjId); +} + XRayPatchingStatus __xray_patch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT { - return mprotectAndPatchFunction(FuncId, true); + auto Ids = __xray::UnpackId(FuncId); + auto ObjId = Ids.first; + auto FnId = Ids.second; + return mprotectAndPatchFunction(FnId, ObjId, true); +} + +XRayPatchingStatus +__xray_patch_function_in_object(int32_t FuncId, + int32_t ObjId) XRAY_NEVER_INSTRUMENT { + return mprotectAndPatchFunction(FuncId, ObjId, true); } XRayPatchingStatus __xray_unpatch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT { - return mprotectAndPatchFunction(FuncId, false); + auto Ids = __xray::UnpackId(FuncId); + auto ObjId = Ids.first; + auto FnId = Ids.second; + return mprotectAndPatchFunction(FnId, ObjId, false); +} + +XRayPatchingStatus +__xray_unpatch_function_in_object(int32_t FuncId, + int32_t ObjId) XRAY_NEVER_INSTRUMENT { + return mprotectAndPatchFunction(FuncId, ObjId, false); } int __xray_set_handler_arg1(void (*entry)(int32_t, XRayEntryType, uint64_t)) { - if (!atomic_load(&XRayInitialized, - memory_order_acquire)) + if (!atomic_load(&XRayInitialized, memory_order_acquire)) return 0; // A relaxed write might not be visible even if the current thread gets // scheduled on a different CPU/NUMA node. We need to wait for everyone to // have this handler installed for consistency of collected data across CPUs. atomic_store(&XRayArgLogger, reinterpret_cast(entry), - memory_order_release); + memory_order_release); return 1; } int __xray_remove_handler_arg1() { return __xray_set_handler_arg1(nullptr); } -uintptr_t __xray_function_address(int32_t FuncId) XRAY_NEVER_INSTRUMENT { +uintptr_t +__xray_function_address(int32_t CombinedFuncId) XRAY_NEVER_INSTRUMENT { + auto Ids = __xray::UnpackId(CombinedFuncId); + return __xray_function_address_in_object(Ids.second, Ids.first); +} + +uintptr_t __xray_function_address_in_object(int32_t FuncId, int32_t ObjId) + XRAY_NEVER_INSTRUMENT { XRaySledMap InstrMap; { SpinMutexLock Guard(&XRayInstrMapMutex); - InstrMap = XRayInstrMap; + auto count = atomic_load(&XRayNumObjects, memory_order_acquire); + if (ObjId < 0 || static_cast(ObjId) >= count) { + Report("Unable to determine function address: invalid sled map index %d " + "(size is %d)\n", + ObjId, (int)count); + return 0; + } + InstrMap = XRayInstrMaps[ObjId]; } if (FuncId <= 0 || static_cast(FuncId) > InstrMap.Functions) @@ -525,6 +655,30 @@ uintptr_t __xray_function_address(int32_t FuncId) XRAY_NEVER_INSTRUMENT { } size_t __xray_max_function_id() XRAY_NEVER_INSTRUMENT { + return __xray_max_function_id_in_object(0); +} + +size_t __xray_max_function_id_in_object(int32_t ObjId) XRAY_NEVER_INSTRUMENT { + SpinMutexLock Guard(&XRayInstrMapMutex); + if (ObjId < 0 || static_cast(ObjId) >= + atomic_load(&XRayNumObjects, memory_order_acquire)) + return 0; + return XRayInstrMaps[ObjId].Functions; +} + +size_t __xray_num_objects() XRAY_NEVER_INSTRUMENT { SpinMutexLock Guard(&XRayInstrMapMutex); - return XRayInstrMap.Functions; + return atomic_load(&XRayNumObjects, memory_order_acquire); +} + +int32_t __xray_unpack_function_id(int32_t PackedId) { + return __xray::UnpackId(PackedId).second; +} + +int32_t __xray_unpack_object_id(int32_t PackedId) { + return __xray::UnpackId(PackedId).first; +} + +int32_t __xray_pack_id(int32_t FuncId, int32_t ObjId) { + return __xray::MakePackedId(FuncId, ObjId); } diff --git a/compiler-rt/lib/xray/xray_interface_internal.h b/compiler-rt/lib/xray/xray_interface_internal.h index 80c07c167f646..a8cfe0fde84dd 100644 --- a/compiler-rt/lib/xray/xray_interface_internal.h +++ b/compiler-rt/lib/xray/xray_interface_internal.h @@ -18,6 +18,18 @@ #include "xray/xray_interface.h" #include #include +#include + +extern "C" { +// The following functions have to be defined in assembler, on a per-platform +// basis. See xray_trampoline_*.S files for implementations. +extern void __xray_FunctionEntry(); +extern void __xray_FunctionExit(); +extern void __xray_FunctionTailExit(); +extern void __xray_ArgLoggerEntry(); +extern void __xray_CustomEvent(); +extern void __xray_TypedEvent(); +} extern "C" { @@ -67,36 +79,72 @@ struct XRayFunctionSledIndex { uintptr_t(Begin)); } }; + +struct XRayTrampolines { + void (*EntryTrampoline)(); + void (*ExitTrampoline)(); + void (*TailExitTrampoline)(); + void (*LogArgsTrampoline)(); + + XRayTrampolines() { + // These resolve to the definitions in the respective executable or DSO. + EntryTrampoline = __xray_FunctionEntry; + ExitTrampoline = __xray_FunctionExit; + TailExitTrampoline = __xray_FunctionTailExit; + LogArgsTrampoline = __xray_ArgLoggerEntry; + } +}; + +extern int32_t __xray_register_dso(const XRaySledEntry *SledsBegin, + const XRaySledEntry *SledsEnd, + const XRayFunctionSledIndex *FnIndexBegin, + const XRayFunctionSledIndex *FnIndexEnd, + XRayTrampolines Trampolines); + +extern bool __xray_deregister_dso(int32_t ObjId); } namespace __xray { +constexpr uint32_t XRayNFnBits = 24; +constexpr uint32_t XRayNObjBits = 8; + +constexpr uint32_t XRayFnBitMask = 0x00FFFFFF; +constexpr uint32_t XRayObjBitMask = 0xFF000000; + +constexpr size_t XRayMaxFunctions = 1 << XRayNFnBits; +constexpr size_t XRayMaxObjects = 1 << XRayNObjBits; + +inline int32_t MakePackedId(int32_t FnId, int32_t ObjId) { + return ((ObjId << XRayNFnBits) & XRayObjBitMask) | (FnId & XRayFnBitMask); +} + +inline std::pair UnpackId(int32_t PackedId) { + uint32_t ObjId = (PackedId & XRayObjBitMask) >> XRayNFnBits; + uint32_t FnId = PackedId & XRayFnBitMask; + return {ObjId, FnId}; +} + struct XRaySledMap { const XRaySledEntry *Sleds; size_t Entries; const XRayFunctionSledIndex *SledsIndex; size_t Functions; + XRayTrampolines Trampolines; + bool FromDSO; + bool Loaded; }; bool patchFunctionEntry(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()); -bool patchFunctionExit(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); + const XRayTrampolines &Trampolines, bool LogArgs); +bool patchFunctionExit(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines); bool patchFunctionTailExit(bool Enable, uint32_t FuncId, - const XRaySledEntry &Sled); + const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines); bool patchCustomEvent(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); bool patchTypedEvent(bool Enable, uint32_t FuncId, const XRaySledEntry &Sled); } // namespace __xray -extern "C" { -// The following functions have to be defined in assembler, on a per-platform -// basis. See xray_trampoline_*.S files for implementations. -extern void __xray_FunctionEntry(); -extern void __xray_FunctionExit(); -extern void __xray_FunctionTailExit(); -extern void __xray_ArgLoggerEntry(); -extern void __xray_CustomEvent(); -extern void __xray_TypedEvent(); -} - #endif diff --git a/compiler-rt/lib/xray/xray_loongarch64.cpp b/compiler-rt/lib/xray/xray_loongarch64.cpp index b839adba00d22..b72417d4f2aad 100644 --- a/compiler-rt/lib/xray/xray_loongarch64.cpp +++ b/compiler-rt/lib/xray/xray_loongarch64.cpp @@ -126,20 +126,25 @@ static inline bool patchSled(const bool Enable, const uint32_t FuncId, bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRayTrampolines &Trampolines, + bool LogArgs) XRAY_NEVER_INSTRUMENT { + auto Trampoline = + LogArgs ? Trampolines.LogArgsTrampoline : Trampolines.EntryTrampoline; return patchSled(Enable, FuncId, Sled, Trampoline); } -bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); +bool patchFunctionExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } -bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { +bool patchFunctionTailExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { // TODO: In the future we'd need to distinguish between non-tail exits and // tail exits for better information preservation. - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } bool patchCustomEvent(const bool Enable, const uint32_t FuncId, @@ -158,3 +163,7 @@ bool patchTypedEvent(const bool Enable, const uint32_t FuncId, extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT { // TODO: This will have to be implemented in the trampoline assembly file. } + +extern "C" void __xray_FunctionTailExit() XRAY_NEVER_INSTRUMENT { + // FIXME: this will have to be implemented in the trampoline assembly file +} diff --git a/compiler-rt/lib/xray/xray_mips.cpp b/compiler-rt/lib/xray/xray_mips.cpp index dc9e837a555dd..4d2a7c82bddb9 100644 --- a/compiler-rt/lib/xray/xray_mips.cpp +++ b/compiler-rt/lib/xray/xray_mips.cpp @@ -136,20 +136,25 @@ inline static bool patchSled(const bool Enable, const uint32_t FuncId, bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRayTrampolines &Trampolines, + bool LogArgs) XRAY_NEVER_INSTRUMENT { + auto Trampoline = + LogArgs ? Trampolines.LogArgsTrampoline : Trampolines.EntryTrampoline; return patchSled(Enable, FuncId, Sled, Trampoline); } -bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); +bool patchFunctionExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } -bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { +bool patchFunctionTailExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { // FIXME: In the future we'd need to distinguish between non-tail exits and // tail exits for better information preservation. - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } bool patchCustomEvent(const bool Enable, const uint32_t FuncId, @@ -169,3 +174,7 @@ bool patchTypedEvent(const bool Enable, const uint32_t FuncId, extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT { // FIXME: this will have to be implemented in the trampoline assembly file } + +extern "C" void __xray_FunctionTailExit() XRAY_NEVER_INSTRUMENT { + // FIXME: this will have to be implemented in the trampoline assembly file +} \ No newline at end of file diff --git a/compiler-rt/lib/xray/xray_mips64.cpp b/compiler-rt/lib/xray/xray_mips64.cpp index 5b221bb6ddc05..a088a322cc156 100644 --- a/compiler-rt/lib/xray/xray_mips64.cpp +++ b/compiler-rt/lib/xray/xray_mips64.cpp @@ -144,20 +144,25 @@ inline static bool patchSled(const bool Enable, const uint32_t FuncId, bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRayTrampolines &Trampolines, + bool LogArgs) XRAY_NEVER_INSTRUMENT { + auto Trampoline = + LogArgs ? Trampolines.LogArgsTrampoline : Trampolines.EntryTrampoline; return patchSled(Enable, FuncId, Sled, Trampoline); } -bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); +bool patchFunctionExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } -bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { +bool patchFunctionTailExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { // FIXME: In the future we'd need to distinguish between non-tail exits and // tail exits for better information preservation. - return patchSled(Enable, FuncId, Sled, __xray_FunctionExit); + return patchSled(Enable, FuncId, Sled, Trampolines.ExitTrampoline); } bool patchCustomEvent(const bool Enable, const uint32_t FuncId, @@ -176,3 +181,7 @@ bool patchTypedEvent(const bool Enable, const uint32_t FuncId, extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT { // FIXME: this will have to be implemented in the trampoline assembly file } + +extern "C" void __xray_FunctionTailExit() XRAY_NEVER_INSTRUMENT { + // FIXME: this will have to be implemented in the trampoline assembly file +} diff --git a/compiler-rt/lib/xray/xray_powerpc64.cpp b/compiler-rt/lib/xray/xray_powerpc64.cpp index c3553d848313f..a568c568c4186 100644 --- a/compiler-rt/lib/xray/xray_powerpc64.cpp +++ b/compiler-rt/lib/xray/xray_powerpc64.cpp @@ -51,7 +51,12 @@ namespace __xray { bool patchFunctionEntry(const bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRayTrampolines &Trampolines, + bool LogArgs) XRAY_NEVER_INSTRUMENT { + // TODO: Trampoline addresses are currently inserted at compile-time, using + // __xray_FunctionEntry and __xray_FunctionExit only. + // To support DSO instrumentation, trampolines have to be written during + // patching (see implementation on X86_64, e.g.). const uint64_t Address = Sled.address(); if (Enable) { // lis 0, FuncId[16..32] @@ -68,8 +73,13 @@ bool patchFunctionEntry(const bool Enable, uint32_t FuncId, return true; } -bool patchFunctionExit(const bool Enable, uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { +bool patchFunctionExit( + const bool Enable, uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + // TODO: Trampoline addresses are currently inserted at compile-time, using + // __xray_FunctionEntry and __xray_FunctionExit only. + // To support DSO instrumentation, trampolines have to be written during + // patching (see implementation on X86_64, e.g.). const uint64_t Address = Sled.address(); if (Enable) { // lis 0, FuncId[16..32] @@ -86,9 +96,10 @@ bool patchFunctionExit(const bool Enable, uint32_t FuncId, return true; } -bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { - return patchFunctionExit(Enable, FuncId, Sled); +bool patchFunctionTailExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { + return patchFunctionExit(Enable, FuncId, Sled, Trampolines); } // FIXME: Maybe implement this better? @@ -111,3 +122,10 @@ bool patchTypedEvent(const bool Enable, const uint32_t FuncId, extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT { // FIXME: this will have to be implemented in the trampoline assembly file } + +extern "C" void __xray_FunctionTailExit() XRAY_NEVER_INSTRUMENT { + // For PowerPC, calls to __xray_FunctionEntry and __xray_FunctionExit + // are statically inserted into the sled. Tail exits are handled like normal + // function exits. This trampoline is therefore not implemented. + // This stub is placed here to avoid linking issues. +} diff --git a/compiler-rt/lib/xray/xray_trampoline_x86_64.S b/compiler-rt/lib/xray/xray_trampoline_x86_64.S index 01098f60eeab8..0f480547b52cc 100644 --- a/compiler-rt/lib/xray/xray_trampoline_x86_64.S +++ b/compiler-rt/lib/xray/xray_trampoline_x86_64.S @@ -107,6 +107,16 @@ .section __TEXT,__text #endif +.macro LOAD_HANDLER_ADDR handler +#if !defined(XRAY_PIC) + movq ASM_SYMBOL(\handler)(%rip), %rax +#else + movq ASM_SYMBOL(\handler)@GOTPCREL(%rip), %rax + movq (%rax), %rax +#endif +.endm + + //===----------------------------------------------------------------------===// .globl ASM_SYMBOL(__xray_FunctionEntry) @@ -121,7 +131,7 @@ ASM_SYMBOL(__xray_FunctionEntry): // This load has to be atomic, it's concurrent with __xray_patch(). // On x86/amd64, a simple (type-aligned) MOV instruction is enough. - movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax + LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE testq %rax, %rax je LOCAL_LABEL(tmp0) @@ -159,7 +169,7 @@ ASM_SYMBOL(__xray_FunctionExit): movupd %xmm1, 16(%rsp) movq %rax, 8(%rsp) movq %rdx, 0(%rsp) - movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax + LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE testq %rax,%rax je LOCAL_LABEL(tmp2) @@ -195,7 +205,7 @@ ASM_SYMBOL(__xray_FunctionTailExit): SAVE_REGISTERS ALIGN_STACK_16B - movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax + LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE testq %rax,%rax je LOCAL_LABEL(tmp4) @@ -224,12 +234,12 @@ ASM_SYMBOL(__xray_ArgLoggerEntry): ALIGN_STACK_16B // Again, these function pointer loads must be atomic; MOV is fine. - movq ASM_SYMBOL(_ZN6__xray13XRayArgLoggerE)(%rip), %rax + LOAD_HANDLER_ADDR _ZN6__xray13XRayArgLoggerE testq %rax, %rax jne LOCAL_LABEL(arg1entryLog) // If [arg1 logging handler] not set, defer to no-arg logging. - movq ASM_SYMBOL(_ZN6__xray19XRayPatchedFunctionE)(%rip), %rax + LOAD_HANDLER_ADDR _ZN6__xray19XRayPatchedFunctionE testq %rax, %rax je LOCAL_LABEL(arg1entryFail) @@ -268,7 +278,7 @@ ASM_SYMBOL(__xray_CustomEvent): // We take two arguments to this trampoline, which should be in rdi and rsi // already. - movq ASM_SYMBOL(_ZN6__xray22XRayPatchedCustomEventE)(%rip), %rax + LOAD_HANDLER_ADDR _ZN6__xray22XRayPatchedCustomEventE testq %rax,%rax je LOCAL_LABEL(customEventCleanup) @@ -293,7 +303,7 @@ ASM_SYMBOL(__xray_TypedEvent): // We pass three arguments to this trampoline, which should be in rdi, rsi // and rdx without our intervention. - movq ASM_SYMBOL(_ZN6__xray21XRayPatchedTypedEventE)(%rip), %rax + LOAD_HANDLER_ADDR _ZN6__xray21XRayPatchedTypedEventE testq %rax,%rax je LOCAL_LABEL(typedEventCleanup) diff --git a/compiler-rt/lib/xray/xray_x86_64.cpp b/compiler-rt/lib/xray/xray_x86_64.cpp index b9666a40861d4..8542351ca2689 100644 --- a/compiler-rt/lib/xray/xray_x86_64.cpp +++ b/compiler-rt/lib/xray/xray_x86_64.cpp @@ -122,7 +122,8 @@ static constexpr int64_t MaxOffset{std::numeric_limits::max()}; bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, - void (*Trampoline)()) XRAY_NEVER_INSTRUMENT { + const XRayTrampolines &Trampolines, + bool LogArgs) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the following sled: // // xray_sled_n: @@ -144,6 +145,8 @@ bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, // opcode and first operand. // // Prerequisite is to compute the relative offset to the trampoline's address. + auto Trampoline = + LogArgs ? Trampolines.LogArgsTrampoline : Trampolines.EntryTrampoline; const uint64_t Address = Sled.address(); int64_t TrampolineOffset = reinterpret_cast(Trampoline) - (static_cast(Address) + 11); @@ -169,8 +172,9 @@ bool patchFunctionEntry(const bool Enable, const uint32_t FuncId, return true; } -bool patchFunctionExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { +bool patchFunctionExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the following sled: // // xray_sled_n: @@ -191,12 +195,13 @@ bool patchFunctionExit(const bool Enable, const uint32_t FuncId, // // Prerequisite is to compute the relative offset fo the // __xray_FunctionExit function's address. + auto Trampoline = Trampolines.ExitTrampoline; const uint64_t Address = Sled.address(); - int64_t TrampolineOffset = reinterpret_cast(__xray_FunctionExit) - + int64_t TrampolineOffset = reinterpret_cast(Trampoline) - (static_cast(Address) + 11); if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) { Report("XRay Exit trampoline (%p) too far from sled (%p)\n", - reinterpret_cast(__xray_FunctionExit), + reinterpret_cast(Trampoline), reinterpret_cast(Address)); return false; } @@ -216,17 +221,18 @@ bool patchFunctionExit(const bool Enable, const uint32_t FuncId, return true; } -bool patchFunctionTailExit(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { +bool patchFunctionTailExit( + const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled, + const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the tail call sled with a similar // sequence as the entry sled, but calls the tail exit sled instead. + auto Trampoline = Trampolines.TailExitTrampoline; const uint64_t Address = Sled.address(); - int64_t TrampolineOffset = - reinterpret_cast(__xray_FunctionTailExit) - - (static_cast(Address) + 11); + int64_t TrampolineOffset = reinterpret_cast(Trampoline) - + (static_cast(Address) + 11); if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) { Report("XRay Tail Exit trampoline (%p) too far from sled (%p)\n", - reinterpret_cast(__xray_FunctionTailExit), + reinterpret_cast(Trampoline), reinterpret_cast(Address)); return false; } @@ -275,7 +281,7 @@ bool patchCustomEvent(const bool Enable, const uint32_t FuncId, } bool patchTypedEvent(const bool Enable, const uint32_t FuncId, - const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { + const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT { // Here we do the dance of replacing the following sled: // // xray_sled_n: diff --git a/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cpp b/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cpp index 9277fe0b23516..38e99cf685945 100644 --- a/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/delay_dbghelp.cpp @@ -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 extern "C" int puts(const char *); diff --git a/compiler-rt/test/ubsan/TestCases/Misc/Posix/static-link.cpp b/compiler-rt/test/ubsan/TestCases/Misc/Posix/static-link.cpp index 2d65330ef2894..081eec049e3fc 100644 --- a/compiler-rt/test/ubsan/TestCases/Misc/Posix/static-link.cpp +++ b/compiler-rt/test/ubsan/TestCases/Misc/Posix/static-link.cpp @@ -1,8 +1,13 @@ +// RUN: %clangxx -fsanitize=bool -static %s -o %t && env UBSAN_OPTIONS=handle_segv=0:handle_sigbus=0:handle_sigfpe=0 %run %t 2>&1 | FileCheck %s +// RUN: %run %t 2>&1 | FileCheck %s + // REQUIRES: ubsan-standalone // REQUIRES: target={{x86_64.*}} // UNSUPPORTED: i386-target-arch, internal_symbolizer -// RUN: %clangxx -fsanitize=bool -static %s -o %t && env UBSAN_OPTIONS=handle_segv=0:handle_sigbus=0:handle_sigfpe=0 %run %t 2>&1 | FileCheck %s -// RUN: %run %t 2>&1 | FileCheck %s + +// Does not link. +// UNSUPPORTED: darwin + #include #include diff --git a/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp new file mode 100644 index 0000000000000..31c615bd1f81b --- /dev/null +++ b/compiler-rt/test/xray/TestCases/Posix/basic-mode-dso.cpp @@ -0,0 +1,47 @@ +// Testing shared library support in basic logging mode. + +// RUN: split-file %s %t +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testlib.so -Wl,-rpath,%t -o %t/main.o + +// RUN: XRAY_OPTIONS="patch_premain=false,xray_mode=xray-basic,xray_logfile_base=basic-mode-dso-,verbosity=1" XRAY_BASIC_OPTIONS="func_duration_threshold_us=0" %run %t/main.o 2>&1 | FileCheck %s +// RUN: %llvm_xray account --format=csv --sort=funcid "`ls basic-mode-dso-* | head -1`" | FileCheck --check-prefix=ACCOUNT %s +// RUN: rm basic-mode-dso-* + +// REQUIRES: target=x86_64{{.*}} + +//--- main.cpp + +#include "xray/xray_interface.h" + +#include +#include + +[[clang::xray_always_instrument]] void instrumented_in_executable() { + printf("instrumented_in_executable called\n"); + sleep(1); +} + +extern void instrumented_in_dso(); + +int main() { + // Explicit patching to ensure the DSO has been loaded + __xray_patch(); + instrumented_in_executable(); + // CHECK: instrumented_in_executable called + instrumented_in_dso(); + // CHECK-NEXT: instrumented_in_dso called +} + +//--- testlib.cpp + +#include +#include + +[[clang::xray_always_instrument]] void instrumented_in_dso() { + printf("instrumented_in_dso called\n"); +} + +// ACCOUNT: funcid,count,min,median,90%ile,99%ile,max,sum,debug,function +// ACCOUNT-NEXT: 1,1,{{.*}} +// ACCOUNT-NEXT: 16777217,1,{{.*}} diff --git a/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp b/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp new file mode 100644 index 0000000000000..92f3c29e970d4 --- /dev/null +++ b/compiler-rt/test/xray/TestCases/Posix/clang-xray-shared.cpp @@ -0,0 +1,14 @@ +// Test that the DSO-local runtime library has been linked if -fxray-shared is passed. +// +// RUN: %clangxx -fxray-instrument -fxray-shared %s -shared -o %t.so +// RUN: llvm-nm %t.so | FileCheck %s --check-prefix ENABLED + +// RUN: %clangxx -fxray-instrument %s -shared -o %t.so +// RUN: llvm-nm %t.so | FileCheck %s --check-prefix DISABLED +// +// REQUIRES: target=x86_64{{.*}} + +[[clang::xray_always_instrument]] int always_instrumented() { return 42; } + +// ENABLED: __start_xray_instr_map +// DISABLED-NOT: __start_xray_instr_map diff --git a/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp b/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp new file mode 100644 index 0000000000000..9db411d5ff1c6 --- /dev/null +++ b/compiler-rt/test/xray/TestCases/Posix/dlopen.cpp @@ -0,0 +1,107 @@ +// Check that we can patch and un-patch DSOs loaded with dlopen. +// + +// RUN: split-file %s %t +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so +// RUN: %clangxx_xray -g -fPIC -rdynamic -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp -o %t/main.o +// +// RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlib.so 2>&1 | FileCheck %s + +// REQUIRES: target=x86_64{{.*}} + +//--- main.cpp + +#include "xray/xray_interface.h" + +#include +#include + +void test_handler(int32_t fid, XRayEntryType type) { + printf("called: %d, type=%d\n", fid, static_cast(type)); +} + +[[clang::xray_always_instrument]] void instrumented_in_executable() { + printf("instrumented_in_executable called\n"); +} + +typedef void (*dso_func_type)(); + +int main(int argc, char **argv) { + if (argc < 2) { + printf("Shared library argument missing\n"); + // CHECK-NOT: Shared library argument missing + return 1; + } + + const char *dso_path = argv[1]; + + void *dso_handle = dlopen(dso_path, RTLD_LAZY); + if (!dso_handle) { + printf("Failed to load shared library\n"); + char *error = dlerror(); + if (error) { + fprintf(stderr, "%s\n", error); + return 1; + } + return 1; + } + + dso_func_type instrumented_in_dso = + (dso_func_type)dlsym(dso_handle, "_Z19instrumented_in_dsov"); + if (!instrumented_in_dso) { + printf("Failed to find symbol\n"); + char *error = dlerror(); + if (error) { + fprintf(stderr, "%s\n", error); + return 1; + } + return 1; + } + + __xray_set_handler(test_handler); + + instrumented_in_executable(); + // CHECK: called: {{.*}}, type=0 + // CHECK-NEXT: instrumented_in_executable called + // CHECK-NEXT: called: {{.*}}, type=1 + instrumented_in_dso(); + // CHECK-NEXT: called: {{.*}}, type=0 + // CHECK-NEXT: instrumented_in_dso called + // CHECK-NEXT: called: {{.*}}, type=1 + + auto status = __xray_unpatch(); + printf("unpatching status: %d\n", static_cast(status)); + // CHECK-NEXT: unpatching status: 1 + + instrumented_in_executable(); + // CHECK-NEXT: instrumented_in_executable called + instrumented_in_dso(); + // CHECK-NEXT: instrumented_in_dso called + + status = __xray_patch(); + printf("patching status: %d\n", static_cast(status)); + // CHECK-NEXT: patching status: 1 + + instrumented_in_executable(); + // CHECK-NEXT: called: {{.*}}, type=0 + // CHECK-NEXT: instrumented_in_executable called + // CHECK-NEXT: called: {{.*}}, type=1 + instrumented_in_dso(); + // CHECK-NEXT: called: {{.*}}, type=0 + // CHECK-NEXT: instrumented_in_dso called + // CHECK-NEXT: called: {{.*}}, type=1 + + dlclose(dso_handle); + + status = __xray_unpatch(); + printf("unpatching status: %d\n", static_cast(status)); + // CHECK-NEXT: unpatching status: 1 +} + +//--- testlib.cpp + +#include + +[[clang::xray_always_instrument]] void instrumented_in_dso() { + printf("instrumented_in_dso called\n"); +} diff --git a/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp b/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp new file mode 100644 index 0000000000000..89da2764c35ce --- /dev/null +++ b/compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp @@ -0,0 +1,197 @@ +// Check that loading libraries with different modes (RTLD_LOCAL/RTLD_GLOBAL) +// and dependencies on other DSOs work correctly. +// + +// RUN: split-file %s %t +// +// Build shared libs with dependencies b->c and e->f +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testliba.cpp -o %t/testliba.so +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibc.cpp -o %t/testlibc.so +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibb.cpp %t/testlibc.so -o %t/testlibb.so +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibd.cpp -o %t/testlibd.so +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibf.cpp -o %t/testlibf.so +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibe.cpp %t/testlibf.so -o %t/testlibe.so +// +// Executable links with a and b explicitly and loads d and e at runtime. +// RUN: %clangxx_xray -g -fPIC -rdynamic -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testliba.so %t/testlibb.so -o %t/main.o +// +// RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlibd.so %t/testlibe.so 2>&1 | FileCheck %s + +// REQUIRES: target=x86_64{{.*}} + +//--- main.cpp + +#include "xray/xray_interface.h" + +#include +#include + +[[clang::xray_never_instrument]] void test_handler(int32_t fid, + XRayEntryType type) { + printf("called: %d, object=%d, fn=%d, type=%d\n", fid, (fid >> 24) & 0xFF, + fid & 0x00FFFFFF, static_cast(type)); +} + +[[clang::xray_always_instrument]] void instrumented_in_executable() { + printf("instrumented_in_executable called\n"); +} + +typedef void (*dso_func_type)(); + +[[clang::xray_never_instrument]] void *load_dso(const char *path, int mode) { + void *dso_handle = dlopen(path, mode); + if (!dso_handle) { + printf("failed to load shared library\n"); + char *error = dlerror(); + if (error) { + fprintf(stderr, "%s\n", error); + } + return nullptr; + } + return dso_handle; +} + +[[clang::xray_never_instrument]] void find_and_call(void *dso_handle, + const char *fn) { + dso_func_type dso_fn = (dso_func_type)dlsym(dso_handle, fn); + if (!dso_fn) { + printf("failed to find symbol\n"); + char *error = dlerror(); + if (error) { + fprintf(stderr, "%s\n", error); + } + return; + } + dso_fn(); +} + +extern void a(); +extern void b(); + +int main(int argc, char **argv) { + + if (argc < 3) { + printf("Shared library arguments missing\n"); + // CHECK-NOT: Shared library arguments missing + return 1; + } + + const char *dso_path_d = argv[1]; + const char *dso_path_e = argv[2]; + + __xray_set_handler(test_handler); + + instrumented_in_executable(); + // CHECK: called: {{[0-9]+}}, object=0, fn={{[0-9]+}}, type=0 + // CHECK-NEXT: instrumented_in_executable called + // CHECK-NEXT: called: {{[0-9]+}}, object=0, fn={{[0-9]+}}, type=1 + + a(); + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ1:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: a called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ1]], fn=1, type=1 + + // Make sure this object ID does not appear again + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ1]] + + b(); // b calls c + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ2:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: b called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ3:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: c called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ3]], fn=1, type=1 + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ3]] + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ2]], fn=1, type=1 + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ2]] + + // Now check explicit loading with RTLD_LOCAL + + void *dso_handle_d = load_dso(dso_path_d, RTLD_LAZY | RTLD_LOCAL); + void *dso_handle_e = load_dso(dso_path_e, RTLD_LAZY | RTLD_LOCAL); + // CHECK-NOT: failed to load shared library + + find_and_call(dso_handle_d, "_Z1dv"); + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ4:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: d called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ4]], fn=1, type=1 + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ4]] + + find_and_call(dso_handle_e, "_Z1ev"); + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ5:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: e called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ6:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: f called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ6]], fn=1, type=1 + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ6]] + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ5]], fn=1, type=1 + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ5]] + + // Unload DSOs + dlclose(dso_handle_d); + dlclose(dso_handle_e); + + // Repeat test with RTLD_GLOBAL + dso_handle_d = load_dso(dso_path_d, RTLD_LAZY | RTLD_GLOBAL); + dso_handle_e = load_dso(dso_path_e, RTLD_LAZY | RTLD_GLOBAL); + // CHECK-NOT: failed to load shared library + + find_and_call(dso_handle_d, "_Z1dv"); + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ7:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: d called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ7]], fn=1, type=1 + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ7]] + + find_and_call(dso_handle_e, "_Z1ev"); + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ8:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: e called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ9:[0-9]+]], fn=1, type=0 + // CHECK-NEXT: f called + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ9]], fn=1, type=1 + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ9]] + // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ8]], fn=1, type=1 + // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ8]] + + auto status = __xray_unpatch(); + printf("unpatching status: %d\n", static_cast(status)); + // CHECK-NEXT: unpatching status: 1 + + dlclose(dso_handle_d); + dlclose(dso_handle_e); +} + +//--- libgenmacro.inc +#include +// Helper macros to quickly generate libraries containing a single function. +#define GENERATE_LIB(NAME) \ + [[clang::xray_always_instrument]] void NAME() { printf(#NAME " called\n"); } + +#define GENERATE_LIB_WITH_CALL(NAME, FN) \ + extern void FN(); \ + [[clang::xray_always_instrument]] void NAME() { \ + printf(#NAME " called\n"); \ + FN(); \ + } + +//--- testliba.cpp +#include "libgenmacro.inc" +GENERATE_LIB(a) + +//--- testlibb.cpp +#include "libgenmacro.inc" +GENERATE_LIB_WITH_CALL(b, c) + +//--- testlibc.cpp +#include "libgenmacro.inc" +GENERATE_LIB(c) + +//--- testlibd.cpp +#include "libgenmacro.inc" +GENERATE_LIB(d) + +//--- testlibe.cpp +#include "libgenmacro.inc" +GENERATE_LIB_WITH_CALL(e, f) + +//--- testlibf.cpp +#include "libgenmacro.inc" +GENERATE_LIB(f) diff --git a/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp new file mode 100644 index 0000000000000..0708d0383439d --- /dev/null +++ b/compiler-rt/test/xray/TestCases/Posix/patch-premain-dso.cpp @@ -0,0 +1,45 @@ +// Checking that DSOs are automatically patched upon load, if patch_premain is passed. + +// RUN: split-file %s %t +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testlib.so -Wl,-rpath,%t -o %t/main.o + +// RUN: XRAY_OPTIONS="patch_premain=true,verbosity=1" %run %t/main.o 2>&1 | FileCheck %s + +// REQUIRES: target=x86_64{{.*}} + +//--- main.cpp + +#include "xray/xray_interface.h" + +#include + +void test_handler(int32_t fid, XRayEntryType type) { + printf("called: %d, type=%d\n", fid, static_cast(type)); +} + +[[clang::xray_always_instrument]] void instrumented_in_executable() { + printf("instrumented_in_executable called\n"); +} + +extern void instrumented_in_dso(); + +int main() { + __xray_set_handler(test_handler); + instrumented_in_executable(); + // CHECK: called: {{.*}}, type=0 + // CHECK-NEXT: instrumented_in_executable called + // CHECK-NEXT: called: {{.*}}, type=1 + instrumented_in_dso(); + // CHECK-NEXT: called: {{.*}}, type=0 + // CHECK-NEXT: instrumented_in_dso called + // CHECK-NEXT: called: {{.*}}, type=1 +} + +//--- testlib.cpp + +#include + +[[clang::xray_always_instrument]] void instrumented_in_dso() { + printf("instrumented_in_dso called\n"); +} diff --git a/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp new file mode 100644 index 0000000000000..d3e992dd49772 --- /dev/null +++ b/compiler-rt/test/xray/TestCases/Posix/patching-unpatching-dso.cpp @@ -0,0 +1,75 @@ +// Check that we can patch and un-patch on demand, and that logging gets invoked +// appropriately. +// + +// RUN: split-file %s %t +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so +// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testlib.so -Wl,-rpath,%t -o %t/main.o + +// RUN: XRAY_OPTIONS="patch_premain=false" %run %t/main.o 2>&1 | FileCheck %s + +// REQUIRES: target=x86_64{{.*}} + +//--- main.cpp + +#include "xray/xray_interface.h" + +#include + +bool called = false; + +void test_handler(int32_t fid, XRayEntryType type) { + printf("called: %d, type=%d\n", fid, static_cast(type)); + called = true; +} + +[[clang::xray_always_instrument]] void instrumented_in_executable() { + printf("instrumented_in_executable called\n"); +} + +extern void instrumented_in_dso(); + +int main() { + __xray_set_handler(test_handler); + instrumented_in_executable(); + // CHECK: instrumented_in_executable called + instrumented_in_dso(); + // CHECK: instrumented_in_dso called + auto status = __xray_patch(); + printf("patching status: %d\n", static_cast(status)); + // CHECK-NEXT: patching status: 1 + instrumented_in_executable(); + // CHECK-NEXT: called: {{.*}}, type=0 + // CHECK-NEXT: instrumented_in_executable called + // CHECK-NEXT: called: {{.*}}, type=1 + instrumented_in_dso(); + // CHECK-NEXT: called: {{.*}}, type=0 + // CHECK-NEXT: instrumented_in_dso called + // CHECK-NEXT: called: {{.*}}, type=1 + status = __xray_unpatch(); + printf("patching status: %d\n", static_cast(status)); + // CHECK-NEXT: patching status: 1 + instrumented_in_executable(); + // CHECK-NEXT: instrumented_in_executable called + instrumented_in_dso(); + // CHECK-NEXT: instrumented_in_dso called + status = __xray_patch(); + printf("patching status: %d\n", static_cast(status)); + // CHECK-NEXT: patching status: 1 + __xray_remove_handler(); + instrumented_in_executable(); + // CHECK-NEXT: instrumented_in_executable called + instrumented_in_dso(); + // CHECK-NEXT: instrumented_in_dso called + status = __xray_unpatch(); + printf("patching status: %d\n", static_cast(status)); + // CHECK-NEXT: patching status: 1 +} + +//--- testlib.cpp + +#include + +[[clang::xray_always_instrument]] void instrumented_in_dso() { + printf("instrumented_in_dso called\n"); +} diff --git a/flang/cmake/modules/AddFlangOffloadRuntime.cmake b/flang/cmake/modules/AddFlangOffloadRuntime.cmake index 6407be5d038b8..8e4f47d18535d 100644 --- a/flang/cmake/modules/AddFlangOffloadRuntime.cmake +++ b/flang/cmake/modules/AddFlangOffloadRuntime.cmake @@ -101,7 +101,7 @@ macro(enable_omp_offload_compilation files) "gfx908;gfx90a;gfx90c;gfx940;gfx1010;gfx1030" "gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036" "gfx1100;gfx1101;gfx1102;gfx1103;gfx1150;gfx1151" - "gfx1152" + "gfx1152;gfx1153" ) set(all_nvptx_architectures "sm_35;sm_37;sm_50;sm_52;sm_53;sm_60;sm_61;sm_62" diff --git a/flang/include/flang/Frontend/FrontendPluginRegistry.h b/flang/include/flang/Frontend/FrontendPluginRegistry.h index 8b1f576c39e24..a8079dbfaf869 100644 --- a/flang/include/flang/Frontend/FrontendPluginRegistry.h +++ b/flang/include/flang/Frontend/FrontendPluginRegistry.h @@ -25,4 +25,8 @@ using FrontendPluginRegistry = llvm::Registry; } // namespace Fortran::frontend +namespace llvm { +extern template class Registry; +} + #endif // FORTRAN_FRONTEND_FRONTENDPLUGINREGISTRY_H diff --git a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.h b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.h index 4132db672e394..1edded090f8ce 100644 --- a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.h +++ b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.h @@ -12,6 +12,7 @@ #include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h" #include "flang/Optimizer/Dialect/CUF/CUFDialect.h" #include "flang/Optimizer/Dialect/FIRType.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/IR/OpDefinition.h" #define GET_OP_CLASSES diff --git a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td index 98d1ef529738c..d34a8af0394a4 100644 --- a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td +++ b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td @@ -18,6 +18,7 @@ include "flang/Optimizer/Dialect/CUF/CUFDialect.td" include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.td" include "flang/Optimizer/Dialect/FIRTypes.td" include "flang/Optimizer/Dialect/FIRAttr.td" +include "mlir/Dialect/LLVMIR/LLVMOpBase.td" include "mlir/Interfaces/LoopLikeInterface.td" include "mlir/IR/BuiltinAttributes.td" @@ -288,15 +289,30 @@ def cuf_KernelOp : cuf_Op<"kernel", [AttrSizedOperandSegments, let hasVerifier = 1; } +def cuf_RegisterModuleOp : cuf_Op<"register_module", []> { + let summary = "Register a CUDA module"; + + let arguments = (ins + SymbolRefAttr:$name + ); + + let assemblyFormat = [{ + $name attr-dict `->` type($modulePtr) + }]; + + let results = (outs LLVM_AnyPointer:$modulePtr); +} + def cuf_RegisterKernelOp : cuf_Op<"register_kernel", []> { let summary = "Register a CUDA kernel"; let arguments = (ins - SymbolRefAttr:$name + SymbolRefAttr:$name, + LLVM_AnyPointer:$modulePtr ); let assemblyFormat = [{ - $name attr-dict + $name `(` $modulePtr `:` type($modulePtr) `)`attr-dict }]; let hasVerifier = 1; diff --git a/flang/include/flang/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.h b/flang/include/flang/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.h new file mode 100644 index 0000000000000..f3edb7fca649d --- /dev/null +++ b/flang/include/flang/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.h @@ -0,0 +1,29 @@ +//===- CUFToLLVMIRTranslation.h - CUF Dialect to LLVM IR --------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This provides registration calls for GPU dialect to LLVM IR translation. +// +//===----------------------------------------------------------------------===// + +#ifndef FLANG_OPTIMIZER_DIALECT_CUF_GPUTOLLVMIRTRANSLATION_H_ +#define FLANG_OPTIMIZER_DIALECT_CUF_GPUTOLLVMIRTRANSLATION_H_ + +namespace mlir { +class DialectRegistry; +class MLIRContext; +} // namespace mlir + +namespace cuf { + +/// Register the CUF dialect and the translation from it to the LLVM IR in +/// the given registry. +void registerCUFDialectTranslation(mlir::DialectRegistry ®istry); + +} // namespace cuf + +#endif // FLANG_OPTIMIZER_DIALECT_CUF_GPUTOLLVMIRTRANSLATION_H_ diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index d467f0ab4e1c1..eda8f26e936fb 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -3078,7 +3078,7 @@ def fir_IsPresentOp : fir_SimpleOp<"is_present", [NoMemoryEffect]> { // debug information so we would like to keep this around even if the value // is not used. def fir_DeclareOp : fir_Op<"declare", [AttrSizedOperandSegments, - MemoryEffects<[MemWrite]>, + MemoryEffects<[MemAlloc]>, DeclareOpInterfaceMethods]> { let summary = "declare a variable"; diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index fdf0db9d3c75d..1ab8793f72652 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -36,7 +36,7 @@ class hlfir_Op traits> // from the declare operation can be used to generate debug information so we // don't want to remove it as dead code def hlfir_DeclareOp : hlfir_Op<"declare", [AttrSizedOperandSegments, - MemoryEffects<[MemWrite]>, + MemoryEffects<[MemAlloc]>, DeclareOpInterfaceMethods]> { let summary = "declare a variable and produce an SSA value that can be used as a variable in HLFIR operations"; @@ -130,7 +130,7 @@ def hlfir_DeclareOp : hlfir_Op<"declare", [AttrSizedOperandSegments, let hasVerifier = 1; } -def fir_AssignOp : hlfir_Op<"assign", [MemoryEffects<[MemWrite]>]> { +def fir_AssignOp : hlfir_Op<"assign", [DeclareOpInterfaceMethods]> { let summary = "Assign an expression or variable value to a Fortran variable"; let description = [{ @@ -166,7 +166,7 @@ def fir_AssignOp : hlfir_Op<"assign", [MemoryEffects<[MemWrite]>]> { }]; let arguments = (ins AnyFortranEntity:$rhs, - Arg:$lhs, + AnyFortranVariable:$lhs, UnitAttr:$realloc, UnitAttr:$keep_lhs_length_if_realloc, UnitAttr:$temporary_lhs); diff --git a/flang/include/flang/Optimizer/OpenMP/Passes.td b/flang/include/flang/Optimizer/OpenMP/Passes.td index 1c0ce08f5b483..c070bc22ff20c 100644 --- a/flang/include/flang/Optimizer/OpenMP/Passes.td +++ b/flang/include/flang/Optimizer/OpenMP/Passes.td @@ -22,6 +22,19 @@ def MapInfoFinalizationPass let dependentDialects = ["mlir::omp::OpenMPDialect"]; } +def MapsForPrivatizedSymbolsPass + : Pass<"omp-maps-for-privatized-symbols", "mlir::func::FuncOp"> { + let summary = "Creates MapInfoOp instances for privatized symbols when needed"; + let description = [{ + Adds omp.map.info operations for privatized symbols on omp.target ops + In certain situations, such as when an allocatable is privatized, its + descriptor is needed in the alloc region of the privatizer. This results + in the use of the descriptor inside the target region. As such, the + descriptor then needs to be mapped. This pass adds such MapInfoOp operations. + }]; + let dependentDialects = ["mlir::omp::OpenMPDialect"]; +} + def MarkDeclareTargetPass : Pass<"omp-mark-declare-target", "mlir::ModuleOp"> { let summary = "Marks all functions called by an OpenMP declare target function as declare target"; diff --git a/flang/include/flang/Optimizer/Support/InitFIR.h b/flang/include/flang/Optimizer/Support/InitFIR.h index 04a5dd323e550..1c61c36719992 100644 --- a/flang/include/flang/Optimizer/Support/InitFIR.h +++ b/flang/include/flang/Optimizer/Support/InitFIR.h @@ -14,6 +14,7 @@ #define FORTRAN_OPTIMIZER_SUPPORT_INITFIR_H #include "flang/Optimizer/Dialect/CUF/CUFDialect.h" +#include "flang/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.h" #include "flang/Optimizer/Dialect/FIRDialect.h" #include "flang/Optimizer/HLFIR/HLFIRDialect.h" #include "mlir/Conversion/Passes.h" @@ -61,6 +62,7 @@ inline void addFIRExtensions(mlir::DialectRegistry ®istry, if (addFIRInlinerInterface) addFIRInlinerExtension(registry); addFIRToLLVMIRExtension(registry); + cuf::registerCUFDialectTranslation(registry); } inline void loadNonCodegenDialects(mlir::MLIRContext &context) { diff --git a/flang/include/flang/Optimizer/Support/InternalNames.h b/flang/include/flang/Optimizer/Support/InternalNames.h index 67ab36cf8da7f..41f2cb9842dc7 100644 --- a/flang/include/flang/Optimizer/Support/InternalNames.h +++ b/flang/include/flang/Optimizer/Support/InternalNames.h @@ -184,6 +184,10 @@ struct NameUniquer { static std::string replaceSpecialSymbols(const std::string &name); + /// Returns true if the passed name denotes a special symbol (e.g. global + /// symbol generated for derived type description). + static bool isSpecialSymbol(llvm::StringRef name); + private: static std::string intAsString(std::int64_t i); static std::string doKind(std::int64_t kind); diff --git a/flang/include/flang/Optimizer/Transforms/CufOpConversion.h b/flang/include/flang/Optimizer/Transforms/CUFOpConversion.h similarity index 83% rename from flang/include/flang/Optimizer/Transforms/CufOpConversion.h rename to flang/include/flang/Optimizer/Transforms/CUFOpConversion.h index 79ce4ac5c6cbc..f061323db1704 100644 --- a/flang/include/flang/Optimizer/Transforms/CufOpConversion.h +++ b/flang/include/flang/Optimizer/Transforms/CUFOpConversion.h @@ -1,4 +1,4 @@ -//===------- Optimizer/Transforms/CufOpConversion.h -------------*- C++ -*-===// +//===------- Optimizer/Transforms/CUFOpConversion.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. @@ -18,12 +18,14 @@ class LLVMTypeConverter; namespace mlir { class DataLayout; -} +class SymbolTable; +} // namespace mlir namespace cuf { void populateCUFToFIRConversionPatterns(const fir::LLVMTypeConverter &converter, mlir::DataLayout &dl, + const mlir::SymbolTable &symtab, mlir::RewritePatternSet &patterns); } // namespace cuf diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h index 3b2af3a339810..5d3067aa35981 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -40,7 +40,7 @@ namespace fir { #define GEN_PASS_DECL_CHARACTERCONVERSION #define GEN_PASS_DECL_CFGCONVERSION #define GEN_PASS_DECL_CUFADDCONSTRUCTOR -#define GEN_PASS_DECL_CUFIMPLICITDEVICEGLOBAL +#define GEN_PASS_DECL_CUFDEVICEGLOBAL #define GEN_PASS_DECL_CUFOPCONVERSION #define GEN_PASS_DECL_EXTERNALNAMECONVERSION #define GEN_PASS_DECL_MEMREFDATAFLOWOPT diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index af6bd41cbb71d..2efa543ca0714 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -421,15 +421,15 @@ def AssumedRankOpConversion : Pass<"fir-assumed-rank-op", "mlir::ModuleOp"> { ]; } -def CufOpConversion : Pass<"cuf-convert", "mlir::ModuleOp"> { +def CUFOpConversion : Pass<"cuf-convert", "mlir::ModuleOp"> { let summary = "Convert some CUF operations to runtime calls"; let dependentDialects = [ "fir::FIROpsDialect" ]; } -def CufImplicitDeviceGlobal : - Pass<"cuf-implicit-device-global", "mlir::ModuleOp"> { +def CUFDeviceGlobal : + Pass<"cuf-device-global", "mlir::ModuleOp"> { let summary = "Flag globals used in device function with data attribute"; let dependentDialects = [ "cuf::CUFDialect" diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 4a3c992c4ec51..358fb491b84fb 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3455,7 +3455,7 @@ WRAPPER_CLASS(OmpObjectList, std::list); // map-type-modifier -> ALWAYS | CLOSE | PRESENT | OMPX_HOLD // map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE struct OmpMapClause { - ENUM_CLASS(TypeModifier, Always, Close, Present, OmpxHold); + ENUM_CLASS(TypeModifier, Always, Close, Present, Ompx_Hold); ENUM_CLASS(Type, To, From, Tofrom, Alloc, Release, Delete) TUPLE_CLASS_BOILERPLATE(OmpMapClause); std::tuple>, std::optional, diff --git a/flang/include/flang/Runtime/CUDA/registration.h b/flang/include/flang/Runtime/CUDA/registration.h new file mode 100644 index 0000000000000..cbe202c4d23e0 --- /dev/null +++ b/flang/include/flang/Runtime/CUDA/registration.h @@ -0,0 +1,28 @@ +//===-- include/flang/Runtime/CUDA/registration.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 FORTRAN_RUNTIME_CUDA_REGISTRATION_H_ +#define FORTRAN_RUNTIME_CUDA_REGISTRATION_H_ + +#include "flang/Runtime/entry-names.h" +#include + +namespace Fortran::runtime::cuda { + +extern "C" { + +/// Register a CUDA module. +void *RTDECL(CUFRegisterModule)(void *data); + +/// Register a device function. +void RTDECL(CUFRegisterFunction)(void **module, const char *fct); + +} // extern "C" + +} // namespace Fortran::runtime::cuda +#endif // FORTRAN_RUNTIME_CUDA_REGISTRATION_H_ diff --git a/flang/lib/Lower/DirectivesCommon.h b/flang/lib/Lower/DirectivesCommon.h index da192ded4aa97..421a44b128c01 100644 --- a/flang/lib/Lower/DirectivesCommon.h +++ b/flang/lib/Lower/DirectivesCommon.h @@ -126,12 +126,8 @@ static void processOmpAtomicTODO(mlir::Type elementType, return; if constexpr (std::is_same()) { - // Based on assertion for supported element types in OMPIRBuilder.cpp - // createAtomicRead - mlir::Type unwrappedEleTy = fir::unwrapRefType(elementType); - bool supportedAtomicType = fir::isa_trivial(unwrappedEleTy); - if (!supportedAtomicType) - TODO(loc, "Unsupported atomic type"); + assert(fir::isa_trivial(fir::unwrapRefType(elementType)) && + "is supported type for omp atomic"); } } diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 64d661256a187..303b9ac5b7f4d 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -843,10 +843,10 @@ Map make(const parser::OmpClause::Map &inp, CLAUSET_ENUM_CONVERT( // convert2, parser::OmpMapClause::TypeModifier, Map::MapTypeModifier, // clang-format off - MS(Always, Always) - MS(Close, Close) - MS(OmpxHold, OmpxHold) - MS(Present, Present) + MS(Always, Always) + MS(Close, Close) + MS(Ompx_Hold, OmpxHold) + MS(Present, Present) // clang-format on ); diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index cf469003b7298..52a077cd5a797 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2209,6 +2209,12 @@ static void genCompositeDistributeParallelDoSimd( genSimdClauses(converter, semaCtx, simdItem->clauses, loc, simdClauseOps, simdReductionSyms); + // TODO: Remove this after omp.simd reductions on composite constructs are + // supported. + simdClauseOps.reductionVars.clear(); + simdClauseOps.reductionByref.clear(); + simdClauseOps.reductionSyms.clear(); + mlir::omp::LoopNestOperands loopNestClauseOps; llvm::SmallVector iv; genLoopNestClauses(converter, semaCtx, eval, simdItem->clauses, loc, @@ -2230,9 +2236,7 @@ static void genCompositeDistributeParallelDoSimd( wsloopOp.setComposite(/*val=*/true); EntryBlockArgs simdArgs; - // TODO: Add private syms and vars. - simdArgs.reduction.syms = simdReductionSyms; - simdArgs.reduction.vars = simdClauseOps.reductionVars; + // TODO: Add private and reduction syms and vars. auto simdOp = genWrapperOp(converter, loc, simdClauseOps, simdArgs); simdOp.setComposite(/*val=*/true); @@ -2325,6 +2329,12 @@ static void genCompositeDoSimd(lower::AbstractConverter &converter, genSimdClauses(converter, semaCtx, simdItem->clauses, loc, simdClauseOps, simdReductionSyms); + // TODO: Remove this after omp.simd reductions on composite constructs are + // supported. + simdClauseOps.reductionVars.clear(); + simdClauseOps.reductionByref.clear(); + simdClauseOps.reductionSyms.clear(); + // TODO: Support delayed privatization. DataSharingProcessor dsp(converter, semaCtx, simdItem->clauses, eval, /*shouldCollectPreDeterminedSymbols=*/true, @@ -2348,9 +2358,7 @@ static void genCompositeDoSimd(lower::AbstractConverter &converter, wsloopOp.setComposite(/*val=*/true); EntryBlockArgs simdArgs; - // TODO: Add private syms and vars. - simdArgs.reduction.syms = simdReductionSyms; - simdArgs.reduction.vars = simdClauseOps.reductionVars; + // TODO: Add private and reduction syms and vars. auto simdOp = genWrapperOp(converter, loc, simdClauseOps, simdArgs); simdOp.setComposite(/*val=*/true); diff --git a/flang/lib/Optimizer/Dialect/CUF/CMakeLists.txt b/flang/lib/Optimizer/Dialect/CUF/CMakeLists.txt index b2221199995d5..5d4bd0785971f 100644 --- a/flang/lib/Optimizer/Dialect/CUF/CMakeLists.txt +++ b/flang/lib/Optimizer/Dialect/CUF/CMakeLists.txt @@ -3,6 +3,7 @@ add_subdirectory(Attributes) add_flang_library(CUFDialect CUFDialect.cpp CUFOps.cpp + CUFToLLVMIRTranslation.cpp DEPENDS MLIRIR diff --git a/flang/lib/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.cpp b/flang/lib/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.cpp new file mode 100644 index 0000000000000..c6c9f96b81135 --- /dev/null +++ b/flang/lib/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.cpp @@ -0,0 +1,104 @@ +//===- CUFToLLVMIRTranslation.cpp - Translate CUF dialect to LLVM IR ------===// +// +// 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 implements a translation between the MLIR CUF dialect and LLVM IR. +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/Dialect/CUF/CUFToLLVMIRTranslation.h" +#include "flang/Optimizer/Dialect/CUF/CUFOps.h" +#include "flang/Runtime/entry-names.h" +#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h" +#include "mlir/Target/LLVMIR/ModuleTranslation.h" +#include "llvm/ADT/TypeSwitch.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace mlir; + +namespace { + +LogicalResult registerModule(cuf::RegisterModuleOp op, + llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation) { + std::string binaryIdentifier = + op.getName().getLeafReference().str() + "_bin_cst"; + llvm::Module *module = moduleTranslation.getLLVMModule(); + llvm::Value *binary = module->getGlobalVariable(binaryIdentifier, true); + if (!binary) + return op.emitError() << "Couldn't find the binary: " << binaryIdentifier; + + llvm::Type *ptrTy = builder.getPtrTy(0); + llvm::FunctionCallee fct = module->getOrInsertFunction( + RTNAME_STRING(CUFRegisterModule), + llvm::FunctionType::get(ptrTy, ArrayRef({ptrTy}), false)); + auto *handle = builder.CreateCall(fct, {binary}); + moduleTranslation.mapValue(op->getResults().front()) = handle; + return mlir::success(); +} + +llvm::Value *getOrCreateFunctionName(llvm::Module *module, + llvm::IRBuilderBase &builder, + llvm::StringRef moduleName, + llvm::StringRef kernelName) { + std::string globalName = + std::string(llvm::formatv("{0}_{1}_kernel_name", moduleName, kernelName)); + + if (llvm::GlobalVariable *gv = module->getGlobalVariable(globalName)) + return gv; + + return builder.CreateGlobalString(kernelName, globalName); +} + +LogicalResult registerKernel(cuf::RegisterKernelOp op, + llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation) { + llvm::Module *module = moduleTranslation.getLLVMModule(); + llvm::Type *ptrTy = builder.getPtrTy(0); + llvm::FunctionCallee fct = module->getOrInsertFunction( + RTNAME_STRING(CUFRegisterFunction), + llvm::FunctionType::get(ptrTy, ArrayRef({ptrTy, ptrTy}), + false)); + llvm::Value *modulePtr = moduleTranslation.lookupValue(op.getModulePtr()); + builder.CreateCall( + fct, {modulePtr, getOrCreateFunctionName(module, builder, + op.getKernelModuleName().str(), + op.getKernelName().str())}); + return mlir::success(); +} + +class CUFDialectLLVMIRTranslationInterface + : public LLVMTranslationDialectInterface { +public: + using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface; + + LogicalResult + convertOperation(Operation *operation, llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation) const override { + return llvm::TypeSwitch(operation) + .Case([&](cuf::RegisterModuleOp op) { + return registerModule(op, builder, moduleTranslation); + }) + .Case([&](cuf::RegisterKernelOp op) { + return registerKernel(op, builder, moduleTranslation); + }) + .Default([&](Operation *op) { + return op->emitError("unsupported GPU operation: ") << op->getName(); + }); + } +}; + +} // namespace + +void cuf::registerCUFDialectTranslation(DialectRegistry ®istry) { + registry.insert(); + registry.addExtension(+[](MLIRContext *ctx, cuf::CUFDialect *dialect) { + dialect->addInterfaces(); + }); +} diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index ed301c74c9ede..b593383ff2848 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -90,6 +90,62 @@ llvm::LogicalResult hlfir::AssignOp::verify() { return mlir::success(); } +void hlfir::AssignOp::getEffects( + llvm::SmallVectorImpl< + mlir::SideEffects::EffectInstance> + &effects) { + mlir::OpOperand &rhs = getRhsMutable(); + mlir::OpOperand &lhs = getLhsMutable(); + mlir::Type rhsType = getRhs().getType(); + mlir::Type lhsType = getLhs().getType(); + if (mlir::isa(hlfir::getFortranElementType(lhsType))) { + // For derived type assignments, set unknown read/write effects since it + // is not known here if user defined finalization is needed, and also + // because allocatable components may lead to "deeper" read/write effects + // that cannot be described with this API. + effects.emplace_back(mlir::MemoryEffects::Read::get(), + mlir::SideEffects::DefaultResource::get()); + effects.emplace_back(mlir::MemoryEffects::Write::get(), + mlir::SideEffects::DefaultResource::get()); + } else { + // Read effect when RHS is a variable. + if (hlfir::isFortranVariableType(rhsType)) { + if (hlfir::isBoxAddressType(rhsType)) { + // Unknown read effect if the RHS is a descriptor since the read effect + // on the data cannot be described. + effects.emplace_back(mlir::MemoryEffects::Read::get(), + mlir::SideEffects::DefaultResource::get()); + } else { + effects.emplace_back(mlir::MemoryEffects::Read::get(), &rhs, + mlir::SideEffects::DefaultResource::get()); + } + } + + // Write effects on LHS. + if (hlfir::isBoxAddressType(lhsType)) { + // If the LHS is a descriptor, the descriptor will be read and the data + // write cannot be described in this API (and the descriptor may be + // written to in case of realloc, which is covered by the unknown write + // effect. + effects.emplace_back(mlir::MemoryEffects::Read::get(), &lhs, + mlir::SideEffects::DefaultResource::get()); + effects.emplace_back(mlir::MemoryEffects::Write::get(), + mlir::SideEffects::DefaultResource::get()); + } else { + effects.emplace_back(mlir::MemoryEffects::Write::get(), &lhs, + mlir::SideEffects::DefaultResource::get()); + } + } + + if (getRealloc()) { + // Reallocation of the data cannot be precisely described by this API. + effects.emplace_back(mlir::MemoryEffects::Free::get(), + mlir::SideEffects::DefaultResource::get()); + effects.emplace_back(mlir::MemoryEffects::Allocate::get(), + mlir::SideEffects::DefaultResource::get()); + } +} + //===----------------------------------------------------------------------===// // DeclareOp //===----------------------------------------------------------------------===// diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp index efe59b8ef988e..5971b5b9d76a0 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/ScheduleOrderedAssignments.cpp @@ -347,12 +347,23 @@ conflict(llvm::ArrayRef effectsA, anyRAWorWAW(effectsB, effectsA, aliasAnalysis); } -/// Could there be any write effects in "effects"? +/// Could there be any write effects in "effects" affecting memory storages +/// that are not local to the current region. static bool -anyWrite(llvm::ArrayRef effects) { +anyNonLocalWrite(llvm::ArrayRef effects, + mlir::Region ®ion) { return llvm::any_of( - effects, [](const mlir::MemoryEffects::EffectInstance &effect) { - return mlir::isa(effect.getEffect()); + effects, [®ion](const mlir::MemoryEffects::EffectInstance &effect) { + if (mlir::isa(effect.getEffect())) { + if (mlir::Value v = effect.getValue()) { + v = getStorageSource(v); + if (v.getDefiningOp() || + v.getDefiningOp()) + return !region.isAncestor(v.getParentRegion()); + } + return true; + } + return false; }); } @@ -393,9 +404,13 @@ void Scheduler::saveEvaluationIfConflict(mlir::Region &yieldRegion, if (entity && hlfir::isFortranVariableType(entity->get().getType())) effects.emplace_back(mlir::MemoryEffects::Read::get(), entity); } - if (!leafRegionsMayOnlyRead && anyWrite(effects)) { - // Region with write effect must be executed only once: save it the first - // time it is encountered. + if (!leafRegionsMayOnlyRead && anyNonLocalWrite(effects, yieldRegion)) { + // Region with write effect must be executed only once (unless all writes + // affect storages allocated inside the region): save it the first time it + // is encountered. + LLVM_DEBUG(llvm::dbgs() + << "saving eval because write effect prevents re-evaluation" + << "\n";); saveEvaluation(yieldRegion, effects, /*anyWrite=*/true); } else if (conflict(effects, assignEffects)) { // Region that conflicts with the current assignments must be fully @@ -411,7 +426,8 @@ void Scheduler::saveEvaluationIfConflict(mlir::Region &yieldRegion, // For example, a WHERE mask might be written by the masked assignment // evaluations, and it has to be saved in this case: // where (mask) r = f() ! function f modifies mask - saveEvaluation(yieldRegion, effects, anyWrite(effects)); + saveEvaluation(yieldRegion, effects, + anyNonLocalWrite(effects, yieldRegion)); } else { // Can be executed while doing the assignment. independentEvaluationEffects.append(effects.begin(), effects.end()); diff --git a/flang/lib/Optimizer/OpenMP/CMakeLists.txt b/flang/lib/Optimizer/OpenMP/CMakeLists.txt index 92051634f0378..035d0d5ca46c7 100644 --- a/flang/lib/Optimizer/OpenMP/CMakeLists.txt +++ b/flang/lib/Optimizer/OpenMP/CMakeLists.txt @@ -2,6 +2,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) add_flang_library(FlangOpenMPTransforms FunctionFiltering.cpp + MapsForPrivatizedSymbols.cpp MapInfoFinalization.cpp MarkDeclareTarget.cpp diff --git a/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp b/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp new file mode 100644 index 0000000000000..2fa55844aec7c --- /dev/null +++ b/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp @@ -0,0 +1,156 @@ +//===- MapsForPrivatizedSymbols.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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +/// \file +/// An OpenMP dialect related pass for FIR/HLFIR which creates MapInfoOp +/// instances for certain privatized symbols. +/// For example, if an allocatable variable is used in a private clause attached +/// to a omp.target op, then the allocatable variable's descriptor will be +/// needed on the device (e.g. GPU). This descriptor needs to be separately +/// mapped onto the device. This pass creates the necessary omp.map.info ops for +/// this. +//===----------------------------------------------------------------------===// +// TODO: +// 1. Before adding omp.map.info, check if we already have an omp.map.info for +// the variable in question. +// 2. Generalize this for more than just omp.target ops. +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/Dialect/Support/KindMapping.h" +#include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Optimizer/OpenMP/Passes.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/SymbolTable.h" +#include "mlir/Pass/Pass.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" +#include "llvm/Support/Debug.h" +#include + +#define DEBUG_TYPE "omp-maps-for-privatized-symbols" + +namespace flangomp { +#define GEN_PASS_DEF_MAPSFORPRIVATIZEDSYMBOLSPASS +#include "flang/Optimizer/OpenMP/Passes.h.inc" +} // namespace flangomp +using namespace mlir; +namespace { +class MapsForPrivatizedSymbolsPass + : public flangomp::impl::MapsForPrivatizedSymbolsPassBase< + MapsForPrivatizedSymbolsPass> { + + bool privatizerNeedsMap(omp::PrivateClauseOp &privatizer) { + Region &allocRegion = privatizer.getAllocRegion(); + Value blockArg0 = allocRegion.getArgument(0); + if (blockArg0.use_empty()) + return false; + return true; + } + omp::MapInfoOp createMapInfo(Location loc, Value var, + fir::FirOpBuilder &builder) { + uint64_t mapTypeTo = static_cast< + std::underlying_type_t>( + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO); + Operation *definingOp = var.getDefiningOp(); + auto declOp = llvm::dyn_cast_or_null(definingOp); + assert(declOp && + "Expected defining Op of privatized var to be hlfir.declare"); + + // We want the first result of the hlfir.declare op because our goal + // is to map the descriptor (fir.box or fir.boxchar) and the first + // result for hlfir.declare is the descriptor if a the symbol being + // decalred needs a descriptor. + Value varPtr = declOp.getBase(); + + // If we do not have a reference to descritor, but the descriptor itself + // then we need to store that on the stack so that we can map the + // address of the descriptor. + if (mlir::isa(varPtr.getType()) || + mlir::isa(varPtr.getType())) { + OpBuilder::InsertPoint savedInsPoint = builder.saveInsertionPoint(); + mlir::Block *allocaBlock = builder.getAllocaBlock(); + assert(allocaBlock && "No allocablock found for a funcOp"); + builder.setInsertionPointToStart(allocaBlock); + auto alloca = builder.create(loc, varPtr.getType()); + builder.restoreInsertionPoint(savedInsPoint); + builder.create(loc, varPtr, alloca); + varPtr = alloca; + } + return builder.create( + loc, varPtr.getType(), varPtr, + TypeAttr::get(llvm::cast(varPtr.getType()) + .getElementType()), + /*varPtrPtr=*/Value{}, + /*members=*/SmallVector{}, + /*member_index=*/DenseIntElementsAttr{}, + /*bounds=*/ValueRange{}, + builder.getIntegerAttr(builder.getIntegerType(64, /*isSigned=*/false), + mapTypeTo), + builder.getAttr( + omp::VariableCaptureKind::ByRef), + StringAttr(), builder.getBoolAttr(false)); + } + void addMapInfoOp(omp::TargetOp targetOp, omp::MapInfoOp mapInfoOp) { + auto argIface = llvm::cast(*targetOp); + unsigned insertIndex = + argIface.getMapBlockArgsStart() + argIface.numMapBlockArgs(); + targetOp.getMapVarsMutable().append(ValueRange{mapInfoOp}); + targetOp.getRegion().insertArgument(insertIndex, mapInfoOp.getType(), + mapInfoOp.getLoc()); + } + void addMapInfoOps(omp::TargetOp targetOp, + llvm::SmallVectorImpl &mapInfoOps) { + for (auto mapInfoOp : mapInfoOps) + addMapInfoOp(targetOp, mapInfoOp); + } + void runOnOperation() override { + ModuleOp module = getOperation()->getParentOfType(); + fir::KindMapping kindMap = fir::getKindMapping(module); + fir::FirOpBuilder builder{module, std::move(kindMap)}; + llvm::DenseMap> + mapInfoOpsForTarget; + + getOperation()->walk([&](omp::TargetOp targetOp) { + if (targetOp.getPrivateVars().empty()) + return; + OperandRange privVars = targetOp.getPrivateVars(); + std::optional privSyms = targetOp.getPrivateSyms(); + SmallVector mapInfoOps; + for (auto [privVar, privSym] : llvm::zip_equal(privVars, *privSyms)) { + + SymbolRefAttr privatizerName = llvm::cast(privSym); + omp::PrivateClauseOp privatizer = + SymbolTable::lookupNearestSymbolFrom( + targetOp, privatizerName); + if (!privatizerNeedsMap(privatizer)) { + continue; + } + builder.setInsertionPoint(targetOp); + Location loc = targetOp.getLoc(); + omp::MapInfoOp mapInfoOp = createMapInfo(loc, privVar, builder); + mapInfoOps.push_back(mapInfoOp); + LLVM_DEBUG(llvm::dbgs() << "MapsForPrivatizedSymbolsPass created ->\n"); + LLVM_DEBUG(mapInfoOp.dump()); + } + if (!mapInfoOps.empty()) { + mapInfoOpsForTarget.insert({targetOp.getOperation(), mapInfoOps}); + } + }); + if (!mapInfoOpsForTarget.empty()) { + for (auto &[targetOp, mapInfoOps] : mapInfoOpsForTarget) { + addMapInfoOps(static_cast(targetOp), mapInfoOps); + } + } + } +}; +} // namespace diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 3fa5c54403bd8..3c139f7e93405 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -243,6 +243,7 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, /// rather than the host device. void createOpenMPFIRPassPipeline(mlir::PassManager &pm, bool isTargetDevice) { pm.addPass(flangomp::createMapInfoFinalizationPass()); + pm.addPass(flangomp::createMapsForPrivatizedSymbolsPass()); pm.addPass(flangomp::createMarkDeclareTargetPass()); if (isTargetDevice) pm.addPass(flangomp::createFunctionFilteringPass()); diff --git a/flang/lib/Optimizer/Support/InternalNames.cpp b/flang/lib/Optimizer/Support/InternalNames.cpp index 58a5da5de7972..011021c9f0350 100644 --- a/flang/lib/Optimizer/Support/InternalNames.cpp +++ b/flang/lib/Optimizer/Support/InternalNames.cpp @@ -411,3 +411,7 @@ fir::NameUniquer::dropTypeConversionMarkers(llvm::StringRef mangledTypeName) { std::string fir::NameUniquer::replaceSpecialSymbols(const std::string &name) { return std::regex_replace(name, std::regex{"\\."}, "X"); } + +bool fir::NameUniquer::isSpecialSymbol(llvm::StringRef name) { + return !name.empty() && (name[0] == '.' || name[0] == 'X'); +} diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 400a8648dd7e0..3a437c7a0f013 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -211,10 +211,7 @@ void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp, if (result.first != fir::NameUniquer::NameKind::VARIABLE) return; - // Discard entries that describe a derived type. Usually start with '.c.', - // '.dt.' or '.n.'. It would be better if result of the deconstruct had a flag - // for such values so that we dont have to look at string values. - if (!result.second.name.empty() && result.second.name[0] == '.') + if (fir::NameUniquer::isSpecialSymbol(result.second.name)) return; unsigned line = getLineFromLoc(globalOp.getLoc()); diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt index 352fe4cbe09e9..8f4f731e00922 100644 --- a/flang/lib/Optimizer/Transforms/CMakeLists.txt +++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt @@ -10,8 +10,8 @@ add_flang_library(FIRTransforms ConstantArgumentGlobalisation.cpp ControlFlowConverter.cpp CUFAddConstructor.cpp - CufImplicitDeviceGlobal.cpp - CufOpConversion.cpp + CUFDeviceGlobal.cpp + CUFOpConversion.cpp ArrayValueCopy.cpp ExternalNameConversion.cpp MemoryUtils.cpp diff --git a/flang/lib/Optimizer/Transforms/CUFAddConstructor.cpp b/flang/lib/Optimizer/Transforms/CUFAddConstructor.cpp index 3db24226e7504..f260437e71041 100644 --- a/flang/lib/Optimizer/Transforms/CUFAddConstructor.cpp +++ b/flang/lib/Optimizer/Transforms/CUFAddConstructor.cpp @@ -62,12 +62,15 @@ struct CUFAddConstructor // Register kernels auto gpuMod = symTab.lookup(cudaModName); if (gpuMod) { + auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(ctx); + auto registeredMod = builder.create( + loc, llvmPtrTy, mlir::SymbolRefAttr::get(ctx, gpuMod.getName())); for (auto func : gpuMod.getOps()) { if (func.isKernel()) { auto kernelName = mlir::SymbolRefAttr::get( builder.getStringAttr(cudaModName), {mlir::SymbolRefAttr::get(builder.getContext(), func.getName())}); - builder.create(loc, kernelName); + builder.create(loc, kernelName, registeredMod); } } } diff --git a/flang/lib/Optimizer/Transforms/CufImplicitDeviceGlobal.cpp b/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp similarity index 91% rename from flang/lib/Optimizer/Transforms/CufImplicitDeviceGlobal.cpp rename to flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp index 206400c2ef8e5..a4761f24f16d7 100644 --- a/flang/lib/Optimizer/Transforms/CufImplicitDeviceGlobal.cpp +++ b/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp @@ -1,4 +1,4 @@ -//===-- CufOpConversion.cpp -----------------------------------------------===// +//===-- CUFOpConversion.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -18,7 +18,7 @@ #include "mlir/Transforms/DialectConversion.h" namespace fir { -#define GEN_PASS_DEF_CUFIMPLICITDEVICEGLOBAL +#define GEN_PASS_DEF_CUFDEVICEGLOBAL #include "flang/Optimizer/Transforms/Passes.h.inc" } // namespace fir @@ -45,8 +45,7 @@ static void prepareImplicitDeviceGlobals(mlir::func::FuncOp funcOp, } } -class CufImplicitDeviceGlobal - : public fir::impl::CufImplicitDeviceGlobalBase { +class CUFDeviceGlobal : public fir::impl::CUFDeviceGlobalBase { public: void runOnOperation() override { mlir::Operation *op = getOperation(); diff --git a/flang/lib/Optimizer/Transforms/CufOpConversion.cpp b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp similarity index 88% rename from flang/lib/Optimizer/Transforms/CufOpConversion.cpp rename to flang/lib/Optimizer/Transforms/CUFOpConversion.cpp index 91ef1259332de..069d88e0afca4 100644 --- a/flang/lib/Optimizer/Transforms/CufOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp @@ -1,4 +1,4 @@ -//===-- CufOpConversion.cpp -----------------------------------------------===// +//===-- CUFDeviceGlobal.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "flang/Optimizer/Transforms/CufOpConversion.h" +#include "flang/Optimizer/Transforms/CUFOpConversion.h" #include "flang/Common/Fortran.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" #include "flang/Optimizer/CodeGen/TypeConverter.h" @@ -20,6 +20,7 @@ #include "flang/Runtime/CUDA/descriptor.h" #include "flang/Runtime/CUDA/memory.h" #include "flang/Runtime/allocatable.h" +#include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" @@ -77,6 +78,69 @@ static bool hasDoubleDescriptors(OpTy op) { return false; } +static mlir::Value createConvertOp(mlir::PatternRewriter &rewriter, + mlir::Location loc, mlir::Type toTy, + mlir::Value val) { + if (val.getType() != toTy) + return rewriter.create(loc, toTy, val); + return val; +} + +mlir::Value getDeviceAddress(mlir::PatternRewriter &rewriter, + mlir::OpOperand &operand, + const mlir::SymbolTable &symtab) { + mlir::Value v = operand.get(); + auto declareOp = v.getDefiningOp(); + if (!declareOp) + return v; + + auto addrOfOp = declareOp.getMemref().getDefiningOp(); + if (!addrOfOp) + return v; + + auto globalOp = symtab.lookup( + addrOfOp.getSymbol().getRootReference().getValue()); + + if (!globalOp) + return v; + + bool isDevGlobal{false}; + auto attr = globalOp.getDataAttrAttr(); + if (attr) { + switch (attr.getValue()) { + case cuf::DataAttribute::Device: + case cuf::DataAttribute::Managed: + case cuf::DataAttribute::Pinned: + isDevGlobal = true; + break; + default: + break; + } + } + if (!isDevGlobal) + return v; + mlir::OpBuilder::InsertionGuard guard(rewriter); + rewriter.setInsertionPoint(operand.getOwner()); + auto loc = declareOp.getLoc(); + auto mod = declareOp->getParentOfType(); + fir::FirOpBuilder builder(rewriter, mod); + + mlir::func::FuncOp callee = + fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = callee.getFunctionType(); + auto toTy = fTy.getInput(0); + mlir::Value inputArg = + createConvertOp(rewriter, loc, toTy, declareOp.getResult()); + mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); + mlir::Value sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(2)); + llvm::SmallVector args{fir::runtime::createArguments( + builder, loc, fTy, inputArg, sourceFile, sourceLine)}; + auto call = rewriter.create(loc, callee, args); + + return call->getResult(0); +} + template static mlir::LogicalResult convertOpToCall(OpTy op, mlir::PatternRewriter &rewriter, @@ -363,18 +427,14 @@ struct CufFreeOpConversion : public mlir::OpRewritePattern { } }; -static mlir::Value createConvertOp(mlir::PatternRewriter &rewriter, - mlir::Location loc, mlir::Type toTy, - mlir::Value val) { - if (val.getType() != toTy) - return rewriter.create(loc, toTy, val); - return val; -} - struct CufDataTransferOpConversion : public mlir::OpRewritePattern { using OpRewritePattern::OpRewritePattern; + CufDataTransferOpConversion(mlir::MLIRContext *context, + const mlir::SymbolTable &symtab) + : OpRewritePattern(context), symtab{symtab} {} + mlir::LogicalResult matchAndRewrite(cuf::DataTransferOp op, mlir::PatternRewriter &rewriter) const override { @@ -445,9 +505,11 @@ struct CufDataTransferOpConversion mlir::Value sourceLine = fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); - llvm::SmallVector args{fir::runtime::createArguments( - builder, loc, fTy, op.getDst(), op.getSrc(), bytes, modeValue, - sourceFile, sourceLine)}; + mlir::Value dst = getDeviceAddress(rewriter, op.getDstMutable(), symtab); + mlir::Value src = getDeviceAddress(rewriter, op.getSrcMutable(), symtab); + llvm::SmallVector args{ + fir::runtime::createArguments(builder, loc, fTy, dst, src, bytes, + modeValue, sourceFile, sourceLine)}; builder.create(loc, func, args); rewriter.eraseOp(op); return mlir::success(); @@ -552,9 +614,12 @@ struct CufDataTransferOpConversion } return mlir::success(); } + +private: + const mlir::SymbolTable &symtab; }; -class CufOpConversion : public fir::impl::CufOpConversionBase { +class CUFOpConversion : public fir::impl::CUFOpConversionBase { public: void runOnOperation() override { auto *ctx = &getContext(); @@ -565,13 +630,15 @@ class CufOpConversion : public fir::impl::CufOpConversionBase { mlir::ModuleOp module = mlir::dyn_cast(op); if (!module) return signalPassFailure(); + mlir::SymbolTable symtab(module); std::optional dl = fir::support::getOrSetDataLayout(module, /*allowDefaultLayout=*/false); fir::LLVMTypeConverter typeConverter(module, /*applyTBAA=*/false, /*forceUnifiedTBAATree=*/false, *dl); target.addLegalDialect(); - cuf::populateCUFToFIRConversionPatterns(typeConverter, *dl, patterns); + cuf::populateCUFToFIRConversionPatterns(typeConverter, *dl, symtab, + patterns); if (mlir::failed(mlir::applyPartialConversion(getOperation(), target, std::move(patterns)))) { mlir::emitError(mlir::UnknownLoc::get(ctx), @@ -584,9 +651,9 @@ class CufOpConversion : public fir::impl::CufOpConversionBase { void cuf::populateCUFToFIRConversionPatterns( const fir::LLVMTypeConverter &converter, mlir::DataLayout &dl, - mlir::RewritePatternSet &patterns) { + const mlir::SymbolTable &symtab, mlir::RewritePatternSet &patterns) { patterns.insert(patterns.getContext(), &dl, &converter); patterns.insert( - patterns.getContext()); + CufFreeOpConversion>(patterns.getContext()); + patterns.insert(patterns.getContext(), symtab); } diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 8634c522cf343..9b4cdf3720b78 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -110,7 +110,7 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( "ALWAYS" >> pure(OmpMapClause::TypeModifier::Always) || "CLOSE" >> pure(OmpMapClause::TypeModifier::Close) || - "OMPX_HOLD" >> pure(OmpMapClause::TypeModifier::OmpxHold) || + "OMPX_HOLD" >> pure(OmpMapClause::TypeModifier::Ompx_Hold) || "PRESENT" >> pure(OmpMapClause::TypeModifier::Present))) TYPE_PARSER( @@ -657,33 +657,36 @@ TYPE_PARSER(construct(startOmpLine >> "END ATOMIC"_tok)) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] READ [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER("ATOMIC" >> - construct(Parser{} / maybe(","_tok), - verbatim("READ"_tok), Parser{} / endOmpLine, - statement(assignmentStmt), maybe(Parser{} / endOmpLine))) + sourced(construct( + Parser{} / maybe(","_tok), verbatim("READ"_tok), + Parser{} / endOmpLine, statement(assignmentStmt), + maybe(Parser{} / endOmpLine)))) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] CAPTURE [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER("ATOMIC" >> - construct(Parser{} / maybe(","_tok), - verbatim("CAPTURE"_tok), Parser{} / endOmpLine, - statement(assignmentStmt), statement(assignmentStmt), - Parser{} / endOmpLine)) + sourced(construct( + Parser{} / maybe(","_tok), verbatim("CAPTURE"_tok), + Parser{} / endOmpLine, statement(assignmentStmt), + statement(assignmentStmt), Parser{} / endOmpLine))) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] UPDATE [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER("ATOMIC" >> - construct(Parser{} / maybe(","_tok), - verbatim("UPDATE"_tok), Parser{} / endOmpLine, - statement(assignmentStmt), maybe(Parser{} / endOmpLine))) + sourced(construct( + Parser{} / maybe(","_tok), verbatim("UPDATE"_tok), + Parser{} / endOmpLine, statement(assignmentStmt), + maybe(Parser{} / endOmpLine)))) // OMP ATOMIC [atomic-clause-list] -TYPE_PARSER(construct(verbatim("ATOMIC"_tok), +TYPE_PARSER(sourced(construct(verbatim("ATOMIC"_tok), Parser{} / endOmpLine, statement(assignmentStmt), - maybe(Parser{} / endOmpLine))) + maybe(Parser{} / endOmpLine)))) // OMP ATOMIC [MEMORY-ORDER-CLAUSE-LIST] WRITE [MEMORY-ORDER-CLAUSE-LIST] TYPE_PARSER("ATOMIC" >> - construct(Parser{} / maybe(","_tok), - verbatim("WRITE"_tok), Parser{} / endOmpLine, - statement(assignmentStmt), maybe(Parser{} / endOmpLine))) + sourced(construct( + Parser{} / maybe(","_tok), verbatim("WRITE"_tok), + Parser{} / endOmpLine, statement(assignmentStmt), + maybe(Parser{} / endOmpLine)))) // Atomic Construct TYPE_PARSER(construct(Parser{}) || diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index d1011fe58a026..d65ddfabb05d9 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2087,13 +2087,6 @@ class UnparseVisitor { } Walk(std::get(x.t)); } - void Unparse(const OmpMapClause::TypeModifier &x) { - if (x == OmpMapClause::TypeModifier::OmpxHold) { - Word("OMPX_HOLD"); - } else { - Word(OmpMapClause::EnumToString(x)); - } - } void Unparse(const OmpScheduleModifier &x) { Walk(std::get(x.t)); Walk(",", std::get>(x.t)); @@ -2801,6 +2794,7 @@ class UnparseVisitor { WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier WALK_NESTED_ENUM(OmpMapClause, Type) // OMP map-type + WALK_NESTED_ENUM(OmpMapClause, TypeModifier) // OMP map-type-modifier #undef WALK_NESTED_ENUM void Unparse(const ReductionOperator::Operator x) { switch (x) { diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 461a99f59e4ce..6479d15821d14 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1888,16 +1888,21 @@ inline void OmpStructureChecker::ErrIfLHSAndRHSSymbolsMatch( inline void OmpStructureChecker::ErrIfNonScalarAssignmentStmt( const parser::Variable &var, const parser::Expr &expr) { // Err out if either the variable on the LHS or the expression on the RHS of - // the assignment statement are non-scalar (i.e. have rank > 0) + // the assignment statement are non-scalar (i.e. have rank > 0 or is of + // CHARACTER type) const auto *e{GetExpr(context_, expr)}; const auto *v{GetExpr(context_, var)}; if (e && v) { - if (e->Rank() != 0) + if (e->Rank() != 0 || + (e->GetType().has_value() && + e->GetType().value().category() == common::TypeCategory::Character)) context_.Say(expr.source, "Expected scalar expression " "on the RHS of atomic assignment " "statement"_err_en_US); - if (v->Rank() != 0) + if (v->Rank() != 0 || + (v->GetType().has_value() && + v->GetType()->category() == common::TypeCategory::Character)) context_.Say(var.GetSource(), "Expected scalar variable " "on the LHS of atomic assignment " @@ -2008,12 +2013,16 @@ void OmpStructureChecker::CheckAtomicUpdateStmt( expr.u); if (const auto *e{GetExpr(context_, expr)}) { const auto *v{GetExpr(context_, var)}; - if (e->Rank() != 0) + if (e->Rank() != 0 || + (e->GetType().has_value() && + e->GetType().value().category() == common::TypeCategory::Character)) context_.Say(expr.source, "Expected scalar expression " "on the RHS of atomic update assignment " "statement"_err_en_US); - if (v->Rank() != 0) + if (v->Rank() != 0 || + (v->GetType().has_value() && + v->GetType()->category() == common::TypeCategory::Character)) context_.Say(var.GetSource(), "Expected scalar variable " "on the LHS of atomic update assignment " diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 2fa5b75e073b6..030dbc5ea0f02 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1530,6 +1530,23 @@ class OmpVisitor : public virtual DeclarationVisitor { void Post(const parser::OpenMPDeclarativeAllocate &) { SkipImplicitTyping(false); } + bool Pre(const parser::OpenMPDeclarativeConstruct &x) { + AddOmpSourceRange(x.source); + return true; + } + void Post(const parser::OpenMPDeclarativeConstruct &) { + messageHandler().set_currStmtSource(std::nullopt); + } + bool Pre(const parser::OpenMPAtomicConstruct &x) { + return common::visit(common::visitors{[&](const auto &u) -> bool { + AddOmpSourceRange(u.source); + return true; + }}, + x.u); + } + void Post(const parser::OpenMPAtomicConstruct &) { + messageHandler().set_currStmtSource(std::nullopt); + } }; bool OmpVisitor::NeedsScope(const parser::OpenMPBlockConstruct &x) { diff --git a/flang/runtime/CUDA/CMakeLists.txt b/flang/runtime/CUDA/CMakeLists.txt index 193dd77e93455..86523b419f871 100644 --- a/flang/runtime/CUDA/CMakeLists.txt +++ b/flang/runtime/CUDA/CMakeLists.txt @@ -18,6 +18,7 @@ add_flang_library(${CUFRT_LIBNAME} allocatable.cpp descriptor.cpp memory.cpp + registration.cpp ) if (BUILD_SHARED_LIBS) diff --git a/flang/runtime/CUDA/registration.cpp b/flang/runtime/CUDA/registration.cpp new file mode 100644 index 0000000000000..e5d9503e95fd8 --- /dev/null +++ b/flang/runtime/CUDA/registration.cpp @@ -0,0 +1,34 @@ +//===-- runtime/CUDA/registration.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 "flang/Runtime/CUDA/registration.h" + +#include "cuda_runtime.h" + +namespace Fortran::runtime::cuda { + +extern "C" { + +extern void **__cudaRegisterFatBinary(void *); +extern void __cudaRegisterFatBinaryEnd(void *); +extern void __cudaRegisterFunction(void **fatCubinHandle, const char *hostFun, + char *deviceFun, const char *deviceName, int thread_limit, uint3 *tid, + uint3 *bid, dim3 *bDim, dim3 *gDim, int *wSize); + +void *RTDECL(CUFRegisterModule)(void *data) { + void **fatHandle{__cudaRegisterFatBinary(data)}; + __cudaRegisterFatBinaryEnd(fatHandle); + return fatHandle; +} + +void RTDEF(CUFRegisterFunction)(void **module, const char *fct) { + __cudaRegisterFunction(module, fct, const_cast(fct), fct, -1, + (uint3 *)0, (uint3 *)0, (dim3 *)0, (dim3 *)0, (int *)0); +} +} +} // namespace Fortran::runtime::cuda diff --git a/flang/test/Driver/msvc-dependent-lib-flags.f90 b/flang/test/Driver/msvc-dependent-lib-flags.f90 index 1b7ecb604ad67..765917f07d8e7 100644 --- a/flang/test/Driver/msvc-dependent-lib-flags.f90 +++ b/flang/test/Driver/msvc-dependent-lib-flags.f90 @@ -1,36 +1,36 @@ -! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC -! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=static_dbg %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DEBUG -! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=dll %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL -! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=dll_dbg %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL-DEBUG - -! MSVC: -fc1 -! MSVC-SAME: --dependent-lib=clang_rt.builtins.lib -! MSVC-SAME: -D_MT -! MSVC-SAME: --dependent-lib=libcmt -! MSVC-SAME: --dependent-lib=FortranRuntime.static.lib -! MSVC-SAME: --dependent-lib=FortranDecimal.static.lib - -! MSVC-DEBUG: -fc1 -! MSVC-DEBUG-SAME: --dependent-lib=clang_rt.builtins.lib -! MSVC-DEBUG-SAME: -D_MT -! MSVC-DEBUG-SAME: -D_DEBUG -! MSVC-DEBUG-SAME: --dependent-lib=libcmtd -! MSVC-DEBUG-SAME: --dependent-lib=FortranRuntime.static_dbg.lib -! MSVC-DEBUG-SAME: --dependent-lib=FortranDecimal.static_dbg.lib - -! MSVC-DLL: -fc1 -! MSVC-DLL-SAME: --dependent-lib=clang_rt.builtins.lib -! MSVC-DLL-SAME: -D_MT -! MSVC-DLL-SAME: -D_DLL -! MSVC-DLL-SAME: --dependent-lib=msvcrt -! MSVC-DLL-SAME: --dependent-lib=FortranRuntime.dynamic.lib -! MSVC-DLL-SAME: --dependent-lib=FortranDecimal.dynamic.lib - -! MSVC-DLL-DEBUG: -fc1 -! MSVC-DLL-DEBUG-SAME: --dependent-lib=clang_rt.builtins.lib -! MSVC-DLL-DEBUG-SAME: -D_MT -! MSVC-DLL-DEBUG-SAME: -D_DEBUG -! MSVC-DLL-DEBUG-SAME: -D_DLL -! MSVC-DLL-DEBUG-SAME: --dependent-lib=msvcrtd -! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranRuntime.dynamic_dbg.lib -! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranDecimal.dynamic_dbg.lib +! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC +! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=static_dbg %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DEBUG +! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=dll %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL +! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=dll_dbg %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL-DEBUG + +! MSVC: -fc1 +! MSVC-SAME: --dependent-lib=clang_rt.builtins.lib +! MSVC-SAME: -D_MT +! MSVC-SAME: --dependent-lib=libcmt +! MSVC-SAME: --dependent-lib=FortranRuntime.static.lib +! MSVC-SAME: --dependent-lib=FortranDecimal.static.lib + +! MSVC-DEBUG: -fc1 +! MSVC-DEBUG-SAME: --dependent-lib=clang_rt.builtins.lib +! MSVC-DEBUG-SAME: -D_MT +! MSVC-DEBUG-SAME: -D_DEBUG +! MSVC-DEBUG-SAME: --dependent-lib=libcmtd +! MSVC-DEBUG-SAME: --dependent-lib=FortranRuntime.static_dbg.lib +! MSVC-DEBUG-SAME: --dependent-lib=FortranDecimal.static_dbg.lib + +! MSVC-DLL: -fc1 +! MSVC-DLL-SAME: --dependent-lib=clang_rt.builtins.lib +! MSVC-DLL-SAME: -D_MT +! MSVC-DLL-SAME: -D_DLL +! MSVC-DLL-SAME: --dependent-lib=msvcrt +! MSVC-DLL-SAME: --dependent-lib=FortranRuntime.dynamic.lib +! MSVC-DLL-SAME: --dependent-lib=FortranDecimal.dynamic.lib + +! MSVC-DLL-DEBUG: -fc1 +! MSVC-DLL-DEBUG-SAME: --dependent-lib=clang_rt.builtins.lib +! MSVC-DLL-DEBUG-SAME: -D_MT +! MSVC-DLL-DEBUG-SAME: -D_DEBUG +! MSVC-DLL-DEBUG-SAME: -D_DLL +! MSVC-DLL-DEBUG-SAME: --dependent-lib=msvcrtd +! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranRuntime.dynamic_dbg.lib +! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranDecimal.dynamic_dbg.lib diff --git a/flang/test/Fir/CUDA/cuda-data-transfer.fir b/flang/test/Fir/CUDA/cuda-data-transfer.fir index ed894aed5534a..c33c50115b9fc 100644 --- a/flang/test/Fir/CUDA/cuda-data-transfer.fir +++ b/flang/test/Fir/CUDA/cuda-data-transfer.fir @@ -189,4 +189,47 @@ func.func @_QPsub7() { // CHECK: %[[SRC:.*]] = fir.convert %[[IHOST]]#0 : (!fir.ref>) -> !fir.llvm_ptr // CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%[[DST]], %[[SRC]], %[[BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none +fir.global @_QMmtestsEn(dense<[3, 4, 5, 6, 7]> : tensor<5xi32>) {data_attr = #cuf.cuda} : !fir.array<5xi32> +func.func @_QPsub8() attributes {fir.bindc_name = "t"} { + %c5 = arith.constant 5 : index + %0 = fir.alloca !fir.array<5xi32> {bindc_name = "m", uniq_name = "_QFEm"} + %1 = fir.shape %c5 : (index) -> !fir.shape<1> + %2 = fir.declare %0(%1) {uniq_name = "_QFEm"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + %3 = fir.address_of(@_QMmtestsEn) : !fir.ref> + %4 = fir.declare %3(%1) {data_attr = #cuf.cuda, uniq_name = "_QMmtestsEn"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + cuf.data_transfer %4 to %2 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>, !fir.ref> + return +} + +// CHECK-LABEL: func.func @_QPsub8() +// CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<5xi32> +// CHECK: %[[LOCAL:.*]] = fir.declare %[[ALLOCA]] +// CHECK: %[[GBL:.*]] = fir.address_of(@_QMmtestsEn) : !fir.ref> +// CHECK: %[[DECL:.*]] = fir.declare %[[GBL]] +// CHECK: %[[HOST:.*]] = fir.convert %[[DECL]] : (!fir.ref>) -> !fir.llvm_ptr +// CHECK: %[[SRC:.*]] = fir.call @_FortranACUFGetDeviceAddress(%[[HOST]], %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.ref, i32) -> !fir.llvm_ptr +// CHECK: %[[DST:.*]] = fir.convert %[[LOCAL]] : (!fir.ref>) -> !fir.llvm_ptr +// CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%[[DST]], %[[SRC]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none + + +func.func @_QPsub9() { + %c5 = arith.constant 5 : index + %0 = fir.alloca !fir.array<5xi32> {bindc_name = "m", uniq_name = "_QFtest9Em"} + %1 = fir.shape %c5 : (index) -> !fir.shape<1> + %2 = fir.declare %0(%1) {uniq_name = "_QFtest9Em"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + %3 = fir.address_of(@_QMmtestsEn) : !fir.ref> + %4 = fir.declare %3(%1) {data_attr = #cuf.cuda, uniq_name = "_QMmtestsEn"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + cuf.data_transfer %2 to %4 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>, !fir.ref> + return +} + +// CHECK-LABEL: func.func @_QPsub9() +// CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<5xi32> +// CHECK: %[[LOCAL:.*]] = fir.declare %[[ALLOCA]] +// CHECK: %[[GBL:.*]] = fir.address_of(@_QMmtestsEn) : !fir.ref> +// CHECK: %[[DECL:.*]] = fir.declare %[[GBL]] +// CHECK: %[[HOST:.*]] = fir.convert %[[DECL]] : (!fir.ref>) -> !fir.llvm_ptr +// CHECK: %[[DST:.*]] = fir.call @_FortranACUFGetDeviceAddress(%[[HOST]], %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.ref, i32) -> !fir.llvm_ptr +// CHECK: %[[SRC:.*]] = fir.convert %[[LOCAL]] : (!fir.ref>) -> !fir.llvm_ptr +// CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%[[DST]], %[[SRC]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none } // end of module diff --git a/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 b/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 index c8bee3c62e644..82a0c5948d9cb 100644 --- a/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 +++ b/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 @@ -1,4 +1,4 @@ -// RUN: fir-opt --split-input-file --cuf-implicit-device-global %s | FileCheck %s +// RUN: fir-opt --split-input-file --cuf-device-global %s | FileCheck %s // Test that global used in device function are flagged with the correct // attribute. diff --git a/flang/test/Fir/CUDA/cuda-register-func.fir b/flang/test/Fir/CUDA/cuda-register-func.fir index 277475f0883dc..6b0cbfd3aca63 100644 --- a/flang/test/Fir/CUDA/cuda-register-func.fir +++ b/flang/test/Fir/CUDA/cuda-register-func.fir @@ -12,5 +12,6 @@ module attributes {gpu.container_module} { } // CHECK-LABEL: llvm.func internal @__cudaFortranConstructor() -// CHECK: cuf.register_kernel @cuda_device_mod::@_QPsub_device1 -// CHECK: cuf.register_kernel @cuda_device_mod::@_QPsub_device2 +// CHECK: %[[MOD_HANDLE:.*]] = cuf.register_module @cuda_device_mod -> !llvm.ptr +// CHECK: cuf.register_kernel @cuda_device_mod::@_QPsub_device1(%[[MOD_HANDLE]] : !llvm.ptr) +// CHECK: cuf.register_kernel @cuda_device_mod::@_QPsub_device2(%[[MOD_HANDLE]] : !llvm.ptr) diff --git a/flang/test/Fir/OpenACC/legalize-data.fir b/flang/test/Fir/OpenACC/legalize-data.fir index 3b8695434e6e4..6bc81dc08db30 100644 --- a/flang/test/Fir/OpenACC/legalize-data.fir +++ b/flang/test/Fir/OpenACC/legalize-data.fir @@ -1,4 +1,4 @@ -// RUN: fir-opt -split-input-file --openacc-legalize-data %s | FileCheck %s +// RUN: fir-opt -split-input-file --openacc-legalize-data-values %s | FileCheck %s func.func @_QPsub1(%arg0: !fir.ref {fir.bindc_name = "i"}) { %0:2 = hlfir.declare %arg0 {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) @@ -22,3 +22,36 @@ func.func @_QPsub1(%arg0: !fir.ref {fir.bindc_name = "i"}) { // CHECK: acc.yield // CHECK: } // CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref) to varPtr(%[[I]]#0 : !fir.ref) {dataClause = #acc, name = "i"} + +// ----- + +func.func @_QPsub1(%arg0: !fir.ref {fir.bindc_name = "i"}) { + %0:2 = hlfir.declare %arg0 {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %1 = acc.copyin varPtr(%0#0 : !fir.ref) -> !fir.ref {dataClause = #acc, name = "i"} + acc.data dataOperands(%1 : !fir.ref) { + %c0_i32 = arith.constant 0 : i32 + hlfir.assign %c0_i32 to %0#0 : i32, !fir.ref + acc.serial { + hlfir.assign %c0_i32 to %0#0 : i32, !fir.ref + acc.yield + } + acc.terminator + } + acc.copyout accPtr(%1 : !fir.ref) to varPtr(%0#0 : !fir.ref) {dataClause = #acc, name = "i"} + return +} + +// CHECK-LABEL: func.func @_QPsub1 +// CHECK-SAME: (%[[ARG0:.*]]: !fir.ref {fir.bindc_name = "i"}) +// CHECK: %[[I:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) +// CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[I]]#0 : !fir.ref) -> !fir.ref {dataClause = #acc, name = "i"} +// CHECK: acc.data dataOperands(%[[COPYIN]] : !fir.ref) { +// CHECK: %[[C0:.*]] = arith.constant 0 : i32 +// CHECK: hlfir.assign %[[C0]] to %0#0 : i32, !fir.ref +// CHECK: acc.serial { +// CHECK: hlfir.assign %[[C0]] to %[[COPYIN]] : i32, !fir.ref +// CHECK: acc.yield +// CHECK: } +// CHECK: acc.terminator +// CHECK: } +// CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref) to varPtr(%[[I]]#0 : !fir.ref) {dataClause = #acc, name = "i"} diff --git a/flang/test/Fir/cuf-invalid.fir b/flang/test/Fir/cuf-invalid.fir index 8a1eb48576832..a3b9be3ee8223 100644 --- a/flang/test/Fir/cuf-invalid.fir +++ b/flang/test/Fir/cuf-invalid.fir @@ -135,8 +135,9 @@ module attributes {gpu.container_module} { } } llvm.func internal @__cudaFortranConstructor() { + %0 = cuf.register_module @cuda_device_mod -> !llvm.ptr // expected-error@+1{{'cuf.register_kernel' op only kernel gpu.func can be registered}} - cuf.register_kernel @cuda_device_mod::@_QPsub_device1 + cuf.register_kernel @cuda_device_mod::@_QPsub_device1(%0 : !llvm.ptr) llvm.return } } @@ -150,8 +151,9 @@ module attributes {gpu.container_module} { } } llvm.func internal @__cudaFortranConstructor() { + %0 = cuf.register_module @cuda_device_mod -> !llvm.ptr // expected-error@+1{{'cuf.register_kernel' op device function not found}} - cuf.register_kernel @cuda_device_mod::@_QPsub_device2 + cuf.register_kernel @cuda_device_mod::@_QPsub_device2(%0 : !llvm.ptr) llvm.return } } @@ -160,8 +162,9 @@ module attributes {gpu.container_module} { module attributes {gpu.container_module} { llvm.func internal @__cudaFortranConstructor() { + %0 = cuf.register_module @cuda_device_mod -> !llvm.ptr // expected-error@+1{{'cuf.register_kernel' op gpu module not found}} - cuf.register_kernel @cuda_device_mod::@_QPsub_device1 + cuf.register_kernel @cuda_device_mod::@_QPsub_device1(%0 : !llvm.ptr) llvm.return } } @@ -170,8 +173,9 @@ module attributes {gpu.container_module} { module attributes {gpu.container_module} { llvm.func internal @__cudaFortranConstructor() { + %0 = cuf.register_module @cuda_device_mod -> !llvm.ptr // expected-error@+1{{'cuf.register_kernel' op expect a module and a kernel name}} - cuf.register_kernel @_QPsub_device1 + cuf.register_kernel @_QPsub_device1(%0 : !llvm.ptr) llvm.return } } @@ -185,8 +189,9 @@ module attributes {gpu.container_module} { } } llvm.func internal @__cudaFortranConstructor() { + %0 = cuf.register_module @cuda_device_mod -> !llvm.ptr // expected-error@+1{{'cuf.register_kernel' op only gpu.kernel llvm.func can be registered}} - cuf.register_kernel @cuda_device_mod::@_QPsub_device1 + cuf.register_kernel @cuda_device_mod::@_QPsub_device1(%0 : !llvm.ptr) llvm.return } } diff --git a/flang/test/HLFIR/assign-side-effects.fir b/flang/test/HLFIR/assign-side-effects.fir new file mode 100644 index 0000000000000..dfd1c5886e4fa --- /dev/null +++ b/flang/test/HLFIR/assign-side-effects.fir @@ -0,0 +1,31 @@ +// Test side effects of hlfir.assign op. +// RUN: fir-opt %s --test-side-effects --verify-diagnostics + +func.func @test1(%x: !fir.ref, %i: i32) { + // expected-remark @below {{found an instance of 'write' on a op operand, on resource ''}} + hlfir.assign %i to %x : i32, !fir.ref + return +} + +func.func @test2(%x: !fir.ref, %y: !fir.ref) { + // expected-remark @below {{found an instance of 'write' on a op operand, on resource ''}} + // expected-remark @below {{found an instance of 'read' on a op operand, on resource ''}} + hlfir.assign %y to %x : !fir.ref, !fir.ref + return +} + +func.func @test3(%x: !fir.ref>, %y: !fir.ref>) { + // expected-remark @below {{found an instance of 'write' on resource ''}} + // expected-remark @below {{found an instance of 'read' on resource ''}} + hlfir.assign %y to %x : !fir.ref>, !fir.ref> + return +} + +func.func @test4(%x: !fir.ref>>>, %y: !fir.box>) { + // expected-remark @below {{found an instance of 'read' on a op operand, on resource ''}} + // expected-remark @below {{found an instance of 'write' on resource ''}} + // expected-remark @below {{found an instance of 'free' on resource ''}} + // expected-remark @below {{found an instance of 'allocate' on resource ''}} + hlfir.assign %y to %x realloc : !fir.box>, !fir.ref>>> + return +} diff --git a/flang/test/HLFIR/order_assignments/vector-subscripts-scheduling.fir b/flang/test/HLFIR/order_assignments/vector-subscripts-scheduling.fir new file mode 100644 index 0000000000000..b76492efe2a56 --- /dev/null +++ b/flang/test/HLFIR/order_assignments/vector-subscripts-scheduling.fir @@ -0,0 +1,31 @@ +// Test local alloca and store inside hlfir.region_assign do not trigger the +// creation of a temporary for the LHS. + +// RUN: fir-opt -o - -lower-hlfir-ordered-assignments --debug-only=flang-ordered-assignment -flang-dbg-order-assignment-schedule-only %s 2>&1 | FileCheck %s +// REQUIRES: asserts + +func.func @simple(%arg0: !fir.ref> , %arg1: !fir.ref> , %arg2: !fir.ref>, %i: i64, %f: f32) { + %c10 = arith.constant 10 : index + %c100 = arith.constant 100 : index + %0 = fir.shape %c100, %c10 : (index, index) -> !fir.shape<2> + %1:2 = hlfir.declare %arg0(%0) {uniq_name = "_QFsimpleEx"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) + %2 = fir.shape %c10 : (index) -> !fir.shape<1> + %3:2 = hlfir.declare %arg1(%2) {uniq_name = "y"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + hlfir.region_assign { + hlfir.yield %f : f32 + } to { + %local_temp = fir.alloca i64 + fir.store %i to %local_temp : !fir.ref + %icopy = fir.load %local_temp : !fir.ref + hlfir.elemental_addr %2 : !fir.shape<1> { + ^bb0(%arg3: index): + %5 = hlfir.designate %3#0 (%arg3) : (!fir.ref>, index) -> !fir.ref + %6 = fir.load %5 : !fir.ref + %7 = hlfir.designate %1#0 (%icopy, %6) : (!fir.ref>, i64, i64) -> !fir.ref + hlfir.yield %7 : !fir.ref + } + } + return +} + +// CHECK: run 1 evaluate: region_assign diff --git a/flang/test/HLFIR/order_assignments/where-scheduling.f90 b/flang/test/HLFIR/order_assignments/where-scheduling.f90 index ab87ae92de579..3010476d4a188 100644 --- a/flang/test/HLFIR/order_assignments/where-scheduling.f90 +++ b/flang/test/HLFIR/order_assignments/where-scheduling.f90 @@ -135,6 +135,7 @@ end function f !CHECK-NEXT: run 2 evaluate: where/region_assign1 !CHECK-LABEL: ------------ scheduling where in _QPonly_once ------------ !CHECK-NEXT: unknown effect: %{{[0-9]+}} = llvm.intr.stacksave : !llvm.ptr +!CHECK-NEXT: saving eval because write effect prevents re-evaluation !CHECK-NEXT: run 1 save (w): where/mask !CHECK-NEXT: run 2 evaluate: where/region_assign1 !CHECK-NEXT: run 3 evaluate: where/region_assign2 @@ -180,6 +181,7 @@ end function f !CHECK-NEXT: conflict: R/W: %{{.*}} = hlfir.declare %{{.*}} {uniq_name = "_QFwhere_construct_unknown_conflictEmask"} : (!fir.box>>, !fir.dscope) -> (!fir.box>>, !fir.box>>) W: !CHECK-NEXT: run 1 save : where/mask !CHECK-NEXT: unknown effect: %{{.*}} = fir.call @_QPf() fastmath : () -> f32 +!CHECK-NEXT: saving eval because write effect prevents re-evaluation !CHECK-NEXT: run 2 save (w): where/region_assign1/rhs !CHECK-NEXT: run 3 evaluate: where/region_assign1 !CHECK-NEXT: ------------ scheduling where in _QPelsewhere_construct_unknown_conflict ------------ @@ -190,5 +192,6 @@ end function f !CHECK-NEXT: conflict: R/W: %{{.*}} = hlfir.declare %{{.*}} {uniq_name = "_QFelsewhere_construct_unknown_conflictEmask2"} : (!fir.box>>, !fir.dscope) -> (!fir.box>>, !fir.box>>) W: !CHECK-NEXT: run 2 save : where/elsewhere1/mask !CHECK-NEXT: unknown effect: %{{.*}} = fir.call @_QPf() fastmath : () -> f32 +!CHECK-NEXT: saving eval because write effect prevents re-evaluation !CHECK-NEXT: run 3 save (w): where/elsewhere1/region_assign1/rhs !CHECK-NEXT: run 4 evaluate: where/elsewhere1/region_assign1 diff --git a/flang/test/Integration/debug-extra-global-2.f90 b/flang/test/Integration/debug-extra-global-2.f90 new file mode 100644 index 0000000000000..59cb4b66def50 --- /dev/null +++ b/flang/test/Integration/debug-extra-global-2.f90 @@ -0,0 +1,8 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +module m + integer XcX +end + +! Test that global starting with 'X' don't get filtered. +! CHECK: !DIGlobalVariable(name: "xcx", linkageName: "_QMmExcx"{{.*}}) diff --git a/flang/test/Integration/debug-extra-global.f90 b/flang/test/Integration/debug-extra-global.f90 new file mode 100644 index 0000000000000..c0ad2e306386d --- /dev/null +++ b/flang/test/Integration/debug-extra-global.f90 @@ -0,0 +1,14 @@ +! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s + +program test + type t1 + integer :: XcX + integer :: xdtx + end type + type(t1) :: var + var%XcX = 2 + var%xdtx = 3 +end + +! Test that there is no debug info for compiler generated globals. +! CHECK-NOT: DIGlobalVariable diff --git a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 index a27de1152ce17..e11525c569ffb 100644 --- a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 +++ b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-allocatable.f90 @@ -18,22 +18,22 @@ end subroutine target_allocatable ! CHECK-SAME: @[[VAR_PRIVATIZER_SYM:.*]] : ! CHECK-SAME: [[TYPE:!fir.ref>>]] alloc { ! CHECK: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]): -! CHECK: %[[PRIV_ALLOC:.*]] = fir.alloca !fir.box> {bindc_name = "alloc_var", {{.*}}} +! CHECK: %[[PRIV_ALLOC:.*]] = fir.alloca [[DESC_TYPE:!fir.box>]] {bindc_name = "alloc_var", {{.*}}} -! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]] : !fir.ref>> -! CHECK-NEXT: %[[PRIV_ARG_BOX:.*]] = fir.box_addr %[[PRIV_ARG_VAL]] : (!fir.box>) -> !fir.heap +! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]] : [[TYPE]] +! CHECK-NEXT: %[[PRIV_ARG_BOX:.*]] = fir.box_addr %[[PRIV_ARG_VAL]] : ([[DESC_TYPE]]) -> !fir.heap ! CHECK-NEXT: %[[PRIV_ARG_ADDR:.*]] = fir.convert %[[PRIV_ARG_BOX]] : (!fir.heap) -> i64 ! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64 ! CHECK-NEXT: %[[ALLOC_COND:.*]] = arith.cmpi ne, %[[PRIV_ARG_ADDR]], %[[C0]] : i64 ! CHECK-NEXT: fir.if %[[ALLOC_COND]] { ! CHECK: %[[PRIV_ALLOCMEM:.*]] = fir.allocmem i32 {fir.must_be_heap = true, {{.*}}} -! CHECK-NEXT: %[[PRIV_ALLOCMEM_BOX:.*]] = fir.embox %[[PRIV_ALLOCMEM]] : (!fir.heap) -> !fir.box> -! CHECK-NEXT: fir.store %[[PRIV_ALLOCMEM_BOX]] to %[[PRIV_ALLOC]] : !fir.ref>> +! CHECK-NEXT: %[[PRIV_ALLOCMEM_BOX:.*]] = fir.embox %[[PRIV_ALLOCMEM]] : (!fir.heap) -> [[DESC_TYPE]] +! CHECK-NEXT: fir.store %[[PRIV_ALLOCMEM_BOX]] to %[[PRIV_ALLOC]] : [[TYPE]] ! CHECK-NEXT: } else { ! CHECK-NEXT: %[[ZERO_BITS:.*]] = fir.zero_bits !fir.heap -! CHECK-NEXT: %[[ZERO_BOX:.*]] = fir.embox %[[ZERO_BITS]] : (!fir.heap) -> !fir.box> -! CHECK-NEXT: fir.store %[[ZERO_BOX]] to %[[PRIV_ALLOC]] : !fir.ref>> +! CHECK-NEXT: %[[ZERO_BOX:.*]] = fir.embox %[[ZERO_BITS]] : (!fir.heap) -> [[DESC_TYPE]] +! CHECK-NEXT: fir.store %[[ZERO_BOX]] to %[[PRIV_ALLOC]] : [[TYPE]] ! CHECK-NEXT: } ! CHECK-NEXT: %[[PRIV_DECL:.*]]:2 = hlfir.declare %[[PRIV_ALLOC]] @@ -63,9 +63,11 @@ end subroutine target_allocatable ! CHECK-LABEL: func.func @_QPtarget_allocatable() { -! CHECK: %[[VAR_ALLOC:.*]] = fir.alloca !fir.box> +! CHECK: %[[VAR_ALLOC:.*]] = fir.alloca [[DESC_TYPE]] ! CHECK-SAME: {bindc_name = "alloc_var", {{.*}}} ! CHECK: %[[VAR_DECL:.*]]:2 = hlfir.declare %[[VAR_ALLOC]] -! CHECK: omp.target private( +! CHECK: %[[MAP_VAR:.*]] = omp.map.info var_ptr(%[[VAR_DECL]]#0 : [[TYPE]], [[DESC_TYPE]]) +! CHECK-SAME: map_clauses(to) capture(ByRef) -> [[TYPE]] +! CHECK: omp.target map_entries(%[[MAP_VAR]] -> %arg0 : [[TYPE]]) private( ! CHECK-SAME: @[[VAR_PRIVATIZER_SYM]] %[[VAR_DECL]]#0 -> %{{.*}} : [[TYPE]]) { diff --git a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 index ce98f518581a4..b0c76ff3845f8 100644 --- a/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 +++ b/flang/test/Lower/OpenMP/DelayedPrivatization/target-private-multiple-variables.f90 @@ -147,12 +147,29 @@ end subroutine target_allocatable ! CHECK-NEXT: } ! CHECK: func.func @_QPtarget_allocatable +! CHECK: %[[CHAR_VAR_DESC_ALLOCA:.*]] = fir.alloca !fir.boxchar<1> +! CHECK: %[[REAL_ARR_DESC_ALLOCA:.*]] = fir.alloca !fir.box> +! CHECK: %[[ALLOC_VAR_ALLOCA:.*]] = fir.alloca !fir.box> {bindc_name = "alloc_var", {{.*}}} +! CHECK: %[[ALLOC_VAR_DECL:.*]]:2 = hlfir.declare %[[ALLOC_VAR_ALLOCA]] ! CHECK: %[[MAPPED_ALLOC:.*]] = fir.alloca i32 {bindc_name = "mapped_var", {{.*}}} ! CHECK-NEXT: %[[MAPPED_DECL:.*]]:2 = hlfir.declare %[[MAPPED_ALLOC]] -! CHECK: %[[MAPPED_MI:.*]] = omp.map.info var_ptr(%[[MAPPED_DECL]]#1 : !fir.ref, i32) - +! CHECK: %[[CHAR_VAR_ALLOC:.*]] = fir.alloca !fir.char<1,?>{{.*}} {bindc_name = "char_var", {{.*}}} +! CHECK: %[[CHAR_VAR_DECL:.*]]:2 = hlfir.declare %[[CHAR_VAR_ALLOC]] typeparams +! CHECK: %[[REAL_ARR_ALLOC:.*]] = fir.alloca !fir.array, {{.*}} {bindc_name = "real_arr", {{.*}}} +! CHECK: %[[REAL_ARR_DECL:.*]]:2 = hlfir.declare %[[REAL_ARR_ALLOC]]({{.*}}) +! CHECK: %[[MAPPED_MI0:.*]] = omp.map.info var_ptr(%[[MAPPED_DECL]]#1 : !fir.ref, i32) {{.*}} +! CHECK: %[[ALLOC_VAR_MAP:.*]] = omp.map.info var_ptr(%[[ALLOC_VAR_DECL]]#0 : !fir.ref>>, !fir.box>) +! CHECK: fir.store %[[REAL_ARR_DECL]]#0 to %[[REAL_ARR_DESC_ALLOCA]] : !fir.ref>> +! CHECK: %[[REAL_ARR_DESC_MAP:.*]] = omp.map.info var_ptr(%[[REAL_ARR_DESC_ALLOCA]] : !fir.ref>>, !fir.box>) +! CHECK: fir.store %[[CHAR_VAR_DECL]]#0 to %[[CHAR_VAR_DESC_ALLOCA]] : !fir.ref> +! CHECK: %[[CHAR_VAR_DESC_MAP:.*]] = omp.map.info var_ptr(%[[CHAR_VAR_DESC_ALLOCA]] : !fir.ref>, !fir.boxchar<1>) ! CHECK: omp.target -! CHECK-SAME: map_entries(%[[MAPPED_MI]] -> %[[MAPPED_ARG:.*]] : !fir.ref) +! CHECK-SAME: map_entries( +! CHECK-SAME: %[[MAPPED_MI0]] -> %[[MAPPED_ARG0:[^,]+]], +! CHECK-SAME: %[[ALLOC_VAR_MAP]] -> %[[MAPPED_ARG1:[^,]+]] +! CHECK-SAME %[[REAL_ARR_DESC_MAP]] -> %[[MAPPED_ARG2:[^,]+]] +! CHECK_SAME %[[CHAR_VAR_DESC_MAP]] -> %[[MAPPED_ARG3:.[^,]+]] : +! CHECK-SAME !fir.ref, !fir.ref>>, !fir.ref>>, !fir.ref>) ! CHECK-SAME: private( ! CHECK-SAME: @[[ALLOC_PRIVATIZER_SYM]] %{{[^[:space:]]+}}#0 -> %[[ALLOC_ARG:[^,]+]], ! CHECK-SAME: @[[REAL_PRIVATIZER_SYM]] %{{[^[:space:]]+}}#0 -> %[[REAL_ARG:[^,]+]], @@ -162,7 +179,6 @@ end subroutine target_allocatable ! CHECK-SAME: @[[CHAR_PRIVATIZER_SYM]] %{{[^[:space:]]+}}#0 -> %[[CHAR_ARG:[^,]+]] : ! CHECK-SAME: !fir.ref>>, !fir.ref, !fir.ref, !fir.box>, !fir.ref>, !fir.boxchar<1>) { ! CHECK-NOT: fir.alloca -! CHECK: hlfir.declare %[[MAPPED_ARG]] ! CHECK: hlfir.declare %[[ALLOC_ARG]] ! CHECK: hlfir.declare %[[REAL_ARG]] ! CHECK: hlfir.declare %[[LB_ARG]] diff --git a/flang/test/Lower/OpenMP/Todo/atomic-character.f90 b/flang/test/Lower/OpenMP/Todo/atomic-character.f90 deleted file mode 100644 index 88effa4a2a515..0000000000000 --- a/flang/test/Lower/OpenMP/Todo/atomic-character.f90 +++ /dev/null @@ -1,8 +0,0 @@ -! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s - -! CHECK: not yet implemented: Unsupported atomic type -subroutine character_atomic - character :: l, r - !$omp atomic read - l = r -end subroutine diff --git a/flang/test/Parser/OpenMP/map-modifiers.f90 b/flang/test/Parser/OpenMP/map-modifiers.f90 index 4c6dcde5a20c5..895e29f9101a5 100644 --- a/flang/test/Parser/OpenMP/map-modifiers.f90 +++ b/flang/test/Parser/OpenMP/map-modifiers.f90 @@ -18,7 +18,7 @@ subroutine f00(x) !PARSE-TREE: OmpBeginBlockDirective !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause -!PARSE-TREE: | | TypeModifier = OmpxHold +!PARSE-TREE: | | TypeModifier = Ompx_Hold !PARSE-TREE: | | TypeModifier = Always !PARSE-TREE: | | TypeModifier = Present !PARSE-TREE: | | TypeModifier = Close @@ -42,7 +42,7 @@ subroutine f01(x) !PARSE-TREE: OmpBeginBlockDirective !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause -!PARSE-TREE: | | TypeModifier = OmpxHold +!PARSE-TREE: | | TypeModifier = Ompx_Hold !PARSE-TREE: | | TypeModifier = Always !PARSE-TREE: | | TypeModifier = Present !PARSE-TREE: | | TypeModifier = Close @@ -104,7 +104,7 @@ subroutine f10(x) !PARSE-TREE: OmpBeginBlockDirective !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause -!PARSE-TREE: | | TypeModifier = OmpxHold +!PARSE-TREE: | | TypeModifier = Ompx_Hold !PARSE-TREE: | | TypeModifier = Always !PARSE-TREE: | | TypeModifier = Present !PARSE-TREE: | | TypeModifier = Close @@ -128,7 +128,7 @@ subroutine f11(x) !PARSE-TREE: OmpBeginBlockDirective !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause -!PARSE-TREE: | | TypeModifier = OmpxHold +!PARSE-TREE: | | TypeModifier = Ompx_Hold !PARSE-TREE: | | TypeModifier = Always !PARSE-TREE: | | TypeModifier = Present !PARSE-TREE: | | TypeModifier = Close diff --git a/flang/test/Semantics/OpenMP/atomic02.f90 b/flang/test/Semantics/OpenMP/atomic02.f90 index b823bc4c33b23..c66085d00f157 100644 --- a/flang/test/Semantics/OpenMP/atomic02.f90 +++ b/flang/test/Semantics/OpenMP/atomic02.f90 @@ -30,9 +30,11 @@ program OmpAtomic !$omp atomic !ERROR: Invalid or missing operator in atomic update statement a = a**4 - !$omp atomic + !$omp atomic + !ERROR: Expected scalar variable on the LHS of atomic update assignment statement !ERROR: Invalid or missing operator in atomic update statement - c = c//d + !ERROR: Expected scalar expression on the RHS of atomic update assignment statement + c = d !$omp atomic !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` !ERROR: Invalid or missing operator in atomic update statement @@ -77,7 +79,9 @@ program OmpAtomic !ERROR: Invalid or missing operator in atomic update statement a = a**4 !$omp atomic update + !ERROR: Expected scalar variable on the LHS of atomic update assignment statement !ERROR: Invalid or missing operator in atomic update statement + !ERROR: Expected scalar expression on the RHS of atomic update assignment statement c = c//d !$omp atomic update !ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l` diff --git a/flang/test/Semantics/OpenMP/atomic06-empty.f90 b/flang/test/Semantics/OpenMP/atomic06-empty.f90 new file mode 100644 index 0000000000000..226e8d1bb91a5 --- /dev/null +++ b/flang/test/Semantics/OpenMP/atomic06-empty.f90 @@ -0,0 +1,6 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! Test the source code starting with omp syntax + +!$omp atomic write +i = 123 +end diff --git a/flang/test/Semantics/OpenMP/declare-simd-empty.f90 b/flang/test/Semantics/OpenMP/declare-simd-empty.f90 new file mode 100644 index 0000000000000..b61fb53730a23 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-simd-empty.f90 @@ -0,0 +1,6 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! Test the source code starting with omp syntax + +!$omp declare simd +integer :: x +end diff --git a/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 b/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 index 9701c1db92c1c..505cbc48fef90 100644 --- a/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 +++ b/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 @@ -14,6 +14,7 @@ program sample integer :: m endtype type(sample_type) :: z + character :: l, r !$omp atomic read v = x @@ -148,4 +149,14 @@ program sample y(1) = y(1) + 1 x = y(2) !$omp end atomic + + !$omp atomic read + !ERROR: Expected scalar variable on the LHS of atomic assignment statement + !ERROR: Expected scalar expression on the RHS of atomic assignment statement + l = r + + !$omp atomic write + !ERROR: Expected scalar variable on the LHS of atomic assignment statement + !ERROR: Expected scalar expression on the RHS of atomic assignment statement + l = r end program diff --git a/flang/test/Semantics/OpenMP/threadprivate08-empty.f90 b/flang/test/Semantics/OpenMP/threadprivate08-empty.f90 new file mode 100644 index 0000000000000..38a855dceb836 --- /dev/null +++ b/flang/test/Semantics/OpenMP/threadprivate08-empty.f90 @@ -0,0 +1,5 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! Test the source code starting with omp syntax + +!$omp threadprivate(a) +end diff --git a/flang/test/Transforms/debug-extra-global.fir b/flang/test/Transforms/debug-extra-global.fir new file mode 100644 index 0000000000000..d3bc22ad0c59b --- /dev/null +++ b/flang/test/Transforms/debug-extra-global.fir @@ -0,0 +1,18 @@ +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s + +module attributes {dlti.dl_spec = #dlti.dl_spec<>} { + fir.global linkonce_odr @_QFEXnXxcx constant target : !fir.char<1,3> { + %0 = fir.string_lit "xcx"(3) : !fir.char<1,3> + fir.has_value %0 : !fir.char<1,3> + } loc(#loc1) + fir.global linkonce_odr @_QFEXnXxdtx constant target : !fir.char<1,4> { + %0 = fir.string_lit "xdtx"(4) : !fir.char<1,4> + fir.has_value %0 : !fir.char<1,4> + } loc(#loc1) +} +#loc1 = loc("derived.f90":24:1) + +// Test that no di_global_variable gets created for these compile generated +// globals. + +// CHECK-NOT: #di_global_variable diff --git a/flang/test/Transforms/omp-maps-for-privatized-symbols.fir b/flang/test/Transforms/omp-maps-for-privatized-symbols.fir new file mode 100644 index 0000000000000..d32444aaabf23 --- /dev/null +++ b/flang/test/Transforms/omp-maps-for-privatized-symbols.fir @@ -0,0 +1,48 @@ +// RUN: fir-opt --split-input-file --omp-maps-for-privatized-symbols %s | FileCheck %s +module attributes {omp.is_target_device = false} { + omp.private {type = private} @_QFtarget_simpleEsimple_var_private_ref_box_heap_i32 : !fir.ref>> alloc { + ^bb0(%arg0: !fir.ref>>): + %0 = fir.alloca !fir.box> {bindc_name = "simple_var", pinned, uniq_name = "_QFtarget_simpleEsimple_var"} + %1 = fir.load %arg0 : !fir.ref>> + %5:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtarget_simpleEsimple_var"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) + omp.yield(%5#0 : !fir.ref>>) + } + func.func @_QPtarget_simple() { + %0 = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFtarget_simpleEa"} + %1:2 = hlfir.declare %0 {uniq_name = "_QFtarget_simpleEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %2 = fir.alloca !fir.box> {bindc_name = "simple_var", uniq_name = "_QFtarget_simpleEsimple_var"} + %3 = fir.zero_bits !fir.heap + %4 = fir.embox %3 : (!fir.heap) -> !fir.box> + fir.store %4 to %2 : !fir.ref>> + %5:2 = hlfir.declare %2 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtarget_simpleEsimple_var"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) + %c2_i32 = arith.constant 2 : i32 + hlfir.assign %c2_i32 to %1#0 : i32, !fir.ref + %6 = omp.map.info var_ptr(%1#1 : !fir.ref, i32) map_clauses(to) capture(ByRef) -> !fir.ref {name = "a"} + omp.target map_entries(%6 -> %arg0 : !fir.ref) private(@_QFtarget_simpleEsimple_var_private_ref_box_heap_i32 %5#0 -> %arg1 : !fir.ref>>) { + %11:2 = hlfir.declare %arg0 {uniq_name = "_QFtarget_simpleEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %12:2 = hlfir.declare %arg1 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtarget_simpleEsimple_var"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) + %c10_i32 = arith.constant 10 : i32 + %13 = fir.load %11#0 : !fir.ref + %14 = arith.addi %c10_i32, %13 : i32 + hlfir.assign %14 to %12#0 realloc : i32, !fir.ref>> + omp.terminator + } + %7 = fir.load %5#1 : !fir.ref>> + %8 = fir.box_addr %7 : (!fir.box>) -> !fir.heap + %9 = fir.convert %8 : (!fir.heap) -> i64 + %c0_i64 = arith.constant 0 : i64 + %10 = arith.cmpi ne, %9, %c0_i64 : i64 + fir.if %10 { + %11 = fir.load %5#1 : !fir.ref>> + %12 = fir.box_addr %11 : (!fir.box>) -> !fir.heap + fir.freemem %12 : !fir.heap + %13 = fir.zero_bits !fir.heap + %14 = fir.embox %13 : (!fir.heap) -> !fir.box> + fir.store %14 to %5#1 : !fir.ref>> + } + return + } +} +// CHECK: %[[MAP0:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref, i32) map_clauses(to) capture(ByRef) -> !fir.ref {name = "a"} +// CHECK: %[[MAP1:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(to) capture(ByRef) -> !fir.ref>> +// CHECK: omp.target map_entries(%[[MAP0]] -> %arg0, %[[MAP1]] -> %arg1 : !fir.ref, !fir.ref>>) diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt index d89093b2117c2..38e9f2e685cae 100644 --- a/libc/config/gpu/entrypoints.txt +++ b/libc/config/gpu/entrypoints.txt @@ -567,7 +567,10 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.llogbf16 libc.src.math.llrintf16 libc.src.math.llroundf16 + libc.src.math.log10f16 + libc.src.math.log2f16 libc.src.math.logbf16 + libc.src.math.logf16 libc.src.math.lrintf16 libc.src.math.lroundf16 libc.src.math.modff16 @@ -587,6 +590,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.setpayloadf16 libc.src.math.setpayloadsigf16 libc.src.math.sinhf16 + libc.src.math.sqrtf16 libc.src.math.tanhf16 libc.src.math.totalorderf16 libc.src.math.totalordermagf16 diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 885827d304efe..71c6e874429fe 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -680,6 +680,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.setpayloadf16 libc.src.math.setpayloadsigf16 libc.src.math.sinpif16 + libc.src.math.sqrtf16 libc.src.math.totalorderf16 libc.src.math.totalordermagf16 libc.src.math.truncf16 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 7314dbc660f3c..9bc63edf06f28 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -660,7 +660,10 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.llogbf16 libc.src.math.llrintf16 libc.src.math.llroundf16 + libc.src.math.log10f16 + libc.src.math.log2f16 libc.src.math.logbf16 + libc.src.math.logf16 libc.src.math.lrintf16 libc.src.math.lroundf16 libc.src.math.modff16 @@ -681,6 +684,7 @@ if(LIBC_TYPES_HAS_FLOAT16) libc.src.math.setpayloadsigf16 libc.src.math.sinhf16 libc.src.math.sinpif16 + libc.src.math.sqrtf16 libc.src.math.tanhf16 libc.src.math.totalorderf16 libc.src.math.totalordermagf16 diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 010377a90f6ea..ce4df92393ce7 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -310,15 +310,15 @@ Higher Math Functions +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | lgamma | | | | | | 7.12.8.3 | F.10.5.3 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| log | |check| | |check| | | | | 7.12.6.11 | F.10.3.11 | +| log | |check| | |check| | | |check| | | 7.12.6.11 | F.10.3.11 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| log10 | |check| | |check| | | | | 7.12.6.12 | F.10.3.12 | +| log10 | |check| | |check| | | |check| | | 7.12.6.12 | F.10.3.12 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | log10p1 | | | | | | 7.12.6.13 | F.10.3.13 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | log1p | |check| | |check| | | | | 7.12.6.14 | F.10.3.14 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| log2 | |check| | |check| | | | | 7.12.6.15 | F.10.3.15 | +| log2 | |check| | |check| | | |check| | | 7.12.6.15 | F.10.3.15 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | log2p1 | | | | | | 7.12.6.16 | F.10.3.16 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ @@ -344,7 +344,7 @@ Higher Math Functions +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | sinpi | |check| | | | |check| | | 7.12.4.13 | F.10.1.13 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ -| sqrt | |check| | |check| | |check| | | |check| | 7.12.7.10 | F.10.4.10 | +| sqrt | |check| | |check| | |check| | |check| | |check| | 7.12.7.10 | F.10.4.10 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ | tan | |check| | |check| | | | | 7.12.4.7 | F.10.1.7 | +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+ diff --git a/libc/hdr/stdio_overlay.h b/libc/hdr/stdio_overlay.h index cec55abfde7bf..aef8c448fe49d 100644 --- a/libc/hdr/stdio_overlay.h +++ b/libc/hdr/stdio_overlay.h @@ -27,6 +27,17 @@ #undef _FORTIFY_SOURCE #endif +#ifdef __USE_EXTERN_INLINES +#define LIBC_OLD_USE_EXTERN_INLINES +#undef __USE_EXTERN_INLINES +#endif + +#ifdef __USE_FORTIFY_LEVEL +#define LIBC_OLD_USE_FORTIFY_LEVEL __USE_FORTIFY_LEVEL +#undef __USE_FORTIFY_LEVEL +#define __USE_FORTIFY_LEVEL 0 +#endif + #ifndef __NO_INLINE__ #define __NO_INLINE__ 1 #define LIBC_SET_NO_INLINE @@ -44,4 +55,15 @@ #undef LIBC_SET_NO_INLINE #endif +#ifdef LIBC_OLD_USE_FORTIFY_LEVEL +#undef __USE_FORTIFY_LEVEL +#define __USE_FORTIFY_LEVEL LIBC_OLD_USE_FORTIFY_LEVEL +#undef LIBC_OLD_USE_FORTIFY_LEVEL +#endif + +#ifdef LIBC_OLD_USE_EXTERN_INLINES +#define __USE_EXTERN_INLINES +#undef LIBC_OLD_USE_EXTERN_INLINES +#endif + #endif // LLVM_LIBC_HDR_STDIO_OVERLAY_H diff --git a/libc/hdr/wchar_overlay.h b/libc/hdr/wchar_overlay.h index a1de9d5085d47..99a70899779e7 100644 --- a/libc/hdr/wchar_overlay.h +++ b/libc/hdr/wchar_overlay.h @@ -32,6 +32,17 @@ #define LIBC_SET_NO_INLINE #endif +#ifdef __USE_EXTERN_INLINES +#define LIBC_OLD_USE_EXTERN_INLINES +#undef __USE_EXTERN_INLINES +#endif + +#ifdef __USE_FORTIFY_LEVEL +#define LIBC_OLD_USE_FORTIFY_LEVEL __USE_FORTIFY_LEVEL +#undef __USE_FORTIFY_LEVEL +#define __USE_FORTIFY_LEVEL 0 +#endif + #include #ifdef LIBC_OLD_FORTIFY_SOURCE @@ -44,4 +55,15 @@ #undef LIBC_SET_NO_INLINE #endif +#ifdef LIBC_OLD_USE_FORTIFY_LEVEL +#undef __USE_FORTIFY_LEVEL +#define __USE_FORTIFY_LEVEL LIBC_OLD_USE_FORTIFY_LEVEL +#undef LIBC_OLD_USE_FORTIFY_LEVEL +#endif + +#ifdef LIBC_OLD_USE_EXTERN_INLINES +#define __USE_EXTERN_INLINES +#undef LIBC_OLD_USE_EXTERN_INLINES +#endif + #endif // LLVM_LIBC_HDR_WCHAR_OVERLAY_H diff --git a/libc/newhdrgen/yaml/math.yaml b/libc/newhdrgen/yaml/math.yaml index 98ea1a0d25fbb..fe07803cff06f 100644 --- a/libc/newhdrgen/yaml/math.yaml +++ b/libc/newhdrgen/yaml/math.yaml @@ -206,6 +206,13 @@ functions: return_type: float arguments: - type: float + - name: coshf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: ddivl standards: - stdc @@ -266,6 +273,13 @@ functions: return_type: float arguments: - type: float + - name: exp10m1f16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: exp2 standards: - stdc @@ -1557,6 +1571,13 @@ functions: return_type: float arguments: - type: float + - name: log10f16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: log1p standards: - stdc @@ -1581,6 +1602,13 @@ functions: return_type: float arguments: - type: float + - name: log2f16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: logb standards: - stdc @@ -1619,6 +1647,13 @@ functions: return_type: float arguments: - type: float + - name: logf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: lrint standards: - stdc @@ -2297,6 +2332,13 @@ functions: return_type: float arguments: - type: float + - name: sinhf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: sinpif16 standards: - stdc @@ -2323,6 +2365,13 @@ functions: arguments: - type: float128 guard: LIBC_TYPES_HAS_FLOAT128 + - name: sqrtf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: sqrtl standards: - stdc @@ -2347,6 +2396,13 @@ functions: return_type: float arguments: - type: float + - name: tanhf16 + standards: + - stdc + return_type: _Float16 + arguments: + - type: _Float16 + guard: LIBC_TYPES_HAS_FLOAT16 - name: totalorder standards: - stdc diff --git a/libc/shared/fp_bits.h b/libc/shared/fp_bits.h new file mode 100644 index 0000000000000..2898c508b7772 --- /dev/null +++ b/libc/shared/fp_bits.h @@ -0,0 +1,22 @@ +//===-- Floating point number utils -----------------------------*- 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_LIBC_SHARED_FP_BITS_H +#define LLVM_LIBC_SHARED_FP_BITS_H + +#include "src/__support/FPUtil/FPBits.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using fputil::FPBits; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_FP_BITS_H diff --git a/libc/shared/str_to_float.h b/libc/shared/str_to_float.h new file mode 100644 index 0000000000000..b133a28e26efc --- /dev/null +++ b/libc/shared/str_to_float.h @@ -0,0 +1,27 @@ +//===-- String to float conversion utils ------------------------*- 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_LIBC_SHARED_STR_TO_FLOAT_H +#define LLVM_LIBC_SHARED_STR_TO_FLOAT_H + +#include "src/__support/str_to_float.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using internal::ExpandedFloat; +using internal::FloatConvertReturn; +using internal::RoundDirection; + +using internal::binary_exp_to_float; +using internal::decimal_exp_to_float; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_STR_TO_FLOAT_H diff --git a/libc/shared/str_to_integer.h b/libc/shared/str_to_integer.h new file mode 100644 index 0000000000000..15bee698d5a6b --- /dev/null +++ b/libc/shared/str_to_integer.h @@ -0,0 +1,24 @@ +//===-- String to int conversion utils --------------------------*- 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_LIBC_SHARED_STR_TO_INTEGER_H +#define LLVM_LIBC_SHARED_STR_TO_INTEGER_H + +#include "src/__support/str_to_integer.h" + +namespace LIBC_NAMESPACE_DECL { +namespace shared { + +using LIBC_NAMESPACE::StrToNumResult; + +using internal::strtointeger; + +} // namespace shared +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SHARED_STR_TO_INTEGER_H diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 196dab9f81b38..d1ebc6ffb5821 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -642,15 +642,18 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"log10", RetValSpec, [ArgSpec]>, FunctionSpec<"log10f", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"log10f16", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT16">, FunctionSpec<"log1p", RetValSpec, [ArgSpec]>, FunctionSpec<"log1pf", RetValSpec, [ArgSpec]>, FunctionSpec<"log2", RetValSpec, [ArgSpec]>, FunctionSpec<"log2f", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"log2f16", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT16">, FunctionSpec<"log", RetValSpec, [ArgSpec]>, FunctionSpec<"logf", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"logf16", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT16">, FunctionSpec<"logb", RetValSpec, [ArgSpec]>, FunctionSpec<"logbf", RetValSpec, [ArgSpec]>, @@ -751,6 +754,7 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"sqrt", RetValSpec, [ArgSpec]>, FunctionSpec<"sqrtf", RetValSpec, [ArgSpec]>, FunctionSpec<"sqrtl", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"sqrtf16", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT16">, GuardedFunctionSpec<"sqrtf128", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"trunc", RetValSpec, [ArgSpec]>, diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 5d1f633bb56ee..6da89091a8ced 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -6,6 +6,12 @@ // //===----------------------------------------------------------------------===// +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This file is shared with libc++. You should also be careful when adding +// dependencies to this file, since it needs to build for all libc++ targets. +// ----------------------------------------------------------------------------- + #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H @@ -795,6 +801,12 @@ template LIBC_INLINE static constexpr FPType get_fp_type() { static_assert(cpp::always_false, "Unsupported type"); } +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This interface is shared with libc++, if you change this interface you need +// to update it in both libc and libc++. You should also be careful when adding +// dependencies to this file, since it needs to build for all libc++ targets. +// ----------------------------------------------------------------------------- // A generic class to manipulate C++ floating point formats. // It derives its functionality to FPRepImpl above. template diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h index 01af4bb7c9009..497ebd145c6b4 100644 --- a/libc/src/__support/FPUtil/generic/sqrt.h +++ b/libc/src/__support/FPUtil/generic/sqrt.h @@ -139,7 +139,8 @@ sqrt(InType x) { for (InStorageType current_bit = ONE >> 1; current_bit; current_bit >>= 1) { r <<= 1; - InStorageType tmp = (y << 1) + current_bit; // 2*y(n - 1) + 2^(-n-1) + // 2*y(n - 1) + 2^(-n-1) + InStorageType tmp = static_cast((y << 1) + current_bit); if (r >= tmp) { r -= tmp; y += current_bit; diff --git a/libc/src/__support/high_precision_decimal.h b/libc/src/__support/high_precision_decimal.h index 3e397574d4cbb..ac11649d1d168 100644 --- a/libc/src/__support/high_precision_decimal.h +++ b/libc/src/__support/high_precision_decimal.h @@ -6,6 +6,12 @@ // //===----------------------------------------------------------------------===// +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This file is shared with libc++. You should also be careful when adding +// dependencies to this file, since it needs to build for all libc++ targets. +// ----------------------------------------------------------------------------- + #ifndef LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H #define LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H @@ -23,6 +29,11 @@ struct LShiftTableEntry { char const *power_of_five; }; +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This interface is shared with libc++, if you change this interface you need +// to update it in both libc and libc++. +// ----------------------------------------------------------------------------- // This is used in both this file and in the main str_to_float.h. // TODO: Figure out where to put this. enum class RoundDirection { Up, Down, Nearest }; diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h index 3ede8a6503d77..30c742c007ca1 100644 --- a/libc/src/__support/macros/properties/types.h +++ b/libc/src/__support/macros/properties/types.h @@ -27,6 +27,8 @@ #define LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 #elif (LDBL_MANT_DIG == 113) #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128 +#elif (LDBL_MANT_DIG == 106) +#define LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE #endif // int64 / uint64 support diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index a452b3a55fdeb..a1f4eef03fc3c 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -6,6 +6,12 @@ // //===----------------------------------------------------------------------===// +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This file is shared with libc++. You should also be careful when adding +// dependencies to this file, since it needs to build for all libc++ targets. +// ----------------------------------------------------------------------------- + #ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H #define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H @@ -32,11 +38,21 @@ namespace LIBC_NAMESPACE_DECL { namespace internal { +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This interface is shared with libc++, if you change this interface you need +// to update it in both libc and libc++. +// ----------------------------------------------------------------------------- template struct ExpandedFloat { typename fputil::FPBits::StorageType mantissa; int32_t exponent; }; +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This interface is shared with libc++, if you change this interface you need +// to update it in both libc and libc++. +// ----------------------------------------------------------------------------- template struct FloatConvertReturn { ExpandedFloat num = {0, 0}; int error = 0; @@ -179,7 +195,10 @@ eisel_lemire(ExpandedFloat init_num, return output; } -#if !defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) +// TODO: Re-enable eisel-lemire for long double is double double once it's +// properly supported. +#if !defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) && \ + !defined(LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE) template <> LIBC_INLINE cpp::optional> eisel_lemire(ExpandedFloat init_num, @@ -300,7 +319,8 @@ eisel_lemire(ExpandedFloat init_num, output.exponent = exp2; return output; } -#endif // !defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) +#endif // !defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) && + // !defined(LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE) // The nth item in POWERS_OF_TWO represents the greatest power of two less than // 10^n. This tells us how much we can safely shift without overshooting. @@ -502,6 +522,18 @@ template <> class ClingerConsts { static constexpr long double MAX_EXACT_INT = 10384593717069655257060992658440191.0L; }; +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE) +// TODO: Add proper double double type support here, currently using constants +// for double since it should be safe. +template <> class ClingerConsts { +public: + static constexpr double POWERS_OF_TEN_ARRAY[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, + 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; + static constexpr int32_t EXACT_POWERS_OF_TEN = 22; + static constexpr int32_t DIGITS_IN_MANTISSA = 15; + static constexpr double MAX_EXACT_INT = 9007199254740991.0; +}; #else #error "Unknown long double type" #endif @@ -637,6 +669,11 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound() { return -(309 + 15 + 20); } +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This interface is shared with libc++, if you change this interface you need +// to update it in both libc and libc++. +// ----------------------------------------------------------------------------- // Takes a mantissa and base 10 exponent and converts it into its closest // floating point type T equivalient. First we try the Eisel-Lemire algorithm, // then if that fails then we fall back to a more accurate algorithm for @@ -716,6 +753,11 @@ LIBC_INLINE FloatConvertReturn decimal_exp_to_float( return output; } +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This interface is shared with libc++, if you change this interface you need +// to update it in both libc and libc++. +// ----------------------------------------------------------------------------- // Takes a mantissa and base 2 exponent and converts it into its closest // floating point type T equivalient. Since the exponent is already in the right // form, this is mostly just shifting and rounding. This is used for hexadecimal diff --git a/libc/src/__support/str_to_integer.h b/libc/src/__support/str_to_integer.h index c8d02434c89ce..86611f9a6902d 100644 --- a/libc/src/__support/str_to_integer.h +++ b/libc/src/__support/str_to_integer.h @@ -6,6 +6,12 @@ // //===----------------------------------------------------------------------===// +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This file is shared with libc++. You should also be careful when adding +// dependencies to this file, since it needs to build for all libc++ targets. +// ----------------------------------------------------------------------------- + #ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H #define LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H @@ -73,6 +79,11 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) { return 10; } +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This interface is shared with libc++, if you change this interface you need +// to update it in both libc and libc++. +// ----------------------------------------------------------------------------- // Takes a pointer to a string and the base to convert to. This function is used // as the backend for all of the string to int functions. template diff --git a/libc/src/__support/str_to_num_result.h b/libc/src/__support/str_to_num_result.h index 6d361357cac2a..48c363c88ff41 100644 --- a/libc/src/__support/str_to_num_result.h +++ b/libc/src/__support/str_to_num_result.h @@ -6,6 +6,12 @@ // //===----------------------------------------------------------------------===// +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This file is shared with libc++. You should also be careful when adding +// dependencies to this file, since it needs to build for all libc++ targets. +// ----------------------------------------------------------------------------- + #ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_NUM_RESULT_H #define LLVM_LIBC_SRC___SUPPORT_STR_TO_NUM_RESULT_H @@ -16,6 +22,11 @@ namespace LIBC_NAMESPACE_DECL { +// ----------------------------------------------------------------------------- +// **** WARNING **** +// This interface is shared with libc++, if you change this interface you need +// to update it in both libc and libc++. +// ----------------------------------------------------------------------------- template struct StrToNumResult { T value; int error; diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index 8427b550ab4c7..cb4817348cbba 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -334,15 +334,18 @@ add_math_entrypoint_object(ldexpf128) add_math_entrypoint_object(log10) add_math_entrypoint_object(log10f) +add_math_entrypoint_object(log10f16) add_math_entrypoint_object(log1p) add_math_entrypoint_object(log1pf) add_math_entrypoint_object(log2) add_math_entrypoint_object(log2f) +add_math_entrypoint_object(log2f16) add_math_entrypoint_object(log) add_math_entrypoint_object(logf) +add_math_entrypoint_object(logf16) add_math_entrypoint_object(logb) add_math_entrypoint_object(logbf) @@ -489,6 +492,7 @@ add_math_entrypoint_object(sinhf16) add_math_entrypoint_object(sqrt) add_math_entrypoint_object(sqrtf) add_math_entrypoint_object(sqrtl) +add_math_entrypoint_object(sqrtf16) add_math_entrypoint_object(sqrtf128) add_math_entrypoint_object(tan) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 81b3e44db7923..35e7347b91362 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -2173,6 +2173,28 @@ add_entrypoint_object( -O3 ) +add_entrypoint_object( + log10f16 + SRCS + log10f16.cpp + HDRS + ../log10f16.h + DEPENDS + .expxf16 + libc.hdr.errno_macros + libc.hdr.fenv_macros + libc.src.__support.FPUtil.cast + libc.src.__support.FPUtil.except_value_utils + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.macros.optimization + libc.src.__support.macros.properties.cpu_features + COMPILE_OPTIONS + -O3 +) + add_entrypoint_object( log1p SRCS @@ -2250,6 +2272,28 @@ add_entrypoint_object( -O3 ) +add_entrypoint_object( + log2f16 + SRCS + log2f16.cpp + HDRS + ../log2f16.h + DEPENDS + .expxf16 + libc.hdr.errno_macros + libc.hdr.fenv_macros + libc.src.__support.FPUtil.cast + libc.src.__support.FPUtil.except_value_utils + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.macros.optimization + libc.src.__support.macros.properties.cpu_features + COMPILE_OPTIONS + -O3 +) + add_entrypoint_object( log SRCS @@ -2289,6 +2333,28 @@ add_entrypoint_object( -O3 ) +add_entrypoint_object( + logf16 + SRCS + logf16.cpp + HDRS + ../logf16.h + DEPENDS + .expxf16 + libc.hdr.errno_macros + libc.hdr.fenv_macros + libc.src.__support.FPUtil.cast + libc.src.__support.FPUtil.except_value_utils + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.multiply_add + libc.src.__support.FPUtil.polyeval + libc.src.__support.macros.optimization + libc.src.__support.macros.properties.cpu_features + COMPILE_OPTIONS + -O3 +) + add_entrypoint_object( logb SRCS @@ -3183,6 +3249,18 @@ add_entrypoint_object( -O3 ) +add_entrypoint_object( + sqrtf16 + SRCS + sqrtf16.cpp + HDRS + ../sqrtf16.h + DEPENDS + libc.src.__support.FPUtil.sqrt + COMPILE_OPTIONS + -O3 +) + add_entrypoint_object( sqrtf128 SRCS diff --git a/libc/src/math/generic/atan2f.cpp b/libc/src/math/generic/atan2f.cpp index e4b297c00f012..a2e5499809a34 100644 --- a/libc/src/math/generic/atan2f.cpp +++ b/libc/src/math/generic/atan2f.cpp @@ -246,12 +246,18 @@ LLVM_LIBC_FUNCTION(float, atan2f, (float y, float x)) { uint32_t y_abs = y_bits.uintval(); uint32_t max_abs = x_abs > y_abs ? x_abs : y_abs; uint32_t min_abs = x_abs <= y_abs ? x_abs : y_abs; + float num_f = FPBits(min_abs).get_val(); + float den_f = FPBits(max_abs).get_val(); + double num_d = static_cast(num_f); + double den_d = static_cast(den_f); - if (LIBC_UNLIKELY(max_abs >= 0x7f80'0000U || min_abs == 0U)) { + if (LIBC_UNLIKELY(max_abs >= 0x7f80'0000U || num_d == 0.0)) { if (x_bits.is_nan() || y_bits.is_nan()) return FPBits::quiet_nan().get_val(); - size_t x_except = x_abs == 0 ? 0 : (x_abs == 0x7f80'0000 ? 2 : 1); - size_t y_except = y_abs == 0 ? 0 : (y_abs == 0x7f80'0000 ? 2 : 1); + double x_d = static_cast(x); + double y_d = static_cast(y); + size_t x_except = (x_d == 0.0) ? 0 : (x_abs == 0x7f80'0000 ? 2 : 1); + size_t y_except = (y_d == 0.0) ? 0 : (y_abs == 0x7f80'0000 ? 2 : 1); // Exceptional cases: // EXCEPT[y_except][x_except][x_is_neg] @@ -275,8 +281,6 @@ LLVM_LIBC_FUNCTION(float, atan2f, (float y, float x)) { bool recip = x_abs < y_abs; double final_sign = IS_NEG[(x_sign != y_sign) != recip]; fputil::DoubleDouble const_term = CONST_ADJ[x_sign][y_sign][recip]; - double num_d = static_cast(FPBits(min_abs).get_val()); - double den_d = static_cast(FPBits(max_abs).get_val()); double q_d = num_d / den_d; double k_d = fputil::nearest_integer(q_d * 0x1.0p4f); diff --git a/libc/src/math/generic/expxf16.h b/libc/src/math/generic/expxf16.h index 7202b1b113190..67bb248307519 100644 --- a/libc/src/math/generic/expxf16.h +++ b/libc/src/math/generic/expxf16.h @@ -288,6 +288,62 @@ template LIBC_INLINE float16 eval_sinh_or_cosh(float16 x) { lo, half_p_odd * exp2_hi_mid_diff, half_p_even * exp2_hi_mid_sum)); } +// Generated by Sollya with the following commands: +// > display = hexadecimal; +// > for i from 0 to 31 do print(round(log(1 + i * 2^-5), SG, RN)); +constexpr cpp::array LOGF_F = { + 0x0p+0f, 0x1.f829bp-6f, 0x1.f0a30cp-5f, 0x1.6f0d28p-4f, + 0x1.e27076p-4f, 0x1.29553p-3f, 0x1.5ff308p-3f, 0x1.9525aap-3f, + 0x1.c8ff7cp-3f, 0x1.fb9186p-3f, 0x1.1675cap-2f, 0x1.2e8e2cp-2f, + 0x1.4618bcp-2f, 0x1.5d1bdcp-2f, 0x1.739d8p-2f, 0x1.89a338p-2f, + 0x1.9f323ep-2f, 0x1.b44f78p-2f, 0x1.c8ff7cp-2f, 0x1.dd46ap-2f, + 0x1.f128f6p-2f, 0x1.02552ap-1f, 0x1.0be72ep-1f, 0x1.154c3ep-1f, + 0x1.1e85f6p-1f, 0x1.2795e2p-1f, 0x1.307d74p-1f, 0x1.393e0ep-1f, + 0x1.41d8fep-1f, 0x1.4a4f86p-1f, 0x1.52a2d2p-1f, 0x1.5ad404p-1f, +}; + +// Generated by Sollya with the following commands: +// > display = hexadecimal; +// > for i from 0 to 31 do print(round(log2(1 + i * 2^-5), SG, RN)); +constexpr cpp::array LOG2F_F = { + 0x0p+0f, 0x1.6bad38p-5f, 0x1.663f7p-4f, 0x1.08c588p-3f, + 0x1.5c01a4p-3f, 0x1.acf5e2p-3f, 0x1.fbc16cp-3f, 0x1.24407ap-2f, + 0x1.49a784p-2f, 0x1.6e221cp-2f, 0x1.91bba8p-2f, 0x1.b47ecp-2f, + 0x1.d6753ep-2f, 0x1.f7a856p-2f, 0x1.0c105p-1f, 0x1.1bf312p-1f, + 0x1.2b8034p-1f, 0x1.3abb4p-1f, 0x1.49a784p-1f, 0x1.584822p-1f, + 0x1.66a008p-1f, 0x1.74b1fep-1f, 0x1.82809ep-1f, 0x1.900e62p-1f, + 0x1.9d5dap-1f, 0x1.aa709p-1f, 0x1.b74948p-1f, 0x1.c3e9cap-1f, + 0x1.d053f6p-1f, 0x1.dc899ap-1f, 0x1.e88c6cp-1f, 0x1.f45e08p-1f, +}; + +// Generated by Sollya with the following commands: +// > display = hexadecimal; +// > for i from 0 to 31 do print(round(log10(1 + i * 2^-5), SG, RN)); +constexpr cpp::array LOG10F_F = { + 0x0p+0f, 0x1.b5e908p-7f, 0x1.af5f92p-6f, 0x1.3ed11ap-5f, + 0x1.a30a9ep-5f, 0x1.02428cp-4f, 0x1.31b306p-4f, 0x1.5fe804p-4f, + 0x1.8cf184p-4f, 0x1.b8de4ep-4f, 0x1.e3bc1ap-4f, 0x1.06cbd6p-3f, + 0x1.1b3e72p-3f, 0x1.2f3b6ap-3f, 0x1.42c7e8p-3f, 0x1.55e8c6p-3f, + 0x1.68a288p-3f, 0x1.7af974p-3f, 0x1.8cf184p-3f, 0x1.9e8e7cp-3f, + 0x1.afd3e4p-3f, 0x1.c0c514p-3f, 0x1.d1653p-3f, 0x1.e1b734p-3f, + 0x1.f1bdeep-3f, 0x1.00be06p-2f, 0x1.087a08p-2f, 0x1.101432p-2f, + 0x1.178da6p-2f, 0x1.1ee778p-2f, 0x1.2622bp-2f, 0x1.2d404cp-2f, +}; + +// Generated by Sollya with the following commands: +// > display = hexadecimal; +// > for i from 0 to 31 do print(round(1 / (1 + i * 2^-5), SG, RN)); +constexpr cpp::array ONE_OVER_F_F = { + 0x1p+0f, 0x1.f07c2p-1f, 0x1.e1e1e2p-1f, 0x1.d41d42p-1f, + 0x1.c71c72p-1f, 0x1.bacf92p-1f, 0x1.af286cp-1f, 0x1.a41a42p-1f, + 0x1.99999ap-1f, 0x1.8f9c18p-1f, 0x1.861862p-1f, 0x1.7d05f4p-1f, + 0x1.745d18p-1f, 0x1.6c16c2p-1f, 0x1.642c86p-1f, 0x1.5c9882p-1f, + 0x1.555556p-1f, 0x1.4e5e0ap-1f, 0x1.47ae14p-1f, 0x1.414142p-1f, + 0x1.3b13b2p-1f, 0x1.3521dp-1f, 0x1.2f684cp-1f, 0x1.29e412p-1f, + 0x1.24924ap-1f, 0x1.1f7048p-1f, 0x1.1a7b96p-1f, 0x1.15b1e6p-1f, + 0x1.111112p-1f, 0x1.0c9714p-1f, 0x1.08421p-1f, 0x1.041042p-1f, +}; + } // namespace LIBC_NAMESPACE_DECL #endif // LLVM_LIBC_SRC_MATH_GENERIC_EXPXF16_H diff --git a/libc/src/math/generic/log10f16.cpp b/libc/src/math/generic/log10f16.cpp new file mode 100644 index 0000000000000..990bcabaf6871 --- /dev/null +++ b/libc/src/math/generic/log10f16.cpp @@ -0,0 +1,164 @@ +//===-- Half-precision log10(x) function ----------------------------------===// +// +// 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 "src/math/log10f16.h" +#include "expxf16.h" +#include "hdr/errno_macros.h" +#include "hdr/fenv_macros.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" +#include "src/__support/macros/properties/cpu_features.h" + +namespace LIBC_NAMESPACE_DECL { + +#ifdef LIBC_TARGET_CPU_HAS_FMA +static constexpr size_t N_LOG10F16_EXCEPTS = 11; +#else +static constexpr size_t N_LOG10F16_EXCEPTS = 17; +#endif + +static constexpr fputil::ExceptValues + LOG10F16_EXCEPTS = {{ + // (input, RZ output, RU offset, RD offset, RN offset) + // x = 0x1.e3cp-3, log10f16(x) = -0x1.40cp-1 (RZ) + {0x338fU, 0xb903U, 0U, 1U, 0U}, + // x = 0x1.fep-3, log10f16(x) = -0x1.35p-1 (RZ) + {0x33f8U, 0xb8d4U, 0U, 1U, 1U}, +#ifndef LIBC_TARGET_CPU_HAS_FMA + // x = 0x1.394p-1, log10f16(x) = -0x1.b4cp-3 (RZ) + {0x38e5U, 0xb2d3U, 0U, 1U, 1U}, +#endif + // x = 0x1.ea8p-1, log10f16(x) = -0x1.31p-6 (RZ) + {0x3baaU, 0xa4c4U, 0U, 1U, 1U}, + // x = 0x1.ebp-1, log10f16(x) = -0x1.29cp-6 (RZ) + {0x3bacU, 0xa4a7U, 0U, 1U, 1U}, + // x = 0x1.f3p-1, log10f16(x) = -0x1.6dcp-7 (RZ) + {0x3bccU, 0xa1b7U, 0U, 1U, 1U}, +// x = 0x1.f38p-1, log10f16(x) = -0x1.5f8p-7 (RZ) +#ifndef LIBC_TARGET_CPU_HAS_FMA + {0x3bceU, 0xa17eU, 0U, 1U, 1U}, + // x = 0x1.fd8p-1, log10f16(x) = -0x1.168p-9 (RZ) + {0x3bf6U, 0x985aU, 0U, 1U, 1U}, + // x = 0x1.ff8p-1, log10f16(x) = -0x1.bccp-12 (RZ) + {0x3bfeU, 0x8ef3U, 0U, 1U, 1U}, + // x = 0x1.374p+0, log10f16(x) = 0x1.5b8p-4 (RZ) + {0x3cddU, 0x2d6eU, 1U, 0U, 1U}, + // x = 0x1.3ecp+1, log10f16(x) = 0x1.958p-2 (RZ) + {0x40fbU, 0x3656U, 1U, 0U, 1U}, +#endif + // x = 0x1.4p+3, log10f16(x) = 0x1p+0 (RZ) + {0x4900U, 0x3c00U, 0U, 0U, 0U}, + // x = 0x1.9p+6, log10f16(x) = 0x1p+1 (RZ) + {0x5640U, 0x4000U, 0U, 0U, 0U}, + // x = 0x1.f84p+6, log10f16(x) = 0x1.0ccp+1 (RZ) + {0x57e1U, 0x4033U, 1U, 0U, 0U}, + // x = 0x1.f4p+9, log10f16(x) = 0x1.8p+1 (RZ) + {0x63d0U, 0x4200U, 0U, 0U, 0U}, + // x = 0x1.388p+13, log10f16(x) = 0x1p+2 (RZ) + {0x70e2U, 0x4400U, 0U, 0U, 0U}, + // x = 0x1.674p+13, log10f16(x) = 0x1.03cp+2 (RZ) + {0x719dU, 0x440fU, 1U, 0U, 0U}, + }}; + +LLVM_LIBC_FUNCTION(float16, log10f16, (float16 x)) { + using FPBits = fputil::FPBits; + FPBits x_bits(x); + + uint16_t x_u = x_bits.uintval(); + + // If x <= 0, or x is 1, or x is +inf, or x is NaN. + if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3c00U || x_u >= 0x7c00U)) { + // log10(NaN) = NaN + if (x_bits.is_nan()) { + if (x_bits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + return x; + } + + // log10(+/-0) = −inf + if ((x_u & 0x7fffU) == 0U) { + fputil::raise_except_if_required(FE_DIVBYZERO); + return FPBits::inf(Sign::NEG).get_val(); + } + + if (x_u == 0x3c00U) + return FPBits::zero().get_val(); + + // When x < 0. + if (x_u > 0x8000U) { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + // log10(+inf) = +inf + return FPBits::inf().get_val(); + } + + if (auto r = LOG10F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value())) + return r.value(); + + // To compute log10(x), we perform the following range reduction: + // x = 2^m * 1.mant, + // log10(x) = m * log10(2) + log10(1.mant). + // To compute log10(1.mant), let f be the highest 6 bits including the hidden + // bit, and d be the difference (1.mant - f), i.e., the remaining 5 bits of + // the mantissa, then: + // log10(1.mant) = log10(f) + log10(1.mant / f) + // = log10(f) + log10(1 + d/f) + // since d/f is sufficiently small. + // We store log10(f) and 1/f in the lookup tables LOG10F_F and ONE_OVER_F_F + // respectively. + + int m = -FPBits::EXP_BIAS; + + // When x is subnormal, normalize it. + if ((x_u & FPBits::EXP_MASK) == 0U) { + // Can't pass an integer to fputil::cast directly. + constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN; + x_bits = FPBits(x_bits.get_val() * fputil::cast(NORMALIZE_EXP)); + x_u = x_bits.uintval(); + m -= FPBits::FRACTION_LEN; + } + + uint16_t mant = x_bits.get_mantissa(); + // Leading 10 - 5 = 5 bits of the mantissa. + int f = mant >> 5; + // Unbiased exponent. + m += x_u >> FPBits::FRACTION_LEN; + + // Set bits to 1.mant instead of 2^m * 1.mant. + x_bits.set_biased_exponent(FPBits::EXP_BIAS); + float mant_f = x_bits.get_val(); + // v = 1.mant * 1/f - 1 = d/f + float v = fputil::multiply_add(mant_f, ONE_OVER_F_F[f], -1.0f); + + // Degree-3 minimax polynomial generated by Sollya with the following + // commands: + // > display = hexadecimal; + // > P = fpminimax(log10(1 + x)/x, 2, [|SG...|], [-2^-5, 2^-5]); + // > x * P; + float log10p1_d_over_f = + v * fputil::polyeval(v, 0x1.bcb7bp-2f, -0x1.bce168p-3f, 0x1.28acb8p-3f); + // log10(1.mant) = log10(f) + log10(1 + d/f) + float log10_1_mant = LOG10F_F[f] + log10p1_d_over_f; + return fputil::cast( + fputil::multiply_add(static_cast(m), LOG10F_2, log10_1_mant)); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/log2f16.cpp b/libc/src/math/generic/log2f16.cpp new file mode 100644 index 0000000000000..ff4e0268b53d0 --- /dev/null +++ b/libc/src/math/generic/log2f16.cpp @@ -0,0 +1,149 @@ +//===-- Half-precision log2(x) function -----------------------------------===// +// +// 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 "src/math/log2f16.h" +#include "expxf16.h" +#include "hdr/errno_macros.h" +#include "hdr/fenv_macros.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" +#include "src/__support/macros/properties/cpu_features.h" + +namespace LIBC_NAMESPACE_DECL { + +#ifdef LIBC_TARGET_CPU_HAS_FMA +static constexpr size_t N_LOG2F16_EXCEPTS = 2; +#else +static constexpr size_t N_LOG2F16_EXCEPTS = 9; +#endif + +static constexpr fputil::ExceptValues + LOG2F16_EXCEPTS = {{ +// (input, RZ output, RU offset, RD offset, RN offset) +#ifndef LIBC_TARGET_CPU_HAS_FMA + // x = 0x1.224p-1, log2f16(x) = -0x1.a34p-1 (RZ) + {0x3889U, 0xba8dU, 0U, 1U, 0U}, + // x = 0x1.e34p-1, log2f16(x) = -0x1.558p-4 (RZ) + {0x3b8dU, 0xad56U, 0U, 1U, 0U}, +#endif + // x = 0x1.e8cp-1, log2f16(x) = -0x1.128p-4 (RZ) + {0x3ba3U, 0xac4aU, 0U, 1U, 0U}, +#ifndef LIBC_TARGET_CPU_HAS_FMA + // x = 0x1.f98p-1, log2f16(x) = -0x1.2ep-6 (RZ) + {0x3be6U, 0xa4b8U, 0U, 1U, 0U}, + // x = 0x1.facp-1, log2f16(x) = -0x1.e7p-7 (RZ) + {0x3bebU, 0xa39cU, 0U, 1U, 1U}, +#endif + // x = 0x1.fb4p-1, log2f16(x) = -0x1.b88p-7 (RZ) + {0x3bedU, 0xa2e2U, 0U, 1U, 1U}, +#ifndef LIBC_TARGET_CPU_HAS_FMA + // x = 0x1.fecp-1, log2f16(x) = -0x1.cep-9 (RZ) + {0x3bfbU, 0x9b38U, 0U, 1U, 1U}, + // x = 0x1.ffcp-1, log2f16(x) = -0x1.714p-11 (RZ) + {0x3bffU, 0x91c5U, 0U, 1U, 1U}, + // x = 0x1.224p+0, log2f16(x) = 0x1.72cp-3 (RZ) + {0x3c89U, 0x31cbU, 1U, 0U, 1U}, +#endif + }}; + +LLVM_LIBC_FUNCTION(float16, log2f16, (float16 x)) { + using FPBits = fputil::FPBits; + FPBits x_bits(x); + + uint16_t x_u = x_bits.uintval(); + + // If x <= 0, or x is 1, or x is +inf, or x is NaN. + if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3c00U || x_u >= 0x7c00U)) { + // log2(NaN) = NaN + if (x_bits.is_nan()) { + if (x_bits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + return x; + } + + // log2(+/-0) = −inf + if ((x_u & 0x7fffU) == 0U) { + fputil::raise_except_if_required(FE_DIVBYZERO); + return FPBits::inf(Sign::NEG).get_val(); + } + + if (x_u == 0x3c00U) + return FPBits::zero().get_val(); + + // When x < 0. + if (x_u > 0x8000U) { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + // log2(+inf) = +inf + return FPBits::inf().get_val(); + } + + if (auto r = LOG2F16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value())) + return r.value(); + + // To compute log2(x), we perform the following range reduction: + // x = 2^m * 1.mant, + // log2(x) = m + log2(1.mant). + // To compute log2(1.mant), let f be the highest 6 bits including the hidden + // bit, and d be the difference (1.mant - f), i.e., the remaining 5 bits of + // the mantissa, then: + // log2(1.mant) = log2(f) + log2(1.mant / f) + // = log2(f) + log2(1 + d/f) + // since d/f is sufficiently small. + // We store log2(f) and 1/f in the lookup tables LOG2F_F and ONE_OVER_F_F + // respectively. + + int m = -FPBits::EXP_BIAS; + + // When x is subnormal, normalize it. + if ((x_u & FPBits::EXP_MASK) == 0U) { + // Can't pass an integer to fputil::cast directly. + constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN; + x_bits = FPBits(x_bits.get_val() * fputil::cast(NORMALIZE_EXP)); + x_u = x_bits.uintval(); + m -= FPBits::FRACTION_LEN; + } + + uint16_t mant = x_bits.get_mantissa(); + // Leading 10 - 5 = 5 bits of the mantissa. + int f = mant >> 5; + // Unbiased exponent. + m += x_u >> FPBits::FRACTION_LEN; + + // Set bits to 1.mant instead of 2^m * 1.mant. + x_bits.set_biased_exponent(FPBits::EXP_BIAS); + float mant_f = x_bits.get_val(); + // v = 1.mant * 1/f - 1 = d/f + float v = fputil::multiply_add(mant_f, ONE_OVER_F_F[f], -1.0f); + + // Degree-3 minimax polynomial generated by Sollya with the following + // commands: + // > display = hexadecimal; + // > P = fpminimax(log2(1 + x)/x, 2, [|SG...|], [-2^-5, 2^-5]); + // > x * P; + float log2p1_d_over_f = + v * fputil::polyeval(v, 0x1.715476p+0f, -0x1.71771ap-1f, 0x1.ecb38ep-2f); + // log2(1.mant) = log2(f) + log2(1 + d/f) + float log2_1_mant = LOG2F_F[f] + log2p1_d_over_f; + return fputil::cast(static_cast(m) + log2_1_mant); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/logf16.cpp b/libc/src/math/generic/logf16.cpp new file mode 100644 index 0000000000000..802225a810550 --- /dev/null +++ b/libc/src/math/generic/logf16.cpp @@ -0,0 +1,157 @@ +//===-- Half-precision log(x) function ------------------------------------===// +// +// 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 "src/math/logf16.h" +#include "expxf16.h" +#include "hdr/errno_macros.h" +#include "hdr/fenv_macros.h" +#include "src/__support/FPUtil/FEnvImpl.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/cast.h" +#include "src/__support/FPUtil/except_value_utils.h" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/__support/macros/optimization.h" +#include "src/__support/macros/properties/cpu_features.h" + +namespace LIBC_NAMESPACE_DECL { + +#ifdef LIBC_TARGET_CPU_HAS_FMA +static constexpr size_t N_LOGF16_EXCEPTS = 5; +#else +static constexpr size_t N_LOGF16_EXCEPTS = 11; +#endif + +static constexpr fputil::ExceptValues + LOGF16_EXCEPTS = {{ +// (input, RZ output, RU offset, RD offset, RN offset) +#ifndef LIBC_TARGET_CPU_HAS_FMA + // x = 0x1.61cp-13, logf16(x) = -0x1.16p+3 (RZ) + {0x0987U, 0xc858U, 0U, 1U, 0U}, + // x = 0x1.f2p-12, logf16(x) = -0x1.e98p+2 (RZ) + {0x0fc8U, 0xc7a6U, 0U, 1U, 1U}, +#endif + // x = 0x1.4d4p-9, logf16(x) = -0x1.7e4p+2 (RZ) + {0x1935U, 0xc5f9U, 0U, 1U, 0U}, + // x = 0x1.5ep-8, logf16(x) = -0x1.4ecp+2 (RZ) + {0x1d78U, 0xc53bU, 0U, 1U, 0U}, +#ifndef LIBC_TARGET_CPU_HAS_FMA + // x = 0x1.fdp-1, logf16(x) = -0x1.81p-8 (RZ) + {0x3bf4U, 0x9e04U, 0U, 1U, 1U}, + // x = 0x1.fep-1, logf16(x) = -0x1.008p-8 (RZ) + {0x3bf8U, 0x9c02U, 0U, 1U, 0U}, +#endif + // x = 0x1.ffp-1, logf16(x) = -0x1.004p-9 (RZ) + {0x3bfcU, 0x9801U, 0U, 1U, 0U}, + // x = 0x1.ff8p-1, logf16(x) = -0x1p-10 (RZ) + {0x3bfeU, 0x9400U, 0U, 1U, 1U}, +#ifdef LIBC_TARGET_CPU_HAS_FMA + // x = 0x1.4c4p+1, logf16(x) = 0x1.e84p-1 (RZ) + {0x4131U, 0x3ba1U, 1U, 0U, 1U}, +#else + // x = 0x1.75p+2, logf16(x) = 0x1.c34p+0 (RZ) + {0x45d4U, 0x3f0dU, 1U, 0U, 0U}, + // x = 0x1.75p+2, logf16(x) = 0x1.c34p+0 (RZ) + {0x45d4U, 0x3f0dU, 1U, 0U, 0U}, + // x = 0x1.d5p+9, logf16(x) = 0x1.b5cp+2 (RZ) + {0x6354U, 0x46d7U, 1U, 0U, 1U}, +#endif + }}; + +LLVM_LIBC_FUNCTION(float16, logf16, (float16 x)) { + using FPBits = fputil::FPBits; + FPBits x_bits(x); + + uint16_t x_u = x_bits.uintval(); + + // If x <= 0, or x is 1, or x is +inf, or x is NaN. + if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3c00U || x_u >= 0x7c00U)) { + // log(NaN) = NaN + if (x_bits.is_nan()) { + if (x_bits.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + return x; + } + + // log(+/-0) = −inf + if ((x_u & 0x7fffU) == 0U) { + fputil::raise_except_if_required(FE_DIVBYZERO); + return FPBits::inf(Sign::NEG).get_val(); + } + + if (x_u == 0x3c00U) + return FPBits::zero().get_val(); + + // When x < 0. + if (x_u > 0x8000U) { + fputil::set_errno_if_required(EDOM); + fputil::raise_except_if_required(FE_INVALID); + return FPBits::quiet_nan().get_val(); + } + + // log(+inf) = +inf + return FPBits::inf().get_val(); + } + + if (auto r = LOGF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value())) + return r.value(); + + // To compute log(x), we perform the following range reduction: + // x = 2^m * 1.mant, + // log(x) = m * log(2) + log(1.mant). + // To compute log(1.mant), let f be the highest 6 bits including the hidden + // bit, and d be the difference (1.mant - f), i.e., the remaining 5 bits of + // the mantissa, then: + // log(1.mant) = log(f) + log(1.mant / f) + // = log(f) + log(1 + d/f) + // since d/f is sufficiently small. + // We store log(f) and 1/f in the lookup tables LOGF_F and ONE_OVER_F_F + // respectively. + + int m = -FPBits::EXP_BIAS; + + // When x is subnormal, normalize it. + if ((x_u & FPBits::EXP_MASK) == 0U) { + // Can't pass an integer to fputil::cast directly. + constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN; + x_bits = FPBits(x_bits.get_val() * fputil::cast(NORMALIZE_EXP)); + x_u = x_bits.uintval(); + m -= FPBits::FRACTION_LEN; + } + + uint16_t mant = x_bits.get_mantissa(); + // Leading 10 - 5 = 5 bits of the mantissa. + int f = mant >> 5; + // Unbiased exponent. + m += x_u >> FPBits::FRACTION_LEN; + + // Set bits to 1.mant instead of 2^m * 1.mant. + x_bits.set_biased_exponent(FPBits::EXP_BIAS); + float mant_f = x_bits.get_val(); + // v = 1.mant * 1/f - 1 = d/f + float v = fputil::multiply_add(mant_f, ONE_OVER_F_F[f], -1.0f); + + // Degree-3 minimax polynomial generated by Sollya with the following + // commands: + // > display = hexadecimal; + // > P = fpminimax(log(1 + x)/x, 2, [|SG...|], [-2^-5, 2^-5]); + // > x * P; + float log1p_d_over_f = + v * fputil::polyeval(v, 0x1p+0f, -0x1.001804p-1f, 0x1.557ef6p-2f); + // log(1.mant) = log(f) + log(1 + d/f) + float log_1_mant = LOGF_F[f] + log1p_d_over_f; + return fputil::cast( + fputil::multiply_add(static_cast(m), LOGF_2, log_1_mant)); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp index 8ce2465ba229c..83477c6ef2ace 100644 --- a/libc/src/math/generic/powf.cpp +++ b/libc/src/math/generic/powf.cpp @@ -855,9 +855,9 @@ LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) { : 0.0; exp2_hi_mid_dd.hi = exp2_hi_mid; - return static_cast( - powf_double_double(idx_x, dx, y6, lo6_hi, exp2_hi_mid_dd)) + - 0.0f; + double r_dd = powf_double_double(idx_x, dx, y6, lo6_hi, exp2_hi_mid_dd); + + return static_cast(r_dd); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/generic/sqrtf16.cpp b/libc/src/math/generic/sqrtf16.cpp new file mode 100644 index 0000000000000..0aa4a201b3e68 --- /dev/null +++ b/libc/src/math/generic/sqrtf16.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of sqrtf16 function --------------------------------===// +// +// 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 "src/math/sqrtf16.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(float16, sqrtf16, (float16 x)) { + return fputil::sqrt(x); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/math/log10f16.h b/libc/src/math/log10f16.h new file mode 100644 index 0000000000000..298deb370e0b0 --- /dev/null +++ b/libc/src/math/log10f16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for log10f16 ----------------------*- 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_LIBC_SRC_MATH_LOG10F16_H +#define LLVM_LIBC_SRC_MATH_LOG10F16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +float16 log10f16(float16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_LOG10F16_H diff --git a/libc/src/math/log2f16.h b/libc/src/math/log2f16.h new file mode 100644 index 0000000000000..d89f9f398e2a8 --- /dev/null +++ b/libc/src/math/log2f16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for log2f16 -----------------------*- 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_LIBC_SRC_MATH_LOG2F16_H +#define LLVM_LIBC_SRC_MATH_LOG2F16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +float16 log2f16(float16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_LOG2F16_H diff --git a/libc/src/math/logf16.h b/libc/src/math/logf16.h new file mode 100644 index 0000000000000..e2d296b1d9088 --- /dev/null +++ b/libc/src/math/logf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for logf16 ------------------------*- 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_LIBC_SRC_MATH_LOGF16_H +#define LLVM_LIBC_SRC_MATH_LOGF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +float16 logf16(float16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_LOGF16_H diff --git a/libc/src/math/sqrtf16.h b/libc/src/math/sqrtf16.h new file mode 100644 index 0000000000000..bb09c4fdaf8d0 --- /dev/null +++ b/libc/src/math/sqrtf16.h @@ -0,0 +1,21 @@ +//===-- Implementation header for sqrtf16 -----------------------*- 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_LIBC_SRC_MATH_SQRTF16_H +#define LLVM_LIBC_SRC_MATH_SQRTF16_H + +#include "src/__support/macros/config.h" +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE_DECL { + +float16 sqrtf16(float16 x); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_MATH_SQRTF16_H diff --git a/libc/src/stdio/scanf_core/int_converter.cpp b/libc/src/stdio/scanf_core/int_converter.cpp index 136db2a3773e1..ecdac52e84bbd 100644 --- a/libc/src/stdio/scanf_core/int_converter.cpp +++ b/libc/src/stdio/scanf_core/int_converter.cpp @@ -124,13 +124,24 @@ int convert_int(Reader *reader, const FormatSection &to_conv) { if (to_lower(cur_char) == 'x') { // This is a valid hex prefix. + + is_number = false; + // A valid hex prefix is not necessarily a valid number. For the + // conversion to be valid it needs to use all of the characters it + // consumes. From the standard: + // 7.23.6.2 paragraph 9: "An input item is defined as the longest + // sequence of input characters which does not exceed any specified + // field width and which is, or is a prefix of, a matching input + // sequence." + // 7.23.6.2 paragraph 10: "If the input item is not a matching sequence, + // the execution of the directive fails: this condition is a matching + // failure" base = 16; if (max_width > 1) { --max_width; cur_char = reader->getc(); } else { - write_int_with_length(0, to_conv); - return READ_OK; + return MATCHING_FAILURE; } } else { @@ -198,6 +209,9 @@ int convert_int(Reader *reader, const FormatSection &to_conv) { // last one back. reader->ungetc(cur_char); + if (!is_number) + return MATCHING_FAILURE; + if (has_overflow) { write_int_with_length(MAX, to_conv); } else { @@ -207,8 +221,6 @@ int convert_int(Reader *reader, const FormatSection &to_conv) { write_int_with_length(result, to_conv); } - if (!is_number) - return MATCHING_FAILURE; return READ_OK; } diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt index 787188ab3beb9..b33cbc5358d60 100644 --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -138,6 +138,7 @@ add_entrypoint_object( DEPENDS .strcpy .string_utils + libc.include.llvm-libc-types.size_t ) add_entrypoint_object( @@ -240,6 +241,7 @@ add_entrypoint_object( .string_utils libc.include.stdlib libc.src.errno.errno + libc.include.llvm-libc-types.size_t ) add_entrypoint_object( @@ -270,7 +272,7 @@ add_entrypoint_object( strlcat.h DEPENDS .string_utils - libc.include.string + libc.include.llvm-libc-types.size_t ) add_entrypoint_object( @@ -281,7 +283,7 @@ add_entrypoint_object( strlcpy.h DEPENDS .string_utils - libc.include.string + libc.include.llvm-libc-types.size_t ) add_entrypoint_object( @@ -292,7 +294,7 @@ add_entrypoint_object( strlen.h DEPENDS .string_utils - libc.include.string + libc.include.llvm-libc-types.size_t ) add_entrypoint_object( @@ -304,6 +306,7 @@ add_entrypoint_object( DEPENDS .strncpy .string_utils + libc.include.llvm-libc-types.size_t ) add_entrypoint_object( @@ -346,6 +349,7 @@ add_entrypoint_object( .string_utils libc.include.stdlib libc.src.__support.CPP.new + libc.include.llvm-libc-types.size_t ) add_entrypoint_object( diff --git a/libc/src/string/memory_utils/x86_64/inline_memcpy.h b/libc/src/string/memory_utils/x86_64/inline_memcpy.h index 2b2c6e6fbc546..68f64fb1a5023 100644 --- a/libc/src/string/memory_utils/x86_64/inline_memcpy.h +++ b/libc/src/string/memory_utils/x86_64/inline_memcpy.h @@ -98,8 +98,9 @@ inline_memcpy_x86_sse2_ge64_sw_prefetching(Ptr __restrict dst, while (offset + K_TWO_CACHELINES + 32 <= count) { inline_memcpy_prefetch(dst, src, offset + K_ONE_CACHELINE); inline_memcpy_prefetch(dst, src, offset + K_TWO_CACHELINES); - builtin::Memcpy::block_offset(dst, src, offset); - offset += K_TWO_CACHELINES; + // Copy one cache line at a time to prevent the use of `rep;movsb`. + for (size_t i = 0; i < 2; ++i, offset += K_ONE_CACHELINE) + builtin::Memcpy::block_offset(dst, src, offset); } } else { // Three cache lines at a time. @@ -107,10 +108,9 @@ inline_memcpy_x86_sse2_ge64_sw_prefetching(Ptr __restrict dst, inline_memcpy_prefetch(dst, src, offset + K_ONE_CACHELINE); inline_memcpy_prefetch(dst, src, offset + K_TWO_CACHELINES); inline_memcpy_prefetch(dst, src, offset + K_THREE_CACHELINES); - // It is likely that this copy will be turned into a 'rep;movsb' on - // non-AVX machines. - builtin::Memcpy::block_offset(dst, src, offset); - offset += K_THREE_CACHELINES; + // Copy one cache line at a time to prevent the use of `rep;movsb`. + for (size_t i = 0; i < 3; ++i, offset += K_ONE_CACHELINE) + builtin::Memcpy::block_offset(dst, src, offset); } } // We don't use 'loop_and_tail_offset' because it assumes at least one @@ -148,8 +148,9 @@ inline_memcpy_x86_avx_ge64_sw_prefetching(Ptr __restrict dst, inline_memcpy_prefetch(dst, src, offset + K_ONE_CACHELINE); inline_memcpy_prefetch(dst, src, offset + K_TWO_CACHELINES); inline_memcpy_prefetch(dst, src, offset + K_THREE_CACHELINES); - builtin::Memcpy::block_offset(dst, src, offset); - offset += K_THREE_CACHELINES; + // Copy one cache line at a time to prevent the use of `rep;movsb`. + for (size_t i = 0; i < 3; ++i, offset += K_ONE_CACHELINE) + builtin::Memcpy::block_offset(dst, src, offset); } // We don't use 'loop_and_tail_offset' because it assumes at least one // iteration of the loop. diff --git a/libc/src/string/strcat.h b/libc/src/string/strcat.h index 90a7fd2e41337..82860196ce29a 100644 --- a/libc/src/string/strcat.h +++ b/libc/src/string/strcat.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_STRING_STRCAT_H #define LLVM_LIBC_SRC_STRING_STRCAT_H +#include "include/llvm-libc-types/size_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/string/strcpy.h b/libc/src/string/strcpy.h index d4f3e81fdc733..9e0c3dbc39ef9 100644 --- a/libc/src/string/strcpy.h +++ b/libc/src/string/strcpy.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_STRING_STRCPY_H #define LLVM_LIBC_SRC_STRING_STRCPY_H +#include "include/llvm-libc-types/size_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/string/strdup.h b/libc/src/string/strdup.h index 45303a3efeb49..2744e53d45d47 100644 --- a/libc/src/string/strdup.h +++ b/libc/src/string/strdup.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_STRING_STRDUP_H #define LLVM_LIBC_SRC_STRING_STRDUP_H +#include "include/llvm-libc-types/size_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/string/strlcat.h b/libc/src/string/strlcat.h index ffe97af62a543..9dc8f3a3bc0d1 100644 --- a/libc/src/string/strlcat.h +++ b/libc/src/string/strlcat.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_STRING_STRLCAT_H #define LLVM_LIBC_SRC_STRING_STRLCAT_H +#include "include/llvm-libc-types/size_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/string/strlcpy.h b/libc/src/string/strlcpy.h index 058e7653b1b91..45b2c2a2ec26b 100644 --- a/libc/src/string/strlcpy.h +++ b/libc/src/string/strlcpy.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_STRING_STRLCPY_H #define LLVM_LIBC_SRC_STRING_STRLCPY_H +#include "include/llvm-libc-types/size_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/string/strlen.h b/libc/src/string/strlen.h index f07bf73ace3de..093edcf479bcf 100644 --- a/libc/src/string/strlen.h +++ b/libc/src/string/strlen.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_STRING_STRLEN_H #define LLVM_LIBC_SRC_STRING_STRLEN_H +#include "include/llvm-libc-types/size_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/string/strncat.h b/libc/src/string/strncat.h index 1a130799f3965..f37d9a7bc1544 100644 --- a/libc/src/string/strncat.h +++ b/libc/src/string/strncat.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_STRING_STRNCAT_H #define LLVM_LIBC_SRC_STRING_STRNCAT_H +#include "include/llvm-libc-types/size_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/string/strndup.h b/libc/src/string/strndup.h index 03370cc8d7dce..78cde7b33e13b 100644 --- a/libc/src/string/strndup.h +++ b/libc/src/string/strndup.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_STRING_STRNDUP_H #define LLVM_LIBC_SRC_STRING_STRNDUP_H +#include "include/llvm-libc-types/size_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h index 07e2cd5df18cb..7fcc6a32025b5 100644 --- a/libc/test/UnitTest/FPMatcher.h +++ b/libc/test/UnitTest/FPMatcher.h @@ -16,6 +16,7 @@ #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/fpbits_str.h" #include "src/__support/macros/config.h" +#include "src/__support/macros/properties/architectures.h" #include "test/UnitTest/RoundingModeUtils.h" #include "test/UnitTest/StringUtils.h" #include "test/UnitTest/Test.h" @@ -123,35 +124,35 @@ template class CFPMatcher : public Matcher { bool match(T actualValue) { actual = actualValue; - if (cpp::is_complex_type_same()) + if constexpr (cpp::is_complex_type_same()) return matchComplex(); - else if (cpp::is_complex_type_same()) + else if constexpr (cpp::is_complex_type_same()) return matchComplex(); - else if (cpp::is_complex_type_same()) + else if constexpr (cpp::is_complex_type_same()) return matchComplex(); #ifdef LIBC_TYPES_HAS_CFLOAT16 - else if (cpp::is_complex_type_same) + else if constexpr (cpp::is_complex_type_same) return matchComplex(); #endif #ifdef LIBC_TYPES_HAS_CFLOAT128 - else if (cpp::is_complex_type_same) + else if constexpr (cpp::is_complex_type_same) return matchComplex(); #endif } void explainError() override { - if (cpp::is_complex_type_same()) + if constexpr (cpp::is_complex_type_same()) return explainErrorComplex(); - else if (cpp::is_complex_type_same()) + else if constexpr (cpp::is_complex_type_same()) return explainErrorComplex(); - else if (cpp::is_complex_type_same()) + else if constexpr (cpp::is_complex_type_same()) return explainErrorComplex(); #ifdef LIBC_TYPES_HAS_CFLOAT16 - else if (cpp::is_complex_type_same) + else if constexpr (cpp::is_complex_type_same) return explainErrorComplex(); #endif #ifdef LIBC_TYPES_HAS_CFLOAT128 - else if (cpp::is_complex_type_same) + else if constexpr (cpp::is_complex_type_same) return explainErrorComplex(); #endif } @@ -192,6 +193,31 @@ template struct FPTest : public Test { }; }; +// Add facility to test Flush-Denormal-To-Zero (FTZ) and Denormal-As-Zero (DAZ) +// modes. +// These tests to ensure that our implementations will not crash under these +// modes. +#if defined(LIBC_TARGET_ARCH_IS_X86_64) && __has_builtin(__builtin_ia32_stmxcsr) + +#define LIBC_TEST_FTZ_DAZ + +static constexpr unsigned FTZ = 0x8000; // Flush denormal to zero +static constexpr unsigned DAZ = 0x0040; // Denormal as zero + +struct ModifyMXCSR { + ModifyMXCSR(unsigned flags) { + old_mxcsr = __builtin_ia32_stmxcsr(); + __builtin_ia32_ldmxcsr(old_mxcsr | flags); + } + + ~ModifyMXCSR() { __builtin_ia32_ldmxcsr(old_mxcsr); } + +private: + unsigned old_mxcsr; +}; + +#endif + } // namespace testing } // namespace LIBC_NAMESPACE_DECL @@ -374,4 +400,17 @@ template struct FPTest : public Test { EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_MODE( \ (expected), (actual), (expected_except), RoundingMode::TowardZero) +#define EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(expected, actual, \ + expected_except) \ + do { \ + EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_NEAREST((expected), (actual), \ + (expected_except)); \ + EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_UPWARD((expected), (actual), \ + (expected_except)); \ + EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_DOWNWARD((expected), (actual), \ + (expected_except)); \ + EXPECT_FP_EQ_WITH_EXCEPTION_ROUNDING_TOWARD_ZERO((expected), (actual), \ + (expected_except)); \ + } while (0) + #endif // LLVM_LIBC_TEST_UNITTEST_FPMATCHER_H diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index 11342e6dfa045..262c717dd27d5 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -1490,6 +1490,17 @@ add_fp_unittest( libc.src.math.sqrtl ) +add_fp_unittest( + sqrtf16_test + NEED_MPFR + SUITE + libc-math-unittests + SRCS + sqrtf16_test.cpp + DEPENDS + libc.src.math.sqrtf16 +) + add_fp_unittest( generic_sqrtf_test NEED_MPFR @@ -1772,6 +1783,17 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + logf16_test + NEED_MPFR + SUITE + libc-math-unittests + SRCS + logf16_test.cpp + DEPENDS + libc.src.math.logf16 +) + add_fp_unittest( log2_test NEED_MPFR @@ -1798,6 +1820,17 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + log2f16_test + NEED_MPFR + SUITE + libc-math-unittests + SRCS + log2f16_test.cpp + DEPENDS + libc.src.math.log2f16 +) + add_fp_unittest( log10_test NEED_MPFR @@ -1824,6 +1857,17 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + log10f16_test + NEED_MPFR + SUITE + libc-math-unittests + SRCS + log10f16_test.cpp + DEPENDS + libc.src.math.log10f16 +) + add_fp_unittest( log1p_test NEED_MPFR diff --git a/libc/test/src/math/log10f16_test.cpp b/libc/test/src/math/log10f16_test.cpp new file mode 100644 index 0000000000000..a71e3309ac5f0 --- /dev/null +++ b/libc/test/src/math/log10f16_test.cpp @@ -0,0 +1,40 @@ +//===-- Exhaustive test for log10f16 --------------------------------------===// +// +// 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 "src/math/log10f16.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" +#include "utils/MPFRWrapper/MPFRUtils.h" + +using LlvmLibcLog10f16Test = LIBC_NAMESPACE::testing::FPTest; + +namespace mpfr = LIBC_NAMESPACE::testing::mpfr; + +// Range: [0, Inf]; +static constexpr uint16_t POS_START = 0x0000U; +static constexpr uint16_t POS_STOP = 0x7c00U; + +// Range: [-Inf, 0]; +static constexpr uint16_t NEG_START = 0x8000U; +static constexpr uint16_t NEG_STOP = 0xfc00U; + +TEST_F(LlvmLibcLog10f16Test, PositiveRange) { + for (uint16_t v = POS_START; v <= POS_STOP; ++v) { + float16 x = FPBits(v).get_val(); + EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log10, x, + LIBC_NAMESPACE::log10f16(x), 0.5); + } +} + +TEST_F(LlvmLibcLog10f16Test, NegativeRange) { + for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) { + float16 x = FPBits(v).get_val(); + EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log10, x, + LIBC_NAMESPACE::log10f16(x), 0.5); + } +} diff --git a/libc/test/src/math/log2f16_test.cpp b/libc/test/src/math/log2f16_test.cpp new file mode 100644 index 0000000000000..6630ca877d8d1 --- /dev/null +++ b/libc/test/src/math/log2f16_test.cpp @@ -0,0 +1,40 @@ +//===-- Exhaustive test for log2f16 ---------------------------------------===// +// +// 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 "src/math/log2f16.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" +#include "utils/MPFRWrapper/MPFRUtils.h" + +using LlvmLibcLog2f16Test = LIBC_NAMESPACE::testing::FPTest; + +namespace mpfr = LIBC_NAMESPACE::testing::mpfr; + +// Range: [0, Inf]; +static constexpr uint16_t POS_START = 0x0000U; +static constexpr uint16_t POS_STOP = 0x7c00U; + +// Range: [-Inf, 0]; +static constexpr uint16_t NEG_START = 0x8000U; +static constexpr uint16_t NEG_STOP = 0xfc00U; + +TEST_F(LlvmLibcLog2f16Test, PositiveRange) { + for (uint16_t v = POS_START; v <= POS_STOP; ++v) { + float16 x = FPBits(v).get_val(); + EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log2, x, + LIBC_NAMESPACE::log2f16(x), 0.5); + } +} + +TEST_F(LlvmLibcLog2f16Test, NegativeRange) { + for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) { + float16 x = FPBits(v).get_val(); + EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log2, x, + LIBC_NAMESPACE::log2f16(x), 0.5); + } +} diff --git a/libc/test/src/math/logf16_test.cpp b/libc/test/src/math/logf16_test.cpp new file mode 100644 index 0000000000000..922918b092b21 --- /dev/null +++ b/libc/test/src/math/logf16_test.cpp @@ -0,0 +1,40 @@ +//===-- Exhaustive test for logf16 ----------------------------------------===// +// +// 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 "src/math/logf16.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" +#include "utils/MPFRWrapper/MPFRUtils.h" + +using LlvmLibcLogf16Test = LIBC_NAMESPACE::testing::FPTest; + +namespace mpfr = LIBC_NAMESPACE::testing::mpfr; + +// Range: [0, Inf]; +static constexpr uint16_t POS_START = 0x0000U; +static constexpr uint16_t POS_STOP = 0x7c00U; + +// Range: [-Inf, 0]; +static constexpr uint16_t NEG_START = 0x8000U; +static constexpr uint16_t NEG_STOP = 0xfc00U; + +TEST_F(LlvmLibcLogf16Test, PositiveRange) { + for (uint16_t v = POS_START; v <= POS_STOP; ++v) { + float16 x = FPBits(v).get_val(); + EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log, x, + LIBC_NAMESPACE::logf16(x), 0.5); + } +} + +TEST_F(LlvmLibcLogf16Test, NegativeRange) { + for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) { + float16 x = FPBits(v).get_val(); + EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log, x, + LIBC_NAMESPACE::logf16(x), 0.5); + } +} diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index 899c9d2df4530..b2d1871541efc 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -2889,6 +2889,18 @@ add_fp_unittest( libc.src.math.sqrtl ) +add_fp_unittest( + sqrtf16_test + SUITE + libc-math-smoke-tests + SRCS + sqrtf16_test.cpp + HDRS + SqrtTest.h + DEPENDS + libc.src.math.sqrtf16 +) + add_fp_unittest( sqrtf128_test SUITE @@ -3558,6 +3570,19 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + logf16_test + SUITE + libc-math-smoke-tests + SRCS + logf16_test.cpp + DEPENDS + libc.hdr.fenv_macros + libc.src.errno.errno + libc.src.math.logf16 + libc.src.__support.FPUtil.cast +) + add_fp_unittest( log2_test SUITE @@ -3582,6 +3607,19 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + log2f16_test + SUITE + libc-math-smoke-tests + SRCS + log2f16_test.cpp + DEPENDS + libc.hdr.fenv_macros + libc.src.errno.errno + libc.src.math.log2f16 + libc.src.__support.FPUtil.cast +) + add_fp_unittest( log10_test SUITE @@ -3606,6 +3644,19 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + log10f16_test + SUITE + libc-math-smoke-tests + SRCS + log10f16_test.cpp + DEPENDS + libc.hdr.fenv_macros + libc.src.errno.errno + libc.src.math.log10f16 + libc.src.__support.FPUtil.cast +) + add_fp_unittest( log1p_test SUITE diff --git a/libc/test/src/math/smoke/atan2f_test.cpp b/libc/test/src/math/smoke/atan2f_test.cpp index 32a28cfdfeaa6..94ec18d8f6b14 100644 --- a/libc/test/src/math/smoke/atan2f_test.cpp +++ b/libc/test/src/math/smoke/atan2f_test.cpp @@ -58,3 +58,40 @@ TEST_F(LlvmLibcAtan2fTest, SpecialNumbers) { // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); } + +#ifdef LIBC_TEST_FTZ_DAZ + +using namespace LIBC_NAMESPACE::testing; + +TEST_F(LlvmLibcAtan2fTest, FTZMode) { + ModifyMXCSR mxcsr(FTZ); + + EXPECT_FP_EQ(0x1.921fb6p-1f, + LIBC_NAMESPACE::atan2f(min_denormal, min_denormal)); + EXPECT_FP_EQ(0x1.000002p-23f, + LIBC_NAMESPACE::atan2f(min_denormal, max_denormal)); + EXPECT_FP_EQ(0x1.921fb4p0f, + LIBC_NAMESPACE::atan2f(max_denormal, min_denormal)); + EXPECT_FP_EQ(0x1.921fb6p-1f, + LIBC_NAMESPACE::atan2f(max_denormal, max_denormal)); +} + +TEST_F(LlvmLibcAtan2fTest, DAZMode) { + ModifyMXCSR mxcsr(DAZ); + + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atan2f(min_denormal, min_denormal)); + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atan2f(min_denormal, max_denormal)); + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atan2f(max_denormal, min_denormal)); + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atan2f(max_denormal, max_denormal)); +} + +TEST_F(LlvmLibcAtan2fTest, FTZDAZMode) { + ModifyMXCSR mxcsr(FTZ | DAZ); + + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atan2f(min_denormal, min_denormal)); + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atan2f(min_denormal, max_denormal)); + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atan2f(max_denormal, min_denormal)); + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::atan2f(max_denormal, max_denormal)); +} + +#endif diff --git a/libc/test/src/math/smoke/log10f16_test.cpp b/libc/test/src/math/smoke/log10f16_test.cpp new file mode 100644 index 0000000000000..471e198933326 --- /dev/null +++ b/libc/test/src/math/smoke/log10f16_test.cpp @@ -0,0 +1,50 @@ +//===-- Unittests for log10f16 --------------------------------------------===// +// +// 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 "hdr/fenv_macros.h" +#include "src/__support/FPUtil/cast.h" +#include "src/errno/libc_errno.h" +#include "src/math/log10f16.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +using LlvmLibcLog10f16Test = LIBC_NAMESPACE::testing::FPTest; + +TEST_F(LlvmLibcLog10f16Test, SpecialNumbers) { + LIBC_NAMESPACE::libc_errno = 0; + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log10f16(aNaN)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::log10f16(sNaN), FE_INVALID); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::log10f16(inf)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log10f16(neg_inf)); + EXPECT_MATH_ERRNO(EDOM); + + EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING( + neg_inf, LIBC_NAMESPACE::log10f16(zero), FE_DIVBYZERO); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING( + neg_inf, LIBC_NAMESPACE::log10f16(neg_zero), FE_DIVBYZERO); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING( + zero, + LIBC_NAMESPACE::log10f16(LIBC_NAMESPACE::fputil::cast(1.0))); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING( + aNaN, + LIBC_NAMESPACE::log10f16(LIBC_NAMESPACE::fputil::cast(-1.0))); + EXPECT_MATH_ERRNO(EDOM); +} diff --git a/libc/test/src/math/smoke/log2f16_test.cpp b/libc/test/src/math/smoke/log2f16_test.cpp new file mode 100644 index 0000000000000..6d98482aa4499 --- /dev/null +++ b/libc/test/src/math/smoke/log2f16_test.cpp @@ -0,0 +1,50 @@ +//===-- Unittests for log2f16 ---------------------------------------------===// +// +// 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 "hdr/fenv_macros.h" +#include "src/__support/FPUtil/cast.h" +#include "src/errno/libc_errno.h" +#include "src/math/log2f16.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +using LlvmLibcLog2f16Test = LIBC_NAMESPACE::testing::FPTest; + +TEST_F(LlvmLibcLog2f16Test, SpecialNumbers) { + LIBC_NAMESPACE::libc_errno = 0; + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log2f16(aNaN)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::log2f16(sNaN), FE_INVALID); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::log2f16(inf)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log2f16(neg_inf)); + EXPECT_MATH_ERRNO(EDOM); + + EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING( + neg_inf, LIBC_NAMESPACE::log2f16(zero), FE_DIVBYZERO); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING( + neg_inf, LIBC_NAMESPACE::log2f16(neg_zero), FE_DIVBYZERO); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING( + zero, + LIBC_NAMESPACE::log2f16(LIBC_NAMESPACE::fputil::cast(1.0))); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING( + aNaN, + LIBC_NAMESPACE::log2f16(LIBC_NAMESPACE::fputil::cast(-1.0))); + EXPECT_MATH_ERRNO(EDOM); +} diff --git a/libc/test/src/math/smoke/logf16_test.cpp b/libc/test/src/math/smoke/logf16_test.cpp new file mode 100644 index 0000000000000..c7232aa1c1e32 --- /dev/null +++ b/libc/test/src/math/smoke/logf16_test.cpp @@ -0,0 +1,49 @@ +//===-- Unittests for logf16 ----------------------------------------------===// +// +// 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 "hdr/fenv_macros.h" +#include "src/__support/FPUtil/cast.h" +#include "src/errno/libc_errno.h" +#include "src/math/logf16.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +using LlvmLibcLogf16Test = LIBC_NAMESPACE::testing::FPTest; + +TEST_F(LlvmLibcLogf16Test, SpecialNumbers) { + LIBC_NAMESPACE::libc_errno = 0; + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::logf16(aNaN)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::logf16(sNaN), FE_INVALID); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::logf16(inf)); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::logf16(neg_inf)); + EXPECT_MATH_ERRNO(EDOM); + + EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING( + neg_inf, LIBC_NAMESPACE::logf16(zero), FE_DIVBYZERO); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING( + neg_inf, LIBC_NAMESPACE::logf16(neg_zero), FE_DIVBYZERO); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING( + zero, LIBC_NAMESPACE::logf16(LIBC_NAMESPACE::fputil::cast(1.0))); + EXPECT_MATH_ERRNO(0); + + EXPECT_FP_EQ_ALL_ROUNDING( + aNaN, + LIBC_NAMESPACE::logf16(LIBC_NAMESPACE::fputil::cast(-1.0))); + EXPECT_MATH_ERRNO(EDOM); +} diff --git a/libc/test/src/math/smoke/powf_test.cpp b/libc/test/src/math/smoke/powf_test.cpp index bd4f98e30fbdc..a0f66f2733a1e 100644 --- a/libc/test/src/math/smoke/powf_test.cpp +++ b/libc/test/src/math/smoke/powf_test.cpp @@ -190,4 +190,7 @@ TEST_F(LlvmLibcPowfTest, SpecialNumbers) { FE_UNDERFLOW); } } + + EXPECT_FP_EQ(-0.0f, LIBC_NAMESPACE::powf(-0.015625f, 25.0f)); + EXPECT_FP_EQ(0.0f, LIBC_NAMESPACE::powf(-0.015625f, 26.0f)); } diff --git a/libc/test/src/math/smoke/sqrtf16_test.cpp b/libc/test/src/math/smoke/sqrtf16_test.cpp new file mode 100644 index 0000000000000..d62049661eecb --- /dev/null +++ b/libc/test/src/math/smoke/sqrtf16_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for sqrtf16 ---------------------------------------------===// +// +// 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 "SqrtTest.h" + +#include "src/math/sqrtf16.h" + +LIST_SQRT_TESTS(float16, LIBC_NAMESPACE::sqrtf16) diff --git a/libc/test/src/math/sqrtf16_test.cpp b/libc/test/src/math/sqrtf16_test.cpp new file mode 100644 index 0000000000000..f6e8996761245 --- /dev/null +++ b/libc/test/src/math/sqrtf16_test.cpp @@ -0,0 +1,28 @@ +//===-- Exhaustive test for sqrtf16 ---------------------------------------===// +// +// 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 "src/math/sqrtf16.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" +#include "utils/MPFRWrapper/MPFRUtils.h" + +using LlvmLibcSqrtf16Test = LIBC_NAMESPACE::testing::FPTest; + +namespace mpfr = LIBC_NAMESPACE::testing::mpfr; + +// Range: [0, Inf]; +static constexpr uint16_t POS_START = 0x0000U; +static constexpr uint16_t POS_STOP = 0x7c00U; + +TEST_F(LlvmLibcSqrtf16Test, PositiveRange) { + for (uint16_t v = POS_START; v <= POS_STOP; ++v) { + float16 x = FPBits(v).get_val(); + EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Sqrt, x, + LIBC_NAMESPACE::sqrtf16(x), 0.5); + } +} diff --git a/libc/test/src/stdio/sscanf_test.cpp b/libc/test/src/stdio/sscanf_test.cpp index 33bb0acba3e66..18addb632067c 100644 --- a/libc/test/src/stdio/sscanf_test.cpp +++ b/libc/test/src/stdio/sscanf_test.cpp @@ -177,13 +177,25 @@ TEST(LlvmLibcSScanfTest, IntConvMaxLengthTests) { EXPECT_EQ(ret_val, 1); EXPECT_EQ(result, 0); + result = -999; + + // 0x is a valid prefix, but not a valid number. This should be a matching + // failure and should not modify the values. ret_val = LIBC_NAMESPACE::sscanf("0x1", "%2i", &result); - EXPECT_EQ(ret_val, 1); - EXPECT_EQ(result, 0); + EXPECT_EQ(ret_val, 0); + EXPECT_EQ(result, -999); ret_val = LIBC_NAMESPACE::sscanf("-0x1", "%3i", &result); + EXPECT_EQ(ret_val, 0); + EXPECT_EQ(result, -999); + + ret_val = LIBC_NAMESPACE::sscanf("0x1", "%3i", &result); EXPECT_EQ(ret_val, 1); - EXPECT_EQ(result, 0); + EXPECT_EQ(result, 1); + + ret_val = LIBC_NAMESPACE::sscanf("-0x1", "%4i", &result); + EXPECT_EQ(ret_val, 1); + EXPECT_EQ(result, -1); ret_val = LIBC_NAMESPACE::sscanf("-0x123", "%4i", &result); EXPECT_EQ(ret_val, 1); @@ -212,7 +224,7 @@ TEST(LlvmLibcSScanfTest, IntConvNoWriteTests) { EXPECT_EQ(result, 0); ret_val = LIBC_NAMESPACE::sscanf("0x1", "%*2i", &result); - EXPECT_EQ(ret_val, 1); + EXPECT_EQ(ret_val, 0); EXPECT_EQ(result, 0); ret_val = LIBC_NAMESPACE::sscanf("a", "%*i", &result); @@ -679,13 +691,17 @@ TEST(LlvmLibcSScanfTest, CombinedConv) { EXPECT_EQ(result, 123); ASSERT_STREQ(buffer, "abc"); + result = -1; + + // 0x is a valid prefix, but not a valid number. This should be a matching + // failure and should not modify the values. ret_val = LIBC_NAMESPACE::sscanf("0xZZZ", "%i%s", &result, buffer); - EXPECT_EQ(ret_val, 2); - EXPECT_EQ(result, 0); - ASSERT_STREQ(buffer, "ZZZ"); + EXPECT_EQ(ret_val, 0); + EXPECT_EQ(result, -1); + ASSERT_STREQ(buffer, "abc"); ret_val = LIBC_NAMESPACE::sscanf("0xZZZ", "%X%s", &result, buffer); - EXPECT_EQ(ret_val, 2); - EXPECT_EQ(result, 0); - ASSERT_STREQ(buffer, "ZZZ"); + EXPECT_EQ(ret_val, 0); + EXPECT_EQ(result, -1); + ASSERT_STREQ(buffer, "abc"); } diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index 5f882bac8c465..3d7c3591a556e 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -213,7 +213,7 @@ set( tahiti_aliases pitcairn verde oland hainan bonaire kabini kaveri hawaii gfx1010 gfx1011 gfx1012 gfx1013 gfx1030 gfx1031 gfx1032 gfx1033 gfx1034 gfx1035 gfx1036 gfx1100 gfx1101 gfx1102 gfx1103 - gfx1150 gfx1151 gfx1152 + gfx1150 gfx1151 gfx1152 gfx1153 gfx1200 gfx1201 ) diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv index 3b56807312d55..7714f41ca19e0 100644 --- a/libcxx/docs/Status/Cxx17Papers.csv +++ b/libcxx/docs/Status/Cxx17Papers.csv @@ -71,7 +71,7 @@ "`P0394R4 `__","Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling","2016-06 (Oulu)","|Complete|","17.0","" "","","","","","" "`P0003R5 `__","Removing Deprecated Exception Specifications from C++17","2016-11 (Issaquah)","|Complete|","5.0","" -"`P0067R5 `__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","``std::(to|from)_chars`` for integrals has been available since version 7.0. ``std::to_chars`` for ``float`` and ``double`` since version 14.0 ``std::to_chars`` for ``long double`` uses the implementation for ``double``." +"`P0067R5 `__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","``std::(to|from)_chars`` for integrals has been available since version 7.0. ``std::to_chars`` for ``float`` and ``double`` since version 14.0 ``std::to_chars`` for ``long double`` uses the implementation for ``double``. ``std::from_chars`` for ``float`` and ``double`` since version 20.0." "`P0403R1 `__","Literal suffixes for ``basic_string_view``\ ","2016-11 (Issaquah)","|Complete|","4.0","" "`P0414R2 `__","Merging shared_ptr changes from Library Fundamentals to C++17","2016-11 (Issaquah)","|Complete|","11.0","" "`P0418R2 `__","Fail or succeed: there is no atomic lattice","2016-11 (Issaquah)","","","" diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv index a62c4992020a0..19572c655ecd2 100644 --- a/libcxx/docs/Status/Cxx2cIssues.csv +++ b/libcxx/docs/Status/Cxx2cIssues.csv @@ -78,4 +78,5 @@ "","","","","","" "`LWG3343 `__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Adopted Yet","|Complete|","16.0","" "`LWG4139 `__","§[time.zone.leap] recursive constraint in <=>","Not Adopted Yet","|Complete|","20.0","" +"`LWG3456 `__","Pattern used by std::from_chars is underspecified (option B)",,"Not Yet Adopted","|Complete|","20.0","" "","","","","","" diff --git a/libcxx/docs/Status/ParallelismProjects.csv b/libcxx/docs/Status/ParallelismProjects.csv index 055be02843a2f..fdd6129f926f9 100644 --- a/libcxx/docs/Status/ParallelismProjects.csv +++ b/libcxx/docs/Status/ParallelismProjects.csv @@ -28,6 +28,7 @@ Section,Description,Dependencies,Assignee,Complete | `[parallel.simd.class] `_, "`simd load constructor `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd subscript operators `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "`simd copy functions `_", None, Yin Zhang, |Complete| +| `[parallel.simd.class] `_, "`simd unary operators `_", None, Yin Zhang, |Complete| | `[parallel.simd.class] `_, "Class template simd implementation", None, Yin Zhang, |In Progress| | `[parallel.simd.nonmembers] `_, "simd non-member operations", None, Yin Zhang, |In Progress| | `[parallel.simd.mask.class] `_, "`Class template simd_mask declaration and alias `_", [parallel.simd.abi], Yin Zhang, |Complete| diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 3431ea7dab386..86d2fc2c2c679 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -235,6 +235,7 @@ set(files __bit/rotate.h __bit_reference __charconv/chars_format.h + __charconv/from_chars_floating_point.h __charconv/from_chars_integral.h __charconv/from_chars_result.h __charconv/tables.h @@ -967,7 +968,6 @@ set(files limits list locale - locale.h map math.h mdspan @@ -998,7 +998,6 @@ set(files stdbool.h stddef.h stdexcept - stdint.h stdio.h stdlib.h stop_token diff --git a/libcxx/include/__charconv/from_chars_floating_point.h b/libcxx/include/__charconv/from_chars_floating_point.h new file mode 100644 index 0000000000000..2860b0e8da83a --- /dev/null +++ b/libcxx/include/__charconv/from_chars_floating_point.h @@ -0,0 +1,73 @@ +// -*- 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 _LIBCPP___CHARCONV_FROM_CHARS_FLOATING_POINT_H +#define _LIBCPP___CHARCONV_FROM_CHARS_FLOATING_POINT_H + +#include <__assert> +#include <__charconv/chars_format.h> +#include <__charconv/from_chars_result.h> +#include <__config> +#include <__system_error/errc.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 17 + +template +struct __from_chars_result { + _Fp __value; + ptrdiff_t __n; + errc __ec; +}; + +template +_LIBCPP_EXPORTED_FROM_ABI __from_chars_result<_Fp> __from_chars_floating_point( + [[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt); + +extern template __from_chars_result __from_chars_floating_point( + [[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt); + +extern template __from_chars_result __from_chars_floating_point( + [[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt); + +template +_LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars(const char* __first, const char* __last, _Fp& __value, chars_format __fmt) { + __from_chars_result<_Fp> __r = std::__from_chars_floating_point<_Fp>(__first, __last, __fmt); + if (__r.__ec != errc::invalid_argument) + __value = __r.__value; + return {__first + __r.__n, __r.__ec}; +} + +_LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result +from_chars(const char* __first, const char* __last, float& __value, chars_format __fmt = chars_format::general) { + return std::__from_chars(__first, __last, __value, __fmt); +} + +_LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result +from_chars(const char* __first, const char* __last, double& __value, chars_format __fmt = chars_format::general) { + return std::__from_chars(__first, __last, __value, __fmt); +} + +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHARCONV_FROM_CHARS_FLOATING_POINT_H diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h index f42ff460db454..173999c46807c 100644 --- a/libcxx/include/__configuration/availability.h +++ b/libcxx/include/__configuration/availability.h @@ -87,6 +87,9 @@ // in all versions of the library are available. #if defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) +# define _LIBCPP_INTRODUCED_IN_LLVM_20 1 +# define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE /* nothing */ + # define _LIBCPP_INTRODUCED_IN_LLVM_19 1 # define _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE /* nothing */ @@ -132,6 +135,11 @@ // clang-format off +// LLVM 20 +// TODO: Fill this in +# define _LIBCPP_INTRODUCED_IN_LLVM_20 0 +# define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE __attribute__((unavailable)) + // LLVM 19 // TODO: Fill this in # define _LIBCPP_INTRODUCED_IN_LLVM_19 0 @@ -409,6 +417,11 @@ #define _LIBCPP_AVAILABILITY_HAS_BAD_EXPECTED_ACCESS_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_19 #define _LIBCPP_AVAILABILITY_BAD_EXPECTED_ACCESS_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE +// This controls the availability of floating-point std::from_chars functions. +// These overloads were added later than the integer overloads. +#define _LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20 +#define _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE + // Define availability attributes that depend on _LIBCPP_HAS_EXCEPTIONS. // Those are defined in terms of the availability attributes above, and // should not be vendor-specific. diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h index 50c0f21eaa286..5e88d86ad5e9b 100644 --- a/libcxx/include/__iterator/reverse_iterator.h +++ b/libcxx/include/__iterator/reverse_iterator.h @@ -136,10 +136,12 @@ class _LIBCPP_TEMPLATE_VIS reverse_iterator _LIBCPP_HIDE_FROM_ABI constexpr pointer operator->() const requires is_pointer_v<_Iter> || requires(const _Iter __i) { __i.operator->(); } { + _Iter __tmp = current; + --__tmp; if constexpr (is_pointer_v<_Iter>) { - return std::prev(current); + return __tmp; } else { - return std::prev(current).operator->(); + return __tmp.operator->(); } } #else diff --git a/libcxx/include/charconv b/libcxx/include/charconv index a2e270e9316dc..29c6875008abb 100644 --- a/libcxx/include/charconv +++ b/libcxx/include/charconv @@ -65,6 +65,12 @@ namespace std { constexpr from_chars_result from_chars(const char* first, const char* last, see below& value, int base = 10); // constexpr since C++23 + from_chars_result from_chars(const char* first, const char* last, + float& value, chars_format fmt); + + from_chars_result from_chars(const char* first, const char* last, + double& value, chars_format fmt); + } // namespace std */ @@ -73,6 +79,7 @@ namespace std { #if _LIBCPP_STD_VER >= 17 # include <__charconv/chars_format.h> +# include <__charconv/from_chars_floating_point.h> # include <__charconv/from_chars_integral.h> # include <__charconv/from_chars_result.h> # include <__charconv/tables.h> diff --git a/libcxx/include/clocale b/libcxx/include/clocale index c689a64be288a..4d53aa7eb29b2 100644 --- a/libcxx/include/clocale +++ b/libcxx/include/clocale @@ -38,14 +38,6 @@ lconv* localeconv(); #include -#ifndef _LIBCPP_LOCALE_H -# error tried including but didn't find libc++'s header. \ - This usually means that your header search paths are not configured properly. \ - The header search paths should contain the C++ Standard Library headers before \ - any C Standard Library, and you are probably using compiler flags that make that \ - not be the case. -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/libcxx/include/cstdint b/libcxx/include/cstdint index 8c4782859426d..9c9b2323d06ea 100644 --- a/libcxx/include/cstdint +++ b/libcxx/include/cstdint @@ -144,14 +144,6 @@ Types: #include -#ifndef _LIBCPP_STDINT_H -# error tried including but didn't find libc++'s header. \ - This usually means that your header search paths are not configured properly. \ - The header search paths should contain the C++ Standard Library headers before \ - any C Standard Library, and you are probably using compiler flags that make that \ - not be the case. -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/libcxx/include/experimental/__simd/scalar.h b/libcxx/include/experimental/__simd/scalar.h index a76933e1a5849..d7ac1225fd789 100644 --- a/libcxx/include/experimental/__simd/scalar.h +++ b/libcxx/include/experimental/__simd/scalar.h @@ -68,6 +68,20 @@ struct __simd_operations<_Tp, simd_abi::__scalar> { static _LIBCPP_HIDE_FROM_ABI void __store(_SimdStorage __s, _Up* __mem) noexcept { *__mem = static_cast<_Up>(__s.__data); } + + static _LIBCPP_HIDE_FROM_ABI void __increment(_SimdStorage& __s) noexcept { ++__s.__data; } + + static _LIBCPP_HIDE_FROM_ABI void __decrement(_SimdStorage& __s) noexcept { --__s.__data; } + + static _LIBCPP_HIDE_FROM_ABI _MaskStorage __negate(_SimdStorage __s) noexcept { return {!__s.__data}; } + + static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_not(_SimdStorage __s) noexcept { + return {static_cast<_Tp>(~__s.__data)}; + } + + static _LIBCPP_HIDE_FROM_ABI _SimdStorage __unary_minus(_SimdStorage __s) noexcept { + return {static_cast<_Tp>(-__s.__data)}; + } }; template diff --git a/libcxx/include/experimental/__simd/simd.h b/libcxx/include/experimental/__simd/simd.h index 2c65d19e67b36..8d8d96518d97b 100644 --- a/libcxx/include/experimental/__simd/simd.h +++ b/libcxx/include/experimental/__simd/simd.h @@ -12,6 +12,7 @@ #include <__config> #include <__type_traits/enable_if.h> +#include <__type_traits/is_integral.h> #include <__type_traits/is_same.h> #include <__type_traits/remove_cvref.h> #include <__utility/forward.h> @@ -26,15 +27,29 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace parallelism_v2 { +template +class __simd_int_operators {}; + +template +class __simd_int_operators<_Simd, _Impl, true> { +public: + // unary operators for integral _Tp + _LIBCPP_HIDE_FROM_ABI _Simd operator~() const noexcept { + return _Simd(_Impl::__bitwise_not((*static_cast(this)).__s_), _Simd::__storage_tag); + } +}; + // class template simd [simd.class] // TODO: implement simd class template -class simd { +class simd : public __simd_int_operators, __simd_operations<_Tp, _Abi>, is_integral_v<_Tp>> { using _Impl = __simd_operations<_Tp, _Abi>; using _Storage = typename _Impl::_SimdStorage; _Storage __s_; + friend class __simd_int_operators; + public: using value_type = _Tp; using reference = __simd_reference<_Tp, _Storage, value_type>; @@ -45,6 +60,12 @@ class simd { _LIBCPP_HIDE_FROM_ABI simd() noexcept = default; + // explicit conversion from and to implementation-defined types + struct __storage_tag_t {}; + static constexpr __storage_tag_t __storage_tag{}; + explicit _LIBCPP_HIDE_FROM_ABI operator _Storage() const { return __s_; } + explicit _LIBCPP_HIDE_FROM_ABI simd(const _Storage& __s, __storage_tag_t) : __s_(__s) {} + // broadcast constructor template >, int> = 0> _LIBCPP_HIDE_FROM_ABI simd(_Up&& __v) noexcept : __s_(_Impl::__broadcast(static_cast(__v))) {} @@ -85,6 +106,37 @@ class simd { // scalar access [simd.subscr] _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); } _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); } + + // simd unary operators + _LIBCPP_HIDE_FROM_ABI simd& operator++() noexcept { + _Impl::__increment(__s_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI simd operator++(int) noexcept { + simd __r = *this; + _Impl::__increment(__s_); + return __r; + } + + _LIBCPP_HIDE_FROM_ABI simd& operator--() noexcept { + _Impl::__decrement(__s_); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI simd operator--(int) noexcept { + simd __r = *this; + _Impl::__decrement(__s_); + return __r; + } + + _LIBCPP_HIDE_FROM_ABI mask_type operator!() const noexcept { + return mask_type(_Impl::__negate(__s_), mask_type::__storage_tag); + } + + _LIBCPP_HIDE_FROM_ABI simd operator+() const noexcept { return *this; } + + _LIBCPP_HIDE_FROM_ABI simd operator-() const noexcept { return simd(_Impl::__unary_minus(__s_), __storage_tag); } }; template diff --git a/libcxx/include/experimental/__simd/simd_mask.h b/libcxx/include/experimental/__simd/simd_mask.h index 5527319415313..03e9da8519bfb 100644 --- a/libcxx/include/experimental/__simd/simd_mask.h +++ b/libcxx/include/experimental/__simd/simd_mask.h @@ -42,6 +42,12 @@ class simd_mask { _LIBCPP_HIDE_FROM_ABI simd_mask() noexcept = default; + // explicit conversion from and to implementation-defined types + struct __storage_tag_t {}; + static constexpr __storage_tag_t __storage_tag{}; + explicit _LIBCPP_HIDE_FROM_ABI operator _Storage() const { return __s_; } + explicit _LIBCPP_HIDE_FROM_ABI simd_mask(const _Storage& __s, __storage_tag_t) : __s_(__s) {} + // broadcast constructor _LIBCPP_HIDE_FROM_ABI explicit simd_mask(value_type __v) noexcept : __s_(_Impl::__broadcast(__v)) {} diff --git a/libcxx/include/experimental/__simd/vec_ext.h b/libcxx/include/experimental/__simd/vec_ext.h index 6c7fb8b09a467..6e8400948d46a 100644 --- a/libcxx/include/experimental/__simd/vec_ext.h +++ b/libcxx/include/experimental/__simd/vec_ext.h @@ -87,6 +87,16 @@ struct __simd_operations<_Tp, simd_abi::__vec_ext<_Np>> { for (size_t __i = 0; __i < _Np; __i++) __mem[__i] = static_cast<_Up>(__s.__data[__i]); } + + static _LIBCPP_HIDE_FROM_ABI void __increment(_SimdStorage& __s) noexcept { __s.__data = __s.__data + 1; } + + static _LIBCPP_HIDE_FROM_ABI void __decrement(_SimdStorage& __s) noexcept { __s.__data = __s.__data - 1; } + + static _LIBCPP_HIDE_FROM_ABI _MaskStorage __negate(_SimdStorage __s) noexcept { return {!__s.__data}; } + + static _LIBCPP_HIDE_FROM_ABI _SimdStorage __bitwise_not(_SimdStorage __s) noexcept { return {~__s.__data}; } + + static _LIBCPP_HIDE_FROM_ABI _SimdStorage __unary_minus(_SimdStorage __s) noexcept { return {-__s.__data}; } }; template diff --git a/libcxx/include/locale.h b/libcxx/include/locale.h deleted file mode 100644 index 425bf47d437ac..0000000000000 --- a/libcxx/include/locale.h +++ /dev/null @@ -1,46 +0,0 @@ -// -*- 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 _LIBCPP_LOCALE_H -#define _LIBCPP_LOCALE_H - -/* - locale.h synopsis - -Macros: - - LC_ALL - LC_COLLATE - LC_CTYPE - LC_MONETARY - LC_NUMERIC - LC_TIME - -Types: - - lconv - -Functions: - - setlocale - localeconv - -*/ - -#include <__config> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if __has_include_next() -# include_next -#endif - -#endif // _LIBCPP_LOCALE_H diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 5a0e199394d01..d775da489e35e 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -898,6 +898,7 @@ module std [system] { module charconv { module chars_format { header "__charconv/chars_format.h" } + module from_chars_floating_point { header "__charconv/from_chars_floating_point.h" } module from_chars_integral { header "__charconv/from_chars_integral.h" } module from_chars_result { header "__charconv/from_chars_result.h" } module tables { header "__charconv/tables.h" } @@ -2184,10 +2185,6 @@ module std_inttypes_h [system] { header "inttypes.h" export * } -module std_locale_h [system] { - header "locale.h" - export * -} module std_math_h [system] { header "math.h" export * @@ -2204,10 +2201,6 @@ module std_stddef_h [system] { // 's __need_* macros require textual inclusion. textual header "stddef.h" } -module std_stdint_h [system] { - header "stdint.h" - export * -} module std_stdio_h [system] { // 's __need_* macros require textual inclusion. textual header "stdio.h" diff --git a/libcxx/include/stdint.h b/libcxx/include/stdint.h deleted file mode 100644 index 35e5b8cbdad26..0000000000000 --- a/libcxx/include/stdint.h +++ /dev/null @@ -1,127 +0,0 @@ -// -*- 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 _LIBCPP_STDINT_H -// AIX system headers need stdint.h to be re-enterable while _STD_TYPES_T -// is defined until an inclusion of it without _STD_TYPES_T occurs, in which -// case the header guard macro is defined. -#if !defined(_AIX) || !defined(_STD_TYPES_T) -# define _LIBCPP_STDINT_H -#endif // _STD_TYPES_T - -/* - stdint.h synopsis - -Macros: - - INT8_MIN - INT16_MIN - INT32_MIN - INT64_MIN - - INT8_MAX - INT16_MAX - INT32_MAX - INT64_MAX - - UINT8_MAX - UINT16_MAX - UINT32_MAX - UINT64_MAX - - INT_LEAST8_MIN - INT_LEAST16_MIN - INT_LEAST32_MIN - INT_LEAST64_MIN - - INT_LEAST8_MAX - INT_LEAST16_MAX - INT_LEAST32_MAX - INT_LEAST64_MAX - - UINT_LEAST8_MAX - UINT_LEAST16_MAX - UINT_LEAST32_MAX - UINT_LEAST64_MAX - - INT_FAST8_MIN - INT_FAST16_MIN - INT_FAST32_MIN - INT_FAST64_MIN - - INT_FAST8_MAX - INT_FAST16_MAX - INT_FAST32_MAX - INT_FAST64_MAX - - UINT_FAST8_MAX - UINT_FAST16_MAX - UINT_FAST32_MAX - UINT_FAST64_MAX - - INTPTR_MIN - INTPTR_MAX - UINTPTR_MAX - - INTMAX_MIN - INTMAX_MAX - - UINTMAX_MAX - - PTRDIFF_MIN - PTRDIFF_MAX - - SIG_ATOMIC_MIN - SIG_ATOMIC_MAX - - SIZE_MAX - - WCHAR_MIN - WCHAR_MAX - - WINT_MIN - WINT_MAX - - INT8_C(value) - INT16_C(value) - INT32_C(value) - INT64_C(value) - - UINT8_C(value) - UINT16_C(value) - UINT32_C(value) - UINT64_C(value) - - INTMAX_C(value) - UINTMAX_C(value) - -*/ - -#include <__config> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -/* C99 stdlib (e.g. glibc < 2.18) does not provide macros needed - for C++11 unless __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS - are defined -*/ -#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS) -# define __STDC_LIMIT_MACROS -#endif -#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) -# define __STDC_CONSTANT_MACROS -#endif - -#if __has_include_next() -# include_next -#endif - -#endif // _LIBCPP_STDINT_H diff --git a/libcxx/include/vector b/libcxx/include/vector index dc31f31838264..bfbf1ea1cfc9f 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -1292,24 +1292,14 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(initializer_list __il) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - if (__il.size() > 0) { - __vallocate(__il.size()); - __construct_at_end(__il.begin(), __il.end(), __il.size()); - } - __guard.__complete(); + __init_with_size(__il.begin(), __il.end(), __il.size()); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(initializer_list __il, const allocator_type& __a) : __alloc_(__a) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - if (__il.size() > 0) { - __vallocate(__il.size()); - __construct_at_end(__il.begin(), __il.end(), __il.size()); - } - __guard.__complete(); + __init_with_size(__il.begin(), __il.end(), __il.size()); } #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT index 6911694b75d8a..e27eb5fa046ff 100644 --- a/libcxx/lib/abi/CHANGELOG.TXT +++ b/libcxx/lib/abi/CHANGELOG.TXT @@ -16,6 +16,13 @@ New entries should be added directly below the "Version" header. Version 20.0 ------------ +* [libcxx][libc] Implements from_chars floating-point + + All platforms + ------------- + Symbol added: _ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE + Symbol added: _ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE + * [libc++] Stop trying to avoid exporting some typeinfo names This patch removes the explicit list of symbols to avoid exporting diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index db77e1d0ac30b..79f999b3e02bb 100644 --- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1584,6 +1584,8 @@ {'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__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', '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'} diff --git a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist index 8af5db472f7c3..9efdf11940a77 100644 --- a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1220,6 +1220,8 @@ {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt6__ndk127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt6__ndk127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk134__construct_barrier_algorithm_baseERi', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index 033d9f9987fa8..7fde4b905fc50 100644 --- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1715,6 +1715,8 @@ {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__14__fs10filesystem16_FilesystemClock9is_steadyE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__14__fs10filesystem4path19preferred_separatorE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist index 332d8abeb03e3..da30346257f95 100644 --- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1715,6 +1715,8 @@ {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__122__libcpp_verbose_abortEPKcz', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__14__fs10filesystem16_FilesystemClock9is_steadyE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__14__fs10filesystem4path19preferred_separatorE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'} {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__16__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist index 62716f5c415f0..e1dc6e778b57c 100644 --- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1584,6 +1584,8 @@ {'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__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__from_chars_floating_pointEPKcS1_RdNS_12chars_formatE', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt3__127__from_chars_floating_pointEPKcS1_RfNS_12chars_formatE', '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'} diff --git a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist index 6b77cda1e2866..ceeeffe4d9792 100644 --- a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1220,6 +1220,8 @@ {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt6__ndk127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt6__ndk127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt6__ndk134__construct_barrier_algorithm_baseERl', 'type': 'FUNC'} diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist index 3458b333dd6a9..d3670d237b239 100644 --- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1235,6 +1235,8 @@ {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIlNS_22__cxx_atomic_base_implIlEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', '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'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist index bdf90ba25c7fd..2c21a03d41a0d 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist @@ -1233,6 +1233,8 @@ {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', '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'} diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist index ac3cc129c04b5..0d4c509509087 100644 --- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist +++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist @@ -1204,6 +1204,8 @@ {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', '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'} @@ -2006,4 +2008,4 @@ {'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': '_ZTv0_n24_NSt3__19strstreamD1Ev', 'type': 'FUNC'} \ No newline at end of file diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 4af04f202db1f..cce8b8976f73c 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -31,6 +31,7 @@ set(LIBCXX_SOURCES include/ryu/f2s.h include/ryu/ryu.h include/to_chars_floating_point.h + include/from_chars_floating_point.h legacy_pointer_safety.cpp memory.cpp memory_resource.cpp @@ -172,11 +173,14 @@ endif() split_list(LIBCXX_COMPILE_FLAGS) split_list(LIBCXX_LINK_FLAGS) +include(FindLibcCommonUtils) + # Build the shared library. add_library(cxx_shared SHARED ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) target_include_directories(cxx_shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(cxx_shared PUBLIC cxx-headers libcxx-libc-shared - PRIVATE ${LIBCXX_LIBRARIES}) + PRIVATE ${LIBCXX_LIBRARIES} + PRIVATE llvm-libc-common-utilities) set_target_properties(cxx_shared PROPERTIES EXCLUDE_FROM_ALL "$,FALSE,TRUE>" @@ -267,7 +271,8 @@ add_library(cxx_static STATIC ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) target_include_directories(cxx_static PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(cxx_static PUBLIC cxx-headers libcxx-libc-static PRIVATE ${LIBCXX_LIBRARIES} - PRIVATE libcxx-abi-static) + PRIVATE libcxx-abi-static + PRIVATE llvm-libc-common-utilities) set_target_properties(cxx_static PROPERTIES EXCLUDE_FROM_ALL "$,FALSE,TRUE>" diff --git a/libcxx/src/charconv.cpp b/libcxx/src/charconv.cpp index 4fd7a2c2c0f03..3fe0afec0e283 100644 --- a/libcxx/src/charconv.cpp +++ b/libcxx/src/charconv.cpp @@ -9,6 +9,7 @@ #include #include +#include "include/from_chars_floating_point.h" #include "include/to_chars_floating_point.h" _LIBCPP_BEGIN_NAMESPACE_STD @@ -74,4 +75,15 @@ to_chars_result to_chars(char* __first, char* __last, long double __value, chars __first, __last, static_cast(__value), __fmt, __precision); } +template +__from_chars_result<_Fp> __from_chars_floating_point( + [[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt) { + return std::__from_chars_floating_point_impl<_Fp>(__first, __last, __fmt); +} + +template __from_chars_result __from_chars_floating_point( + [[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt); + +template __from_chars_result __from_chars_floating_point( + [[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt); _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/include/from_chars_floating_point.h b/libcxx/src/include/from_chars_floating_point.h new file mode 100644 index 0000000000000..19eeeb28fb08d --- /dev/null +++ b/libcxx/src/include/from_chars_floating_point.h @@ -0,0 +1,457 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H +#define _LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H + +// These headers are in the shared LLVM-libc header library. +#include "shared/fp_bits.h" +#include "shared/str_to_float.h" +#include "shared/str_to_integer.h" + +#include <__assert> +#include <__config> +#include +#include +#include +#include + +// Included for the _Floating_type_traits class +#include "to_chars_floating_point.h" + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Parses an infinity string. +// Valid strings are case insensitive and contain INF or INFINITY. +// +// - __first is the first argument to std::from_chars. When the string is invalid +// this value is returned as ptr in the result. +// - __last is the last argument of std::from_chars. +// - __value is the value argument of std::from_chars, +// - __ptr is the current position is the input string. This is points beyond +// the initial I character. +// - __negative whether a valid string represents -inf or +inf. +template +__from_chars_result<_Fp> +__from_chars_floating_point_inf(const char* const __first, const char* __last, const char* __ptr, bool __negative) { + if (__last - __ptr < 2) [[unlikely]] + return {_Fp{0}, 0, errc::invalid_argument}; + + if (std::tolower(__ptr[0]) != 'n' || std::tolower(__ptr[1]) != 'f') [[unlikely]] + return {_Fp{0}, 0, errc::invalid_argument}; + + __ptr += 2; + + // At this point the result is valid and contains INF. + // When the remaining part contains INITY this will be consumed. Otherwise + // only INF is consumed. For example INFINITZ will consume INF and ignore + // INITZ. + + if (__last - __ptr >= 5 // + && std::tolower(__ptr[0]) == 'i' // + && std::tolower(__ptr[1]) == 'n' // + && std::tolower(__ptr[2]) == 'i' // + && std::tolower(__ptr[3]) == 't' // + && std::tolower(__ptr[4]) == 'y') + __ptr += 5; + + if constexpr (numeric_limits<_Fp>::has_infinity) { + if (__negative) + return {-std::numeric_limits<_Fp>::infinity(), __ptr - __first, std::errc{}}; + + return {std::numeric_limits<_Fp>::infinity(), __ptr - __first, std::errc{}}; + } else { + return {_Fp{0}, __ptr - __first, errc::result_out_of_range}; + } +} + +// Parses a nan string. +// Valid strings are case insensitive and contain INF or INFINITY. +// +// - __first is the first argument to std::from_chars. When the string is invalid +// this value is returned as ptr in the result. +// - __last is the last argument of std::from_chars. +// - __value is the value argument of std::from_chars, +// - __ptr is the current position is the input string. This is points beyond +// the initial N character. +// - __negative whether a valid string represents -nan or +nan. +template +__from_chars_result<_Fp> +__from_chars_floating_point_nan(const char* const __first, const char* __last, const char* __ptr, bool __negative) { + if (__last - __ptr < 2) [[unlikely]] + return {_Fp{0}, 0, errc::invalid_argument}; + + if (std::tolower(__ptr[0]) != 'a' || std::tolower(__ptr[1]) != 'n') [[unlikely]] + return {_Fp{0}, 0, errc::invalid_argument}; + + __ptr += 2; + + // At this point the result is valid and contains NAN. When the remaining + // part contains ( n-char-sequence_opt ) this will be consumed. Otherwise + // only NAN is consumed. For example NAN(abcd will consume NAN and ignore + // (abcd. + if (__last - __ptr >= 2 && __ptr[0] == '(') { + size_t __offset = 1; + do { + if (__ptr[__offset] == ')') { + __ptr += __offset + 1; + break; + } + if (__ptr[__offset] != '_' && !std::isalnum(__ptr[__offset])) + break; + ++__offset; + } while (__ptr + __offset != __last); + } + + if (__negative) + return {-std::numeric_limits<_Fp>::quiet_NaN(), __ptr - __first, std::errc{}}; + + return {std::numeric_limits<_Fp>::quiet_NaN(), __ptr - __first, std::errc{}}; +} + +template +struct __fractional_constant_result { + size_t __offset{size_t(-1)}; + _Tp __mantissa{0}; + int __exponent{0}; + bool __truncated{false}; + bool __is_valid{false}; +}; + +// Parses the hex constant part of the hexadecimal floating-point value. +// - input start of buffer given to from_chars +// - __n the number of elements in the buffer +// - __offset where to start parsing. The input can have an optional sign, the +// offset starts after this sign. +template +__fractional_constant_result<_Tp> __parse_fractional_hex_constant(const char* __input, size_t __n, size_t __offset) { + __fractional_constant_result<_Tp> __result; + + const _Tp __mantissa_truncate_threshold = numeric_limits<_Tp>::max() / 16; + bool __fraction = false; + for (; __offset < __n; ++__offset) { + if (std::isxdigit(__input[__offset])) { + __result.__is_valid = true; + + uint32_t __digit = __input[__offset] - '0'; + switch (std::tolower(__input[__offset])) { + case 'a': + __digit = 10; + break; + case 'b': + __digit = 11; + break; + case 'c': + __digit = 12; + break; + case 'd': + __digit = 13; + break; + case 'e': + __digit = 14; + break; + case 'f': + __digit = 15; + break; + } + + if (__result.__mantissa < __mantissa_truncate_threshold) { + __result.__mantissa = (__result.__mantissa * 16) + __digit; + if (__fraction) + __result.__exponent -= 4; + } else { + if (__digit > 0) + __result.__truncated = true; + if (!__fraction) + __result.__exponent += 4; + } + } else if (__input[__offset] == '.') { + if (__fraction) + break; // this means that __input[__offset] points to a second decimal point, ending the number. + + __fraction = true; + } else + break; + } + + __result.__offset = __offset; + return __result; +} + +struct __exponent_result { + size_t __offset{size_t(-1)}; + int __value{0}; + bool __present{false}; +}; + +// When the exponent is not present the result of the struct contains +// __offset, 0, false. This allows using the results unconditionally, the +// __present is important for the scientific notation, where the value is +// mandatory. +__exponent_result __parse_exponent(const char* __input, size_t __n, size_t __offset, char __marker) { + if (__offset + 1 < __n && // an exponent always needs at least one digit. + std::tolower(__input[__offset]) == __marker && // + !std::isspace(__input[__offset + 1]) // leading whitespace is not allowed. + ) { + ++__offset; + LIBC_NAMESPACE::shared::StrToNumResult __e = + LIBC_NAMESPACE::shared::strtointeger(__input + __offset, 10, __n - __offset); + // __result.error contains the errno value, 0 or ERANGE these are not interesting. + // If the number of characters parsed is 0 it means there was no number. + if (__e.parsed_len != 0) + return {__offset + __e.parsed_len, __e.value, true}; + else + --__offset; // the assumption of a valid exponent was not true, undo eating the exponent character. + } + + return {__offset, 0, false}; +} + +// Here we do this operation as int64 to avoid overflow. +int32_t __merge_exponents(int64_t __fractional, int64_t __exponent, int __max_biased_exponent) { + int64_t __sum = __fractional + __exponent; + + if (__sum > __max_biased_exponent) + return __max_biased_exponent; + + if (__sum < -__max_biased_exponent) + return -__max_biased_exponent; + + return __sum; +} + +template +__from_chars_result<_Fp> +__calculate_result(_Tp __mantissa, int __exponent, bool __negative, __from_chars_result<_Fp> __result) { + auto __r = LIBC_NAMESPACE::shared::FPBits<_Fp>(); + __r.set_mantissa(__mantissa); + __r.set_biased_exponent(__exponent); + + // C17 7.12.1/6 + // The result underflows if the magnitude of the mathematical result is so + // small that the mathematical result cannot be represented, without + // extraordinary roundoff error, in an object of the specified type.237) If + // the result underflows, the function returns an implementation-defined + // value whose magnitude is no greater than the smallest normalized positive + // number in the specified type; if the integer expression math_errhandling + // & MATH_ERRNO is nonzero, whether errno acquires the value ERANGE is + // implementation-defined; if the integer expression math_errhandling & + // MATH_ERREXCEPT is nonzero, whether the "underflow" floating-point + // exception is raised is implementation-defined. + // + // LLVM-LIBC sets ERAGNE for subnormal values + // + // [charconv.from.chars]/1 + // ... If the parsed value is not in the range representable by the type of + // value, value is unmodified and the member ec of the return value is + // equal to errc::result_out_of_range. ... + // + // Undo the ERANGE for subnormal values. + if (__result.__ec == errc::result_out_of_range && __r.is_subnormal() && !__r.is_zero()) + __result.__ec = errc{}; + + if (__negative) + __result.__value = -__r.get_val(); + else + __result.__value = __r.get_val(); + + return __result; +} + +// Implements from_chars for decimal floating-point values. +// __first forwarded from from_chars +// __last forwarded from from_chars +// __value forwarded from from_chars +// __fmt forwarded from from_chars +// __ptr the start of the buffer to parse. This is after the optional sign character. +// __negative should __value be set to a negative value? +// +// This function and __from_chars_floating_point_decimal are similar. However +// the similar parts are all in helper functions. So the amount of code +// duplication is minimal. +template +__from_chars_result<_Fp> +__from_chars_floating_point_hex(const char* const __first, const char* __last, const char* __ptr, bool __negative) { + size_t __n = __last - __first; + ptrdiff_t __offset = __ptr - __first; + + auto __fractional = + std::__parse_fractional_hex_constant::_Uint_type>(__first, __n, __offset); + if (!__fractional.__is_valid) + return {_Fp{0}, 0, errc::invalid_argument}; + + auto __parsed_exponent = std::__parse_exponent(__first, __n, __fractional.__offset, 'p'); + __offset = __parsed_exponent.__offset; + int __exponent = std::__merge_exponents( + __fractional.__exponent, __parsed_exponent.__value, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT); + + __from_chars_result<_Fp> __result{_Fp{0}, __offset, {}}; + LIBC_NAMESPACE::shared::ExpandedFloat<_Fp> __expanded_float = {0, 0}; + if (__fractional.__mantissa != 0) { + auto __temp = LIBC_NAMESPACE::shared::binary_exp_to_float<_Fp>( + {__fractional.__mantissa, __exponent}, + __fractional.__truncated, + LIBC_NAMESPACE::shared::RoundDirection::Nearest); + __expanded_float = __temp.num; + if (__temp.error == ERANGE) { + __result.__ec = errc::result_out_of_range; + } + } + + return std::__calculate_result<_Fp>(__expanded_float.mantissa, __expanded_float.exponent, __negative, __result); +} + +// Parses the hex constant part of the decimal float value. +// - input start of buffer given to from_chars +// - __n the number of elements in the buffer +// - __offset where to start parsing. The input can have an optional sign, the +// offset starts after this sign. +template +__fractional_constant_result<_Tp> +__parse_fractional_decimal_constant(const char* __input, ptrdiff_t __n, ptrdiff_t __offset) { + __fractional_constant_result<_Tp> __result; + + const _Tp __mantissa_truncate_threshold = numeric_limits<_Tp>::max() / 10; + bool __fraction = false; + for (; __offset < __n; ++__offset) { + if (std::isdigit(__input[__offset])) { + __result.__is_valid = true; + + uint32_t __digit = __input[__offset] - '0'; + if (__result.__mantissa < __mantissa_truncate_threshold) { + __result.__mantissa = (__result.__mantissa * 10) + __digit; + if (__fraction) + --__result.__exponent; + } else { + if (__digit > 0) + __result.__truncated = true; + if (!__fraction) + ++__result.__exponent; + } + } else if (__input[__offset] == '.') { + if (__fraction) + break; // this means that __input[__offset] points to a second decimal point, ending the number. + + __fraction = true; + } else + break; + } + + __result.__offset = __offset; + return __result; +} + +// Implements from_chars for decimal floating-point values. +// __first forwarded from from_chars +// __last forwarded from from_chars +// __value forwarded from from_chars +// __fmt forwarded from from_chars +// __ptr the start of the buffer to parse. This is after the optional sign character. +// __negative should __value be set to a negative value? +template +__from_chars_result<_Fp> __from_chars_floating_point_decimal( + const char* const __first, const char* __last, chars_format __fmt, const char* __ptr, bool __negative) { + ptrdiff_t __n = __last - __first; + ptrdiff_t __offset = __ptr - __first; + + auto __fractional = + std::__parse_fractional_decimal_constant::_Uint_type>(__first, __n, __offset); + if (!__fractional.__is_valid) + return {_Fp{0}, 0, errc::invalid_argument}; + + __offset = __fractional.__offset; + + // LWG3456 Pattern used by std::from_chars is underspecified + // This changes fixed to ignore a possible exponent instead of making its + // existance an error. + int __exponent; + if (__fmt == chars_format::fixed) { + __exponent = + std::__merge_exponents(__fractional.__exponent, 0, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT); + } else { + auto __parsed_exponent = std::__parse_exponent(__first, __n, __offset, 'e'); + if (__fmt == chars_format::scientific && !__parsed_exponent.__present) { + // [charconv.from.chars]/6.2 if fmt has chars_format::scientific set but not chars_format::fixed, + // the otherwise optional exponent part shall appear; + return {_Fp{0}, 0, errc::invalid_argument}; + } + + __offset = __parsed_exponent.__offset; + __exponent = std::__merge_exponents( + __fractional.__exponent, __parsed_exponent.__value, LIBC_NAMESPACE::shared::FPBits<_Fp>::MAX_BIASED_EXPONENT); + } + + __from_chars_result<_Fp> __result{_Fp{0}, __offset, {}}; + LIBC_NAMESPACE::shared::ExpandedFloat<_Fp> __expanded_float = {0, 0}; + if (__fractional.__mantissa != 0) { + // This function expects to parse a positive value. This means it does not + // take a __first, __n as arguments, since __first points to '-' for + // negative values. + auto __temp = LIBC_NAMESPACE::shared::decimal_exp_to_float<_Fp>( + {__fractional.__mantissa, __exponent}, + __fractional.__truncated, + LIBC_NAMESPACE::shared::RoundDirection::Nearest, + __ptr, + __last - __ptr); + __expanded_float = __temp.num; + if (__temp.error == ERANGE) { + __result.__ec = errc::result_out_of_range; + } + } + + return std::__calculate_result(__expanded_float.mantissa, __expanded_float.exponent, __negative, __result); +} + +template +__from_chars_result<_Fp> +__from_chars_floating_point_impl(const char* const __first, const char* __last, chars_format __fmt) { + if (__first == __last) [[unlikely]] + return {_Fp{0}, 0, errc::invalid_argument}; + + const char* __ptr = __first; + bool __negative = *__ptr == '-'; + if (__negative) { + ++__ptr; + if (__ptr == __last) [[unlikely]] + return {_Fp{0}, 0, errc::invalid_argument}; + } + + // [charconv.from.chars] + // [Note 1: If the pattern allows for an optional sign, but the string has + // no digit characters following the sign, no characters match the pattern. + // -- end note] + // This is true for integrals, floating point allows -.0 + + // [charconv.from.chars]/6.2 + // if fmt has chars_format::scientific set but not chars_format::fixed, the + // otherwise optional exponent part shall appear; + // Since INF/NAN do not have an exponent this value is not valid. + // + // LWG3456 Pattern used by std::from_chars is underspecified + // Does not address this point, but proposed option B does solve this issue, + // Both MSVC STL and libstdc++ implement this this behaviour. + switch (std::tolower(*__ptr)) { + case 'i': + return std::__from_chars_floating_point_inf<_Fp>(__first, __last, __ptr + 1, __negative); + case 'n': + if constexpr (numeric_limits<_Fp>::has_quiet_NaN) + // NOTE: The pointer passed here will be parsed in the default C locale. + // This is standard behavior (see https://eel.is/c++draft/charconv.from.chars), but may be unexpected. + return std::__from_chars_floating_point_nan<_Fp>(__first, __last, __ptr + 1, __negative); + return {_Fp{0}, 0, errc::invalid_argument}; + } + + if (__fmt == chars_format::hex) + return std::__from_chars_floating_point_hex<_Fp>(__first, __last, __ptr, __negative); + + return std::__from_chars_floating_point_decimal<_Fp>(__first, __last, __fmt, __ptr, __negative); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPP_SRC_INCLUDE_FROM_CHARS_FLOATING_POINT_H diff --git a/libcxx/test/libcxx/depr/depr.c.headers/extern_c.pass.cpp b/libcxx/test/libcxx/depr/depr.c.headers/extern_c.pass.cpp index 9fa4021e5c1ea..63ca664379713 100644 --- a/libcxx/test/libcxx/depr/depr.c.headers/extern_c.pass.cpp +++ b/libcxx/test/libcxx/depr/depr.c.headers/extern_c.pass.cpp @@ -26,9 +26,6 @@ extern "C" { #include #include #include -#ifndef _LIBCPP_HAS_NO_LOCALIZATION -# include -#endif #include #include #include diff --git a/libcxx/test/libcxx/header_inclusions.gen.py b/libcxx/test/libcxx/header_inclusions.gen.py index 2ecc47cbb1891..e5def1ad4cb70 100644 --- a/libcxx/test/libcxx/header_inclusions.gen.py +++ b/libcxx/test/libcxx/header_inclusions.gen.py @@ -16,7 +16,7 @@ from libcxx.header_information import lit_header_restrictions, public_headers, mandatory_inclusions for header in public_headers: - header_guard = lambda h: f"_LIBCPP_{h.upper().replace('.', '_').replace('/', '_')}" + header_guard = lambda h: f"_LIBCPP_{str(h).upper().replace('.', '_').replace('/', '_')}" # has no header guards if header == 'cassert': diff --git a/libcxx/test/libcxx/headers_in_modulemap.sh.py b/libcxx/test/libcxx/headers_in_modulemap.sh.py index 237b006115ccd..51b14377ba89b 100644 --- a/libcxx/test/libcxx/headers_in_modulemap.sh.py +++ b/libcxx/test/libcxx/headers_in_modulemap.sh.py @@ -1,25 +1,15 @@ -# RUN: %{python} %s %{libcxx-dir}/utils %{include-dir} +# RUN: %{python} %s %{libcxx-dir}/utils import sys - sys.path.append(sys.argv[1]) +from libcxx.header_information import all_headers, libcxx_include -import pathlib -import sys -from libcxx.header_information import is_modulemap_header, is_header - -headers = list(pathlib.Path(sys.argv[2]).rglob("*")) -modulemap = open(f"{sys.argv[2]}/module.modulemap").read() +with open(libcxx_include / "module.modulemap") as f: + modulemap = f.read() isHeaderMissing = False - -for header in headers: - if not is_header(header): - continue - - header = header.relative_to(pathlib.Path(sys.argv[2])).as_posix() - - if not is_modulemap_header(header): +for header in all_headers: + if not header.is_in_modulemap(): continue if not str(header) in modulemap: diff --git a/libcxx/test/libcxx/transitive_includes.gen.py b/libcxx/test/libcxx/transitive_includes.gen.py index 22075364bf1b7..2693617bcb0e5 100644 --- a/libcxx/test/libcxx/transitive_includes.gen.py +++ b/libcxx/test/libcxx/transitive_includes.gen.py @@ -42,10 +42,10 @@ all_traces = [] for header in sorted(public_headers): - if header.endswith(".h"): # Skip C compatibility or detail headers + if header.is_C_compatibility() or header.is_internal(): continue - normalized_header = re.sub("/", "_", header) + normalized_header = re.sub("/", "_", str(header)) print( f"""\ // RUN: echo "#include <{header}>" | %{{cxx}} -xc++ - %{{flags}} %{{compile_flags}} --trace-includes -fshow-skipped-includes --preprocess > /dev/null 2> %t/trace-includes.{normalized_header}.txt @@ -55,17 +55,17 @@ print( f"""\ -// RUN: %{{python}} %{{libcxx-dir}}/test/libcxx/transitive_includes_to_csv.py {' '.join(all_traces)} > %{{libcxx-dir}}/test/libcxx/transitive_includes/%{{cxx_std}}.csv +// RUN: %{{python}} %{{libcxx-dir}}/test/libcxx/transitive_includes/to_csv.py {' '.join(all_traces)} > %{{libcxx-dir}}/test/libcxx/transitive_includes/%{{cxx_std}}.csv """ ) else: for header in public_headers: - if header.endswith(".h"): # Skip C compatibility or detail headers + if header.is_C_compatibility() or header.is_internal(): continue # Escape slashes for the awk command below - escaped_header = header.replace("/", "\\/") + escaped_header = str(header).replace("/", "\\/") print( f"""\ @@ -92,7 +92,7 @@ // RUN: mkdir %t // RUN: %{{cxx}} %s %{{flags}} %{{compile_flags}} --trace-includes -fshow-skipped-includes --preprocess > /dev/null 2> %t/trace-includes.txt -// RUN: %{{python}} %{{libcxx-dir}}/test/libcxx/transitive_includes_to_csv.py %t/trace-includes.txt > %t/actual_transitive_includes.csv +// RUN: %{{python}} %{{libcxx-dir}}/test/libcxx/transitive_includes/to_csv.py %t/trace-includes.txt > %t/actual_transitive_includes.csv // RUN: cat %{{libcxx-dir}}/test/libcxx/transitive_includes/%{{cxx_std}}.csv | awk '/^{escaped_header} / {{ print }}' > %t/expected_transitive_includes.csv // RUN: diff -w %t/expected_transitive_includes.csv %t/actual_transitive_includes.csv #include <{header}> diff --git a/libcxx/test/libcxx/transitive_includes/to_csv.py b/libcxx/test/libcxx/transitive_includes/to_csv.py new file mode 100755 index 0000000000000..69d94deedf6f5 --- /dev/null +++ b/libcxx/test/libcxx/transitive_includes/to_csv.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# ===----------------------------------------------------------------------===## +# +# 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 +# +# ===----------------------------------------------------------------------===## + +from typing import List, Tuple, Optional +import argparse +import io +import itertools +import os +import pathlib +import re +import sys + +libcxx_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) +sys.path.append(os.path.join(libcxx_root, "utils")) +from libcxx.header_information import Header + +def parse_line(line: str) -> Tuple[int, str]: + """ + Parse a single line of --trace-includes output. + + Returns the inclusion level and the raw file name being included. + """ + match = re.match(r"(\.+) (.+)", line) + if not match: + raise ArgumentError(f"Line {line} contains invalid data.") + + # The number of periods in front of the header name is the nesting level of + # that header. + return (len(match.group(1)), match.group(2)) + +def make_cxx_v1_relative(header: str) -> Optional[str]: + """ + Returns the path of the header as relative to /c++/v1, or None if the path + doesn't contain c++/v1. + + We use that heuristic to figure out which headers are libc++ headers. + """ + # On Windows, the path separators can either be forward slash or backslash. + # If it is a backslash, Clang prints it escaped as two consecutive + # backslashes, and they need to be escaped in the RE. (Use a raw string for + # the pattern to avoid needing another level of escaping on the Python string + # literal level.) + pathsep = r"(?:/|\\\\)" + CXX_V1_REGEX = r"^.*c\+\+" + pathsep + r"v[0-9]+" + pathsep + r"(.+)$" + match = re.match(CXX_V1_REGEX, header) + if not match: + return None + else: + return match.group(1) + +def parse_file(file: io.TextIOBase) -> List[Tuple[Header, Header]]: + """ + Parse a file containing --trace-includes output to generate a list of the + transitive includes contained in it. + """ + result = [] + includer = None + for line in file.readlines(): + (level, header) = parse_line(line) + relative = make_cxx_v1_relative(header) + + # Not a libc++ header + if relative is None: + continue + + # If we're at the first level, remember this header as being the one who includes other headers. + # There's usually exactly one, except if the compiler is passed a file with `-include`. + if level == 1: + includer = Header(relative) + continue + + # Otherwise, take note that this header is being included by the top-level includer. + else: + assert includer is not None + result.append((includer, Header(relative))) + return result + +def print_csv(includes: List[Tuple[Header, Header]]) -> None: + """ + Print the transitive includes as space-delimited CSV. + + This function only prints public libc++ headers that are not C compatibility headers. + """ + # Sort and group by includer + by_includer = lambda t: t[0] + includes = itertools.groupby(sorted(includes, key=by_includer), key=by_includer) + + for (includer, includees) in includes: + includees = map(lambda t: t[1], includees) + for h in sorted(set(includees)): + if h.is_public() and not h.is_C_compatibility(): + print(f"{includer} {h}") + +def main(argv): + parser = argparse.ArgumentParser( + description=""" + Given a list of headers produced by --trace-includes, produce a list of libc++ headers in that output. + + Note that -fshow-skipped-includes must also be passed to the compiler in order to get sufficient + information for this script to run. + + The output of this script is provided in space-delimited CSV format where each line contains: + +
+ """) + parser.add_argument("inputs", type=argparse.FileType("r"), nargs='+', default=None, + help="One or more files containing the result of --trace-includes") + args = parser.parse_args(argv) + + includes = [line for file in args.inputs for line in parse_file(file)] + print_csv(includes) + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/libcxx/test/libcxx/transitive_includes_to_csv.py b/libcxx/test/libcxx/transitive_includes_to_csv.py deleted file mode 100755 index 73571fb404ae7..0000000000000 --- a/libcxx/test/libcxx/transitive_includes_to_csv.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python -# ===----------------------------------------------------------------------===## -# -# 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 -# -# ===----------------------------------------------------------------------===## - -from dataclasses import dataclass -from typing import List # Needed for python 3.8 compatibility. -import argparse -import pathlib -import re -import sys - - -@dataclass -class header: - name: str = None - level: int = -1 - - -def parse_line(line: str) -> header: - """ - Parse an output line from --trace-includes into a `header`. - """ - match = re.match(r"(\.+) (.+)", line) - if not match: - sys.exit(f"Line {line} contains invalid data.") - - # The number of periods in front of the header name is the nesting level of - # that header. - return header(match.group(2), len(match.group(1))) - - -# On Windows, the path separators can either be forward slash or backslash. -# If it is a backslash, Clang prints it escaped as two consecutive -# backslashes, and they need to be escaped in the RE. (Use a raw string for -# the pattern to avoid needing another level of escaping on the Python string -# literal level.) -LIBCXX_HEADER_REGEX = r".*c\+\+(?:/|\\\\)v[0-9]+(?:/|\\\\)(.+)" - -def is_libcxx_header(header: str) -> bool: - """ - Returns whether a header is a libc++ header, excluding the C-compatibility headers. - """ - # Only keep files in the c++/vN directory. - match = re.match(LIBCXX_HEADER_REGEX, header) - if not match: - return False - - # Skip C compatibility headers (in particular, make sure not to skip libc++ detail headers). - relative = match.group(1) - if relative.endswith(".h") and not ( - relative.startswith("__") or re.search(r"(/|\\\\)__", relative) - ): - return False - - return True - - -def parse_file(file: pathlib.Path) -> List[str]: - """ - Parse a file containing --trace-includes output to generate a list of the top-level C++ includes - contained in it. - - This effectively generates the list of public libc++ headers of the header whose --trace-includes it is. - In order to get the expected result of --trace-includes, the -fshow-skipped-includes flag also needs to - be passed. - """ - result = list() - with file.open(encoding="utf-8") as f: - for line in f.readlines(): - header = parse_line(line) - - # Skip non-libc++ headers - if not is_libcxx_header(header.name): - continue - - # Include top-level headers in the output. There's usually exactly one, - # except if the compiler is passed a file with `-include`. Top-level - # headers are transparent, in the sense that we want to go look at - # transitive includes underneath. - if header.level == 1: - level = 999 - result.append(header) - continue - - # Detail headers are transparent too: we attribute all includes of public libc++ - # headers under a detail header to the last public libc++ header that included it. - if header.name.startswith("__") or re.search(r"(/|\\\\)__", header.name): - level = 999 - continue - - # Add the non-detail libc++ header to the list. - level = header.level - result.append(header) - return result - - -def create_include_graph(trace_includes: List[pathlib.Path]) -> List[str]: - result = list() - for file in trace_includes: - headers = parse_file(file) - - # Get actual filenames relative to libc++'s installation directory instead of full paths - relative = lambda h: re.match(LIBCXX_HEADER_REGEX, h).group(1) - - top_level = relative( - next(h.name for h in headers if h.level == 1) - ) # There should be only one top-level header - includes = [relative(h.name) for h in headers if h.level != 1] - - # Remove duplicates in all includes. - includes = list(set(includes)) - - if len(includes) != 0: - result.append([top_level] + includes) - return result - - -def print_csv(graph: List[str]) -> None: - for includes in graph: - header = includes[0] - for include in sorted(includes[1:]): - if header == include: - sys.exit(f"Cycle detected: header {header} includes itself.") - print(f"{header} {include}") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="""Produce a dependency graph of libc++ headers, in CSV format. -This script is normally executed by libcxx/test/libcxx/transitive_includes.gen.py""", - formatter_class=argparse.RawDescriptionHelpFormatter, - ) - parser.add_argument( - "inputs", - default=None, - metavar="FILE", - nargs='+', - help="One or more files containing the result of --trace-includes on the headers one wishes to graph.", - ) - options = parser.parse_args() - - print_csv(create_include_graph(map(pathlib.Path, options.inputs))) diff --git a/libcxx/test/std/atomics/atomics.lockfree/is_always_lock_free.pass.cpp b/libcxx/test/std/atomics/atomics.lockfree/is_always_lock_free.pass.cpp index e922bc7413514..5130758d5efd5 100644 --- a/libcxx/test/std/atomics/atomics.lockfree/is_always_lock_free.pass.cpp +++ b/libcxx/test/std/atomics/atomics.lockfree/is_always_lock_free.pass.cpp @@ -52,7 +52,7 @@ void check_always_lock_free(std::atomic const& a) { // In all cases, also sanity-check it based on the implication always-lock-free => lock-free. if (is_always_lock_free) { auto is_lock_free = a.is_lock_free(); - ASSERT_SAME_TYPE(decltype(is_always_lock_free), bool const); + ASSERT_SAME_TYPE(decltype(is_lock_free), bool); assert(is_lock_free); } ASSERT_NOEXCEPT(a.is_lock_free()); diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp new file mode 100644 index 0000000000000..f205ac971e5f0 --- /dev/null +++ b/libcxx/test/std/experimental/simd/simd.class/simd_unary.pass.cpp @@ -0,0 +1,191 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// Older versions of clang may encounter a backend error (see 0295c2ad): +// Pass-by-value arguments with alignment greater than register width are not supported. +// XFAIL: target=powerpc{{.*}}-ibm-{{.*}} && (clang-17 || clang-18) + +// FIXME: The following issue occurs on macOS 13.7 with Apple clang 15.0.0: +// clang: error: unable to execute command: Illegal instruction: 4 +// XFAIL: target=x86_64-apple-macosx13.7 + +// +// +// [simd.class] +// simd& operator++() noexcept; +// simd operator++(int) noexcept; +// simd& operator--() noexcept; +// simd operator--(int) noexcept; +// mask_type operator!() const noexcept; +// simd operator~() const noexcept; +// simd operator+() const noexcept; +// simd operator-() const noexcept; + +#include "../test_utils.h" +#include + +namespace ex = std::experimental::parallelism_v2; + +template +struct CheckSimdPrefixIncrementOperator { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + ex::simd origin_simd([](T i) { return i; }); + static_assert(noexcept(++origin_simd)); + std::array expected_return_value, expected_value; + for (size_t i = 0; i < array_size; ++i) { + expected_return_value[i] = static_cast(i) + 1; + expected_value[i] = static_cast(i) + 1; + } + assert_simd_values_equal(++origin_simd, expected_return_value); + assert_simd_values_equal(origin_simd, expected_value); + } +}; + +template +struct CheckSimdPostfixIncrementOperator { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + ex::simd origin_simd([](T i) { return i; }); + static_assert(noexcept(origin_simd++)); + std::array expected_return_value, expected_value; + for (size_t i = 0; i < array_size; ++i) { + expected_return_value[i] = static_cast(i); + expected_value[i] = static_cast(i) + 1; + } + assert_simd_values_equal(origin_simd++, expected_return_value); + assert_simd_values_equal(origin_simd, expected_value); + } +}; + +template +struct CheckSimdPrefixDecrementOperator { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + ex::simd origin_simd([](T i) { return i; }); + static_assert(noexcept(--origin_simd)); + std::array expected_return_value, expected_value; + for (size_t i = 0; i < array_size; ++i) { + expected_return_value[i] = static_cast(i) - 1; + expected_value[i] = static_cast(i) - 1; + } + assert_simd_values_equal(--origin_simd, expected_return_value); + assert_simd_values_equal(origin_simd, expected_value); + } +}; + +template +struct CheckSimdPostfixDecrementOperator { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + ex::simd origin_simd([](T i) { return i; }); + static_assert(noexcept(origin_simd--)); + std::array expected_return_value, expected_value; + for (size_t i = 0; i < array_size; ++i) { + expected_return_value[i] = static_cast(i); + expected_value[i] = static_cast(i) - 1; + } + assert_simd_values_equal(origin_simd--, expected_return_value); + assert_simd_values_equal(origin_simd, expected_value); + } +}; + +template +struct CheckSimdNegationOperator { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + ex::simd origin_simd([](T i) { return i; }); + static_assert(noexcept(!origin_simd)); + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) + expected_value[i] = !static_cast(i); + assert_simd_mask_values_equal(!origin_simd, expected_value); + } +}; + +template +struct CheckSimdBitwiseNotOperator { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + ex::simd origin_simd([](T i) { return i; }); + static_assert(noexcept(~origin_simd)); + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) + expected_value[i] = ~static_cast(i); + assert_simd_values_equal(~origin_simd, expected_value); + } +}; + +template +struct CheckSimdPositiveSignOperator { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + ex::simd origin_simd([](T i) { return i; }); + static_assert(noexcept(+origin_simd)); + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) + expected_value[i] = +static_cast(i); + assert_simd_values_equal(+origin_simd, expected_value); + } +}; + +template +struct CheckSimdNegativeSignOperator { + template + void operator()() { + constexpr std::size_t array_size = ex::simd_size_v; + ex::simd origin_simd([](T i) { return i; }); + static_assert(noexcept(-origin_simd)); + std::array expected_value; + for (size_t i = 0; i < array_size; ++i) + expected_value[i] = -static_cast(i); + assert_simd_values_equal(-origin_simd, expected_value); + } +}; + +template , class = void> +struct has_bitwise_not_op : std::false_type {}; + +template +struct has_bitwise_not_op>())>> : std::true_type {}; + +template +struct CheckSimdBitwiseNotTraits { + template + void operator()() { + // This function shall not participate in overload resolution unless + // T is an integral type. + if constexpr (std::is_integral_v) + static_assert(has_bitwise_not_op::value); + // T is not an integral type. + else + static_assert(!has_bitwise_not_op::value); + } +}; + +int main(int, char**) { + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + types::for_each(types::integer_types(), TestAllSimdAbiFunctor()); + test_all_simd_abi(); + test_all_simd_abi(); + test_all_simd_abi(); + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp index fcf8d88fcf62b..6fe575ebdd9a0 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/equal.pass.cpp @@ -33,6 +33,10 @@ TEST_CONSTEXPR_CXX17 bool tests() { test(bidirectional_iterator(s), bidirectional_iterator(s+1), false); test(random_access_iterator(s), random_access_iterator(s), true); test(random_access_iterator(s), random_access_iterator(s+1), false); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s), true); + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s + 1), false); +#endif test(s, s, true); test(s, s+1, false); return true; diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp index fdcd02abb0d8e..b2bfdb56d646e 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater-equal.pass.cpp @@ -32,6 +32,11 @@ TEST_CONSTEXPR_CXX17 bool tests() { test(random_access_iterator(s), random_access_iterator(s), true); test(random_access_iterator(s), random_access_iterator(s+1), true); test(random_access_iterator(s+1), random_access_iterator(s), false); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s), true); + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s + 1), true); + test(cpp20_random_access_iterator(s + 1), cpp20_random_access_iterator(s), false); +#endif test(s, s, true); test(s, s+1, true); test(s+1, s, false); diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp index dce331e519646..38f9258de31f5 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/greater.pass.cpp @@ -32,6 +32,11 @@ TEST_CONSTEXPR_CXX17 bool tests() { test(random_access_iterator(s), random_access_iterator(s), false); test(random_access_iterator(s), random_access_iterator(s+1), true); test(random_access_iterator(s+1), random_access_iterator(s), false); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s), false); + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s + 1), true); + test(cpp20_random_access_iterator(s + 1), cpp20_random_access_iterator(s), false); +#endif test(s, s, false); test(s, s+1, true); test(s+1, s, false); diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp index e9cea6250a764..a57930b111314 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less-equal.pass.cpp @@ -32,6 +32,11 @@ TEST_CONSTEXPR_CXX17 bool tests() { test(random_access_iterator(s), random_access_iterator(s), true); test(random_access_iterator(s), random_access_iterator(s+1), false); test(random_access_iterator(s+1), random_access_iterator(s), true); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s), true); + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s + 1), false); + test(cpp20_random_access_iterator(s + 1), cpp20_random_access_iterator(s), true); +#endif test(s, s, true); test(s, s+1, false); test(s+1, s, true); diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp index b66147cf3a03c..4cd3f249d033e 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/less.pass.cpp @@ -32,6 +32,11 @@ TEST_CONSTEXPR_CXX17 bool tests() { test(random_access_iterator(s), random_access_iterator(s), false); test(random_access_iterator(s), random_access_iterator(s+1), false); test(random_access_iterator(s+1), random_access_iterator(s), true); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s), false); + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s + 1), false); + test(cpp20_random_access_iterator(s + 1), cpp20_random_access_iterator(s), true); +#endif test(s, s, false); test(s, s+1, false); test(s+1, s, true); diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp index 37a6ff1302ce7..509ac297c3cba 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/not-equal.pass.cpp @@ -33,6 +33,10 @@ TEST_CONSTEXPR_CXX17 bool tests() { test(bidirectional_iterator(s), bidirectional_iterator(s+1), true); test(random_access_iterator(s), random_access_iterator(s), false); test(random_access_iterator(s), random_access_iterator(s+1), true); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s), false); + test(cpp20_random_access_iterator(s), cpp20_random_access_iterator(s + 1), true); +#endif test(s, s, false); test(s, s+1, true); return true; diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp index 0e5123a49e2b5..f9d2efa7c2a8c 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/assign.pass.cpp @@ -59,6 +59,9 @@ TEST_CONSTEXPR_CXX17 bool tests() { Derived d; test >(bidirectional_iterator(&d)); test >(random_access_iterator(&d)); +#if TEST_STD_VER >= 20 + test >(cpp20_random_access_iterator(&d)); +#endif test(&d); char c = '\0'; diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp index fcb96de91d1a0..90047b19f5a63 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.default.pass.cpp @@ -26,6 +26,9 @@ TEST_CONSTEXPR_CXX17 void test() { TEST_CONSTEXPR_CXX17 bool tests() { test >(); test >(); +#if TEST_STD_VER >= 20 + test >(); +#endif test(); test(); return true; diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp index 801b2cf879ce5..72e77b0856421 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.iter.pass.cpp @@ -28,6 +28,9 @@ TEST_CONSTEXPR_CXX17 bool tests() { const char s[] = "123"; test(bidirectional_iterator(s)); test(random_access_iterator(s)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s)); +#endif test(s); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp index 8f315e83f6d7b..fa967b45b1d9f 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cons/ctor.reverse_iterator.pass.cpp @@ -33,6 +33,9 @@ TEST_CONSTEXPR_CXX17 bool tests() { Derived d; test >(bidirectional_iterator(&d)); test >(random_access_iterator(&d)); +#if TEST_STD_VER >= 20 + test >(cpp20_random_access_iterator(&d)); +#endif test(&d); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp index 4fb33f5426045..35ed17583c855 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.conv/base.pass.cpp @@ -18,20 +18,28 @@ #include "test_macros.h" #include "test_iterators.h" -TEST_CONSTEXPR_CXX17 bool test() { - typedef bidirectional_iterator Iter; - int i = 0; - Iter iter(&i); - std::reverse_iterator const reverse(iter); - std::reverse_iterator::iterator_type base = reverse.base(); - assert(base == Iter(&i)); - return true; +template +TEST_CONSTEXPR_CXX17 void test() { + int i = 0; + Iter iter(&i); + std::reverse_iterator const reverse(iter); + typename std::reverse_iterator::iterator_type base = reverse.base(); + assert(base == Iter(&i)); +} + +TEST_CONSTEXPR_CXX17 bool tests() { + test >(); + test >(); +#if TEST_STD_VER >= 20 + test>(); +#endif + return true; } int main(int, char**) { - test(); + tests(); #if TEST_STD_VER > 14 - static_assert(test(), ""); + static_assert(tests(), ""); #endif - return 0; + return 0; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp index 15d18d9145ef0..665a1a89223bc 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp @@ -24,6 +24,55 @@ #include "test_macros.h" +#if TEST_STD_VER >= 20 +// C++20 bidirectional_iterator that does not satisfy the Cpp17BidirectionalIterator named requirement. +template +class cpp20_bidirectional_iterator_with_arrow { + It it_; + +public: + using iterator_category = std::input_iterator_tag; + using iterator_concept = std::bidirectional_iterator_tag; + using value_type = std::iterator_traits::value_type; + using difference_type = std::iterator_traits::difference_type; + + cpp20_bidirectional_iterator_with_arrow() : it_() {} + explicit cpp20_bidirectional_iterator_with_arrow(It it) : it_(it) {} + + decltype(auto) operator*() const { return *it_; } + + auto operator->() const { + if constexpr (std::is_pointer_v) { + return it_; + } else { + return it_.operator->(); + } + } + + cpp20_bidirectional_iterator_with_arrow& operator++() { + ++it_; + return *this; + } + cpp20_bidirectional_iterator_with_arrow& operator--() { + --it_; + return *this; + } + cpp20_bidirectional_iterator_with_arrow operator++(int) { return cpp20_bidirectional_iterator_with_arrow(it_++); } + cpp20_bidirectional_iterator_with_arrow operator--(int) { return cpp20_bidirectional_iterator_with_arrow(it_--); } + + friend bool + operator==(const cpp20_bidirectional_iterator_with_arrow& x, const cpp20_bidirectional_iterator_with_arrow& y) { + return x.it_ == y.it_; + } + friend bool + operator!=(const cpp20_bidirectional_iterator_with_arrow& x, const cpp20_bidirectional_iterator_with_arrow& y) { + return x.it_ != y.it_; + } + + friend It base(const cpp20_bidirectional_iterator_with_arrow& i) { return i.it_; } +}; +#endif + class A { int data_; @@ -113,6 +162,16 @@ int main(int, char**) static_assert(it1->get() == gC.get(), ""); } +#endif +#if TEST_STD_VER >= 20 + { + // The underlying iterator models c++20 bidirectional_iterator, + // but does not satisfy c++17 BidirectionalIterator named requirement + B data[] = {1, 2, 3}; + cpp20_bidirectional_iterator_with_arrow iter(data + 3); + auto ri = std::make_reverse_iterator(iter); + assert(ri->get() == 3); + } #endif { ((void)gC); diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp index 37a857ceefa83..8b45bfa09b4fe 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/bracket.pass.cpp @@ -33,6 +33,10 @@ TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "1234567890"; test(random_access_iterator(s+5), 4, '1'); test(random_access_iterator(s+5), 0, '5'); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 5), 4, '1'); + test(cpp20_random_access_iterator(s + 5), 0, '5'); +#endif test(s+5, 4, '1'); test(s+5, 0, '5'); return true; diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp index 292c6da9a7733..c3a489085c68b 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/dereference.pass.cpp @@ -21,6 +21,7 @@ #include #include "test_macros.h" +#include "test_iterators.h" class A { @@ -47,6 +48,10 @@ int main(int, char**) { A a; test(&a+1, A()); + test(random_access_iterator(&a + 1), A()); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(&a + 1), A()); +#endif #if TEST_STD_VER > 14 { diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp index 8c83ec1e9389f..91c2d9363619b 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/decrement-assign.pass.cpp @@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits::differen TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "1234567890"; test(random_access_iterator(s+5), 5, random_access_iterator(s+10)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 5), 5, cpp20_random_access_iterator(s + 10)); +#endif test(s+5, 5, s+10); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp index e32fac9fc24fe..2a2746f2cc52b 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/increment-assign.pass.cpp @@ -29,7 +29,10 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits::differen TEST_CONSTEXPR_CXX17 bool tests() { char const* s = "1234567890"; - test(random_access_iterator(s+5), 5, random_access_iterator(s)); + test(random_access_iterator(s + 5), 5, random_access_iterator(s)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 5), 5, cpp20_random_access_iterator(s)); +#endif test(s+5, 5, s); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp index f2474dd7669f2..759cacad94e24 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/minus.pass.cpp @@ -28,7 +28,10 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits::differen TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "1234567890"; - test(random_access_iterator(s+5), 5, random_access_iterator(s+10)); + test(random_access_iterator(s + 5), 5, random_access_iterator(s + 10)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 5), 5, cpp20_random_access_iterator(s + 10)); +#endif test(s+5, 5, s+10); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp index 5673425e79675..24fa84e4f37c8 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/plus.pass.cpp @@ -28,7 +28,10 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits::differen TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "1234567890"; - test(random_access_iterator(s+5), 5, random_access_iterator(s)); + test(random_access_iterator(s + 5), 5, random_access_iterator(s)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 5), 5, cpp20_random_access_iterator(s)); +#endif test(s+5, 5, s); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp index 24bedad314b7e..f0551b5efece0 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postdecrement.pass.cpp @@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "123"; test(bidirectional_iterator(s+1), bidirectional_iterator(s+2)); test(random_access_iterator(s+1), random_access_iterator(s+2)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 1), cpp20_random_access_iterator(s + 2)); +#endif test(s+1, s+2); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp index e15bfb2fd1509..f1d3ea21a5b86 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/postincrement.pass.cpp @@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "123"; test(bidirectional_iterator(s+1), bidirectional_iterator(s)); test(random_access_iterator(s+1), random_access_iterator(s)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 1), cpp20_random_access_iterator(s)); +#endif test(s+1, s); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp index 2fbd530a085dc..5a2ac78570367 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/predecrement.pass.cpp @@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "123"; test(bidirectional_iterator(s+1), bidirectional_iterator(s+2)); test(random_access_iterator(s+1), random_access_iterator(s+2)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 1), cpp20_random_access_iterator(s + 2)); +#endif test(s+1, s+2); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp index 5efc8a39e22aa..6087eedd2449f 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nav/preincrement.pass.cpp @@ -30,6 +30,9 @@ TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "123"; test(bidirectional_iterator(s+1), bidirectional_iterator(s)); test(random_access_iterator(s+1), random_access_iterator(s)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 1), cpp20_random_access_iterator(s)); +#endif test(s+1, s); return true; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp index 401eecb2a3b83..4a4e474a55083 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/make_reverse_iterator.pass.cpp @@ -22,24 +22,34 @@ #include "test_iterators.h" template -TEST_CONSTEXPR_CXX17 void test(It i) { - const std::reverse_iterator r = std::make_reverse_iterator(i); - assert(r.base() == i); +TEST_CONSTEXPR_CXX17 void test_one(It i) { + const std::reverse_iterator r = std::make_reverse_iterator(i); + assert(r.base() == i); +} + +template +TEST_CONSTEXPR_CXX17 void test() { + const char* s = "1234567890"; + It b(s); + It e(s + 10); + while (b != e) + test_one(b++); } TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - random_access_iterator b(s); - random_access_iterator e(s+10); - while (b != e) - test (b++); - return true; + test(); + test>(); + test>(); +#if TEST_STD_VER >= 20 + test>(); +#endif + return true; } int main(int, char**) { - tests(); + tests(); #if TEST_STD_VER > 14 - static_assert(tests(), ""); + static_assert(tests(), ""); #endif - return 0; + return 0; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp index f7f74d145d73c..676f6e1b49169 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/minus.pass.cpp @@ -23,45 +23,63 @@ #include "test_macros.h" #include "test_iterators.h" -template struct HasMinus : std::false_type {}; -template struct HasMinus : std::true_type {}; +template +struct HasMinus : std::false_type {}; +template +struct HasMinus : std::true_type {}; + +// Test non-subtractable base iterator types +static_assert(HasMinus, std::reverse_iterator >::value, ""); +static_assert(HasMinus, std::reverse_iterator >::value, ""); + +#if TEST_STD_VER >= 11 +static_assert(!HasMinus, std::reverse_iterator >::value, ""); +static_assert(!HasMinus >, + std::reverse_iterator > >::value, + ""); +#endif template -TEST_CONSTEXPR_CXX17 void test(It1 l, It2 r, std::ptrdiff_t x) { - const std::reverse_iterator r1(l); - const std::reverse_iterator r2(r); - assert((r1 - r2) == x); +TEST_CONSTEXPR_CXX17 void test_one(It1 l, It2 r, std::ptrdiff_t x) { + const std::reverse_iterator r1(l); + const std::reverse_iterator r2(r); + assert((r1 - r2) == x); } -TEST_CONSTEXPR_CXX17 bool tests() { - using PC = const char*; - char s[3] = {0}; - - // Test same base iterator type - test(s, s, 0); - test(s, s+1, 1); - test(s+1, s, -1); +template +TEST_CONSTEXPR_CXX17 void test() { + // Test same base iterator type + char s[3] = {0}; - // Test different (but subtractable) base iterator types - test(PC(s), s, 0); - test(PC(s), s+1, 1); - test(PC(s+1), s, -1); + test_one(Iter(s), Iter(s), 0); + test_one(Iter(s), Iter(s + 1), 1); + test_one(Iter(s + 1), Iter(s), -1); +} - // Test non-subtractable base iterator types - static_assert( HasMinus, std::reverse_iterator >::value, ""); - static_assert( HasMinus, std::reverse_iterator >::value, ""); -#if TEST_STD_VER >= 11 - static_assert(!HasMinus, std::reverse_iterator >::value, ""); - static_assert(!HasMinus >, std::reverse_iterator > >::value, ""); +TEST_CONSTEXPR_CXX17 bool tests() { + { + test(); + test >(); +#if TEST_STD_VER >= 20 + test>(); #endif + } + { + // Test different (but subtractable) base iterator types + using PC = const char*; + char s[3] = {0}; + test_one(PC(s), s, 0); + test_one(PC(s), s + 1, 1); + test_one(PC(s + 1), s, -1); + } - return true; + return true; } int main(int, char**) { - tests(); + tests(); #if TEST_STD_VER > 14 - static_assert(tests(), ""); + static_assert(tests(), ""); #endif - return 0; + return 0; } diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp index aeb9f89dd4872..9ead123781bc8 100644 --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/plus.pass.cpp @@ -29,6 +29,9 @@ TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits::differen TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "1234567890"; test(random_access_iterator(s+5), 5, random_access_iterator(s)); +#if TEST_STD_VER >= 20 + test(cpp20_random_access_iterator(s + 5), 5, cpp20_random_access_iterator(s)); +#endif test(s+5, 5, s); return true; } diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp new file mode 100644 index 0000000000000..6faf0499c4c9b --- /dev/null +++ b/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp @@ -0,0 +1,1560 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// XFAIL: availability-fp_from_chars-missing + +// from_chars_result from_chars(const char* first, const char* last, +// float& value, chars_format fmt = chars_format::general) +// +// from_chars_result from_chars(const char* first, const char* last, +// double& value, chars_format fmt = chars_format::general) + +#include +#include +#include +#include +#include +#include +#include + +#include "charconv_test_helpers.h" +#include "test_macros.h" + +template +void test_infinity(std::chars_format fmt) { + const char* s = "-InFiNiTyXXX"; + { // I + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 2, value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == s + 1); + assert(value == F(0.25)); + } + { // In + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 3, value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == s + 1); + assert(value == F(0.25)); + } + { // InF + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 4, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(value == std::numeric_limits::infinity()); + } + { // -InF + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 4, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(value == -std::numeric_limits::infinity()); + } + { // InFi + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 5, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(value == std::numeric_limits::infinity()); + } + { // -InFiN + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 6, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(value == -std::numeric_limits::infinity()); + } + { // InFiNi + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 7, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(value == std::numeric_limits::infinity()); + } + { // -InFiNiT + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 8, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(value == -std::numeric_limits::infinity()); + } + { // InFiNiTy + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 9, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 9); + assert(value == std::numeric_limits::infinity()); + } + { // -InFiNiTy + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 9, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 9); + assert(value == -std::numeric_limits::infinity()); + } + { // InFiNiTyXXX + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 12, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 9); + assert(value == std::numeric_limits::infinity()); + } + { // -InFiNiTyXXX + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 12, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 9); + assert(value == -std::numeric_limits::infinity()); + } +} + +template +void test_nan(std::chars_format fmt) { + { + const char* s = "-NaN(1_A)XXX"; + { // N + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 2, value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == s + 1); + assert(value == F(0.25)); + } + { // Na + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 3, value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == s + 1); + assert(value == F(0.25)); + } + { // NaN + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 4, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(std::isnan(value)); + assert(!std::signbit(value)); + } + { // -NaN + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 0, s + 4, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(std::isnan(value)); + assert(std::signbit(value)); + } + { // NaN( + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 5, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(std::isnan(value)); + assert(!std::signbit(value)); + } + { // -NaN(1 + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 6, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(std::isnan(value)); + assert(std::signbit(value)); + } + { // NaN(1_ + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 7, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(std::isnan(value)); + assert(!std::signbit(value)); + } + { // -NaN(1_A + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 8, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 4); + assert(std::isnan(value)); + assert(std::signbit(value)); + } + { // NaN(1_A) + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 9, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 9); + assert(std::isnan(value)); + assert(!std::signbit(value)); + } + { // -NaN(1_A) + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 9, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 9); + assert(std::isnan(value)); + assert(std::signbit(value)); + } + { // NaN(1_A)XXX + F value = 0.25; + std::from_chars_result result = std::from_chars(s + 1, s + 12, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 9); + assert(std::isnan(value)); + assert(!std::signbit(value)); + } + { // -NaN(1_A)XXX + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + 12, value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 9); + assert(std::isnan(value)); + assert(std::signbit(value)); + } + } + { + const char* s = "NaN()"; + F value = 0.25; + std::from_chars_result result = std::from_chars(s, s + std::strlen(s), value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s + 5); + assert(std::isnan(value)); + assert(!std::signbit(value)); + } + { // validates a n-char-sequences with an invalid value + std::array s = {'N', 'a', 'N', '(', ' ', ')'}; + s[4] = 'a'; + { + F value = 0.25; + std::from_chars_result result = std::from_chars(s.data(), s.data() + s.size(), value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s.data() + s.size()); + assert(std::isnan(value)); + assert(!std::signbit(value)); + } + for (auto c : "!@#$%^&*(-=+[]{}|\\;:'\",./<>?~` \t\v\r\n") { + F value = 0.25; + s[4] = c; + std::from_chars_result result = std::from_chars(s.data(), s.data() + s.size(), value, fmt); + + assert(result.ec == std::errc{}); + assert(result.ptr == s.data() + 3); + assert(std::isnan(value)); + assert(!std::signbit(value)); + } + } +} + +template +void test_fmt_independent(std::chars_format fmt) { + test_infinity(fmt); + test_nan(fmt); + + { // first == last + F value = 0.25; + std::from_chars_result result = std::from_chars(nullptr, nullptr, value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == nullptr); + assert(value == F(0.25)); + } + { // only a sign + F value = 0.25; + const char* s = "-"; + std::from_chars_result result = std::from_chars(s, s + std::strlen(s), value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == s); + assert(value == F(0.25)); + } + { // only decimal separator + F value = 0.25; + const char* s = "."; + std::from_chars_result result = std::from_chars(s, s + std::strlen(s), value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == s); + assert(value == F(0.25)); + } + { // sign and decimal separator + F value = 0.25; + const char* s = "-."; + std::from_chars_result result = std::from_chars(s, s + std::strlen(s), value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == s); + assert(value == F(0.25)); + } + { // + sign is not allowed + F value = 0.25; + const char* s = "+0.25"; + std::from_chars_result result = std::from_chars(s, s + std::strlen(s), value, fmt); + + assert(result.ec == std::errc::invalid_argument); + assert(result.ptr == s); + assert(value == F(0.25)); + } +} + +template +struct test_basics { + void operator()() { + for (auto fmt : {std::chars_format::scientific, + std::chars_format::fixed, + /*std::chars_format::hex,*/ std::chars_format::general}) + test_fmt_independent(fmt); + } +}; + +template +struct test_fixed { + void operator()() { + std::from_chars_result r; + F x = 0.25; + + // *** Failures + + { // Starts with invalid character + std::array s = {' ', '1'}; + for (auto c : "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") { + s[0] = c; + r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::fixed); + + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s.data()); + assert(x == F(0.25)); + } + } + + // *** Success + + { // number followed by non-numeric values + const char* s = "001x"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.0)); + } + { // no leading digit + const char* s = ".5"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 2); + assert(x == F(0.5)); + } + { // negative sign and no leading digit + const char* s = "-.5"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(-0.5)); + } + + { // double deciamal point + const char* s = "1.25.78"; + + // This number is halfway between two float values. + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { // exponenent no sign + const char* s = "1.5e10"; + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { // exponenent capitalized no sign + const char* s = "1.5E10"; + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { // exponenent + sign + const char* s = "1.5e+10"; + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { // exponenent - sign + const char* s = "1.5e-10"; + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { // Exponent no number + const char* s = "1.5e"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { // Exponent sign no number + { + const char* s = "1.5e+"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { + const char* s = "1.5e-"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + } + { // Exponent with whitespace + { + const char* s = "1.5e +1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { + const char* s = "1.5e+ 1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { + const char* s = "1.5e -1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { + const char* s = "1.5e- 1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + } + { // double exponent + const char* s = "1.25e0e12"; + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { // Exponent double sign + { + const char* s = "1.25e++12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { + const char* s = "1.25e+-12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { + const char* s = "1.25e-+12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { + const char* s = "1.25e--12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + } + { // exponent hex prefix + const char* s = "1.25e0x12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { // This number is halfway between two float values. + const char* s = "20040229"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 8); + assert(x == F(20040229)); + } + { // Shifting mantissa exponent and no exponent + const char* s = "123.456"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(1.23456e2)); + } + { // Shifting mantissa exponent and an exponent + const char* s = "123.456e3"; + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(123.456)); + } + { // Mantissa overflow + { + const char* s = "0.111111111111111111111111111111111111111111"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(0.111111111111111111111111111111111111111111)); + } + { + const char* s = "111111111111.111111111111111111111111111111111111111111"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(111111111111.111111111111111111111111111111111111111111)); + } + } + { // Negative value + const char* s = "-0.25"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(-0.25)); + } + } +}; + +template +struct test_scientific { + void operator()() { + std::from_chars_result r; + F x = 0.25; + + // *** Failures + + { // Starts with invalid character + std::array s = {' ', '1', 'e', '0'}; + for (auto c : "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") { + s[0] = c; + r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::scientific); + + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s.data()); + assert(x == F(0.25)); + } + } + { // No exponent + const char* s = "1.23"; + r = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific); + + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { // Exponent no number + const char* s = "1.23e"; + r = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific); + + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { // Exponent sign no number + { + const char* s = "1.5e+"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { + const char* s = "1.5e-"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + } + { // Exponent with whitespace + { + const char* s = "1.5e +1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { + const char* s = "1.5e+ 1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { + const char* s = "1.5e -1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { + const char* s = "1.5e- 1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + } + { // exponent double sign + { + const char* s = "1.25e++12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { + const char* s = "1.25e+-12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { + const char* s = "1.25e-+12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + { + const char* s = "1.25e--12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s); + assert(x == F(0.25)); + } + } + + // *** Success + + { // number followed by non-numeric values + const char* s = "001e0x"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 5); + assert(x == F(1.0)); + } + + { // double deciamal point + const char* s = "1.25e0.78"; + + // This number is halfway between two float values. + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.25)); + } + + { // exponenent no sign + const char* s = "1.5e10"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.5e10)); + } + { // exponenent capitalized no sign + const char* s = "1.5E10"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.5e10)); + } + { // exponenent + sign + const char* s = "1.5e+10"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(1.5e10)); + } + { // exponenent - sign + const char* s = "1.5e-10"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(1.5e-10)); + } + { // exponent hex prefix -> e0 + const char* s = "1.25e0x12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.25)); + } + { // double exponent + const char* s = "1.25e0e12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.25)); + } + { // This number is halfway between two float values. + const char* s = "20040229e0"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 10); + assert(x == F(20040229)); + } + { // Shifting mantissa exponent and an exponent + const char* s = "123.456e3"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 9); + assert(x == F(1.23456e5)); + } + { // Mantissa overflow + { + const char* s = "0.111111111111111111111111111111111111111111e0"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(0.111111111111111111111111111111111111111111)); + } + { + const char* s = "111111111111.111111111111111111111111111111111111111111e0"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(111111111111.111111111111111111111111111111111111111111)); + } + } + { // Negative value + const char* s = "-0.25e0"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(-0.25)); + } + { // value is too big -> +inf + const char* s = "1e9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == std::numeric_limits::infinity()); + } + { // negative value is too big -> -inf + const char* s = "-1e9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == -std::numeric_limits::infinity()); + } + { // value is too small -> 0 + const char* s = "1e-9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == F(0.0)); + } + { // negative value is too small -> -0 + const char* s = "-1e-9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == F(-0.0)); + } + } +}; + +template +struct test_general { + void operator()() { + std::from_chars_result r; + F x = 0.25; + + // *** Failures + + { // Starts with invalid character + std::array s = {' ', '1'}; + for (auto c : "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") { + s[0] = c; + r = std::from_chars(s.data(), s.data() + s.size(), x); + + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s.data()); + assert(x == F(0.25)); + } + } + + // *** Success + + { // number followed by non-numeric values + const char* s = "001x"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.0)); + } + { // no leading digit + const char* s = ".5e0"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(0.5)); + } + { // negative sign and no leading digit + const char* s = "-.5e0"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 5); + assert(x == F(-0.5)); + } + { // no leading digit + const char* s = ".5"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 2); + assert(x == F(0.5)); + } + { // negative sign and no leading digit + const char* s = "-.5"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(-0.5)); + } + { // double deciamal point + const char* s = "1.25.78"; + + // This number is halfway between two float values. + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { // exponenent no sign + const char* s = "1.5e10"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.5e10)); + } + { // exponenent capitalized no sign + const char* s = "1.5E10"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.5e10)); + } + { // exponenent + sign + const char* s = "1.5e+10"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(1.5e10)); + } + { // exponenent - sign + const char* s = "1.5e-10"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(1.5e-10)); + } + { // Exponent no number + const char* s = "1.5e"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { // Exponent sign no number + { + const char* s = "1.5e+"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { + const char* s = "1.5e-"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + } + { // Exponent with whitespace + { + const char* s = "1.5e +1"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { + const char* s = "1.5e+ 1"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { + const char* s = "1.5e -1"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + { + const char* s = "1.5e- 1"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.5)); + } + } + { // exponent double sign + { + const char* s = "1.25e++12"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { + const char* s = "1.25e+-12"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { + const char* s = "1.25e-+12"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + { + const char* s = "1.25e--12"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(1.25)); + } + } + { // exponent hex prefix -> e0 + const char* s = "1.25e0x12"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.25)); + } + { // double exponent + const char* s = "1.25e0e12"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(1.25)); + } + { // This number is halfway between two float values. + const char* s = "20040229"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 8); + assert(x == F(20040229)); + } + { // Shifting mantissa exponent and no exponent + const char* s = "123.456"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(1.23456e2)); + } + { // Shifting mantissa exponent and an exponent + const char* s = "123.456e3"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 9); + assert(x == F(1.23456e5)); + } + { // Mantissa overflow + { + const char* s = "0.111111111111111111111111111111111111111111"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(0.111111111111111111111111111111111111111111)); + } + { + const char* s = "111111111111.111111111111111111111111111111111111111111"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(111111111111.111111111111111111111111111111111111111111)); + } + } + { // Negative value + const char* s = "-0.25"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(-0.25)); + } + { // value is too big -> +inf + const char* s = "1e9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == std::numeric_limits::infinity()); + } + { // negative value is too big -> -inf + const char* s = "-1e9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == -std::numeric_limits::infinity()); + } + { // value is too small -> 0 + const char* s = "1e-9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == F(0.0)); + } + { // negative value is too small -> -0 + const char* s = "-1e-9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == F(-0.0)); + } + } +}; + +template +struct test_hex { + void operator()() { + std::from_chars_result r; + F x = 0.25; + + // *** Failures + + { // Starts with invalid character + std::array s = {' ', '1', 'e', '0'}; + for (auto c : "ghijklmnopqrstuvwxyz" + "GHIJKLMNOPQRSTUVWXYZ" + "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") { + s[0] = c; + r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::hex); + + assert(r.ec == std::errc::invalid_argument); + assert(r.ptr == s.data()); + assert(x == F(0.25)); + } + } + + // *** Success + + { // number followed by non-numeric values + const char* s = "001x"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(1.0)); + } + { // no leading digit + const char* s = ".5p0"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(0x0.5p0)); + } + { // negative sign and no leading digit + const char* s = "-.5p0"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 5); + assert(x == F(-0x0.5p0)); + } + { // no leading digit + const char* s = ".5"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 2); + assert(x == F(0x0.5p0)); + } + { // negative sign and no leading digit + const char* s = "-.5"; + + // the expected form of the subject sequence is a nonempty sequence of + // decimal digits optionally containing a decimal-point character, then + // an optional exponent part as defined in 6.4.4.3, excluding any digit + // separators (6.4.4.2); (C23 7.24.1.5) + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(-0x0.5p0)); + } + { // double deciamal point + const char* s = "1.25.78"; + + // This number is halfway between two float values. + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(0x1.25p0)); + } + { // exponenent no sign + const char* s = "1.5p10"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(0x1.5p10)); + } + { // exponenent capitalized no sign + const char* s = "1.5P10"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(0x1.5p10)); + } + { // exponenent + sign + const char* s = "1.5p+10"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(0x1.5p10)); + } + { // exponenent - sign + const char* s = "1.5p-10"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(0x1.5p-10)); + } + { // Exponent no number + const char* s = "1.5p"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(0x1.5p0)); + } + { // Exponent sign no number + { + const char* s = "1.5p+"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(0x1.5p0)); + } + { + const char* s = "1.5p-"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(0x1.5p0)); + } + } + { // Exponent with whitespace + { + const char* s = "1.5p +1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(0x1.5p0)); + } + { + const char* s = "1.5p+ 1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(0x1.5p0)); + } + { + const char* s = "1.5p -1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(0x1.5p0)); + } + { + const char* s = "1.5p- 1"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == F(0x1.5p0)); + } + } + { // Exponent double sign + { + const char* s = "1.25p++12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(0x1.25p0)); + } + { + const char* s = "1.25p+-12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(0x1.25p0)); + } + { + const char* s = "1.25p-+12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(0x1.25p0)); + } + { + const char* s = "1.25p--12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 4); + assert(x == F(0x1.25p0)); + } + } + { // exponent hex prefix -> p0 + const char* s = "1.25p0x12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(0x1.25p0)); + } + { // double exponent + const char* s = "1.25p0p12"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 6); + assert(x == F(0x1.25p0)); + } + { // This number is halfway between two float values. + const char* s = "131CA25"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(0x131CA25p0)); + } + { // Shifting mantissa exponent and no exponent + const char* s = "123.456"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 7); + assert(x == F(0x123.456p0)); + } + { // Shifting mantissa exponent and an exponent + const char* s = "123.456p3"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 9); + assert(x == F(0x123.456p3)); + } + { // Mantissa overflow + { + const char* s = "0.111111111111111111111111111111111111111111"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(0x0.111111111111111111111111111111111111111111p0)); + } + { + const char* s = "111111111111.111111111111111111111111111111111111111111"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(0x111111111111.111111111111111111111111111111111111111111p0)); + } + } + { // Negative value + const char* s = "-0.25"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc{}); + assert(r.ptr == s + std::strlen(s)); + assert(x == F(-0x0.25p0)); + } + { // value is too big -> +inf + const char* s = "1p9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == std::numeric_limits::infinity()); + } + { // negative value is too big -> -inf + const char* s = "-1p9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == -std::numeric_limits::infinity()); + } + { // value is too small -> 0 + const char* s = "1p-9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == F(0.0)); + } + { // negative value is too small -> -0 + const char* s = "-1p-9999999999999999999999999999999999999999"; + + r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex); + assert(r.ec == std::errc::result_out_of_range); + assert(r.ptr == s + strlen(s)); + assert(x == F(-0.0)); + } + } +}; + +// The test +// test/std/utilities/charconv/charconv.msvc/test.cpp +// uses random values. This tests contains errors found by this test. +void test_random_errors() { + { + const char* s = "4.219902180869891e-2788"; + const char* last = s + std::strlen(s) - 1; + + // last + 1 contains a digit. When that value is parsed the exponent is + // e-2788 which returns std::errc::result_out_of_range and the value 0. + // the proper exponent is e-278, which can be represented by a double. + + double value = 0.25; + std::from_chars_result result = std::from_chars(s, last, value); + + assert(result.ec == std::errc{}); + assert(result.ptr == last); + assert(value == 4.219902180869891e-278); + } + { + const char* s = "7.411412e-39U"; + const char* last = s + std::strlen(s) - 1; + + float value = 0.25; + std::from_chars_result result = std::from_chars(s, last, value); + + assert(result.ec == std::errc{}); + assert(result.ptr == last); + assert(value == 7.411412e-39F); + } +} + +int main(int, char**) { + run(all_floats); + run(all_floats); + run(all_floats); + run(all_floats); + + run(all_floats); + + test_random_errors(); + + return 0; +} diff --git a/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp b/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp index 30ee9adcd74bf..ace6d46b879b0 100644 --- a/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp +++ b/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp @@ -45,6 +45,7 @@ #include "float_hex_precision_to_chars_test_cases.hpp" #include "float_scientific_precision_to_chars_test_cases.hpp" #include "float_to_chars_test_cases.hpp" +#include "floating_point_test_cases.hpp" using namespace std; @@ -589,8 +590,8 @@ void test_floating_prefix(const conditional_t(val) == bits, "round-trip", bits); -#endif +#endif // TEST_HAS_FROM_CHARS_FLOATING_POINT } { @@ -656,8 +656,8 @@ void test_floating_hex_prefix(const conditional_t(val) == bits, "(hex) round-trip", bits); -#endif +#endif // TEST_HAS_FROM_CHARS_FLOATING_POINT } } @@ -786,8 +786,7 @@ void test_floating_prefixes(mt19937_64& mt64) { } } -// TODO Enable once std::from_chars has floating point support. -#if 0 +#ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT template void test_floating_from_chars(const chars_format fmt) { test_from_chars("", fmt, 0, inv_arg); // no characters @@ -855,11 +854,13 @@ void test_floating_from_chars(const chars_format fmt) { // The UCRT considers indeterminate NaN to be negative quiet NaN with no payload bits set. // It parses "nan(ind)" and "-nan(ind)" identically. +# ifdef _MSC_VER test_from_chars("nan(InD)", fmt, 8, errc{}, -qnan); test_from_chars("-nan(InD)", fmt, 9, errc{}, -qnan); test_from_chars("nan(SnAn)", fmt, 9, errc{}, nullopt, TestFromCharsMode::SignalingNaN); test_from_chars("-nan(SnAn)", fmt, 10, errc{}, nullopt, TestFromCharsMode::SignalingNaN); +# endif switch (fmt) { case chars_format::general: @@ -941,7 +942,7 @@ void test_floating_from_chars(const chars_format fmt) { break; } } -#endif +#endif // TEST_HAS_FROM_CHARS_FLOATING_POINT template void test_floating_to_chars( @@ -953,13 +954,11 @@ void test_floating_to_chars( void all_floating_tests(mt19937_64& mt64) { test_floating_prefixes(mt64); -// TODO Enable once std::from_chars has floating point support. -#if 0 +#ifdef TEST_HAS_FROM_CHARS_FLOATING_POINT for (const auto& fmt : {chars_format::general, chars_format::scientific, chars_format::fixed, chars_format::hex}) { test_floating_from_chars(fmt); test_floating_from_chars(fmt); } - // Test rounding. // See float_from_chars_test_cases.hpp in this directory. @@ -993,7 +992,8 @@ void all_floating_tests(mt19937_64& mt64) { for (const auto& p : floating_point_test_cases_double) { test_from_chars(p.first, chars_format::general, strlen(p.first), errc{}, _Bit_cast(p.second)); } -#endif +#endif // TEST_HAS_FROM_CHARS_FLOATING_POINT + // See float_to_chars_test_cases.hpp in this directory. for (const auto& t : float_to_chars_test_cases) { if (t.fmt == chars_format{}) { diff --git a/libcxx/test/std/utilities/charconv/charconv.msvc/test.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.msvc/test.pass.cpp index 09ef70ea9924e..c294a40ce71ce 100644 --- a/libcxx/test/std/utilities/charconv/charconv.msvc/test.pass.cpp +++ b/libcxx/test/std/utilities/charconv/charconv.msvc/test.pass.cpp @@ -8,6 +8,9 @@ // UNSUPPORTED: c++03, c++11, c++14 +// TODO Investigate why this fails +// UNSUPPORTED: windows + // to_chars requires functions in the dylib that have not been introduced in older // versions of the dylib on macOS. // XFAIL: availability-fp_to_chars-missing @@ -22,6 +25,7 @@ // #include +#include "test_macros.h" // Work-around for sprintf_s's usage in the Microsoft tests. #ifndef _WIN32 diff --git a/libcxx/test/support/charconv_test_helpers.h b/libcxx/test/support/charconv_test_helpers.h index f5fbedbeb0dcd..fcae09478457b 100644 --- a/libcxx/test/support/charconv_test_helpers.h +++ b/libcxx/test/support/charconv_test_helpers.h @@ -317,6 +317,8 @@ auto all_unsigned = type_list< >(); auto integrals = concat(all_signed, all_unsigned); +auto all_floats = type_list< float, double >(); //TODO: Add long double + template