Importing rustc-1.56.0
Change-Id: I98941481270706fa55f8fb2cb91686ae3bd30f38
diff --git a/src/llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/src/llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp
index a412012..75100fd 100644
--- a/src/llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/src/llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -551,7 +551,9 @@
llvm::Optional<bool> SwiftInferImportAsMember = {llvm::None};
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void dump() /*const*/;
+#endif
};
} // namespace
@@ -571,10 +573,12 @@
} // namespace yaml
} // namespace llvm
-void Module::dump() {
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void Module::dump() {
llvm::yaml::Output OS(llvm::errs());
OS << *this;
}
+#endif
namespace {
bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag,
diff --git a/src/llvm-project/clang/lib/ARCMigrate/FileRemapper.cpp b/src/llvm-project/clang/lib/ARCMigrate/FileRemapper.cpp
index f536af1..92027fe 100644
--- a/src/llvm-project/clang/lib/ARCMigrate/FileRemapper.cpp
+++ b/src/llvm-project/clang/lib/ARCMigrate/FileRemapper.cpp
@@ -63,7 +63,7 @@
std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
- llvm::MemoryBuffer::getFile(infoFile);
+ llvm::MemoryBuffer::getFile(infoFile, /*IsText=*/true);
if (!fileBuf)
return report("Error opening file: " + infoFile, Diag);
@@ -121,7 +121,7 @@
std::error_code EC;
std::string infoFile = std::string(outputPath);
- llvm::raw_fd_ostream infoOut(infoFile, EC, llvm::sys::fs::OF_None);
+ llvm::raw_fd_ostream infoOut(infoFile, EC, llvm::sys::fs::OF_Text);
if (EC)
return report(EC.message(), Diag);
@@ -142,9 +142,10 @@
SmallString<64> tempPath;
int fd;
- if (fs::createTemporaryFile(path::filename(origFE->getName()),
- path::extension(origFE->getName()).drop_front(), fd,
- tempPath))
+ if (fs::createTemporaryFile(
+ path::filename(origFE->getName()),
+ path::extension(origFE->getName()).drop_front(), fd, tempPath,
+ llvm::sys::fs::OF_Text))
return report("Could not create file: " + tempPath.str(), Diag);
llvm::raw_fd_ostream newOut(fd, /*shouldClose=*/true);
diff --git a/src/llvm-project/clang/lib/ARCMigrate/ObjCMT.cpp b/src/llvm-project/clang/lib/ARCMigrate/ObjCMT.cpp
index 68a51a4..c8069b5 100644
--- a/src/llvm-project/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/src/llvm-project/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -613,7 +613,7 @@
continue;
HasAtleastOneRequiredProperty = true;
DeclContext::lookup_result R = IDecl->lookup(Property->getDeclName());
- if (R.size() == 0) {
+ if (R.empty()) {
// Relax the rule and look into class's implementation for a synthesize
// or dynamic declaration. Class is implementing a property coming from
// another protocol. This still makes the target protocol as conforming.
@@ -621,14 +621,12 @@
Property->getDeclName().getAsIdentifierInfo(),
Property->getQueryKind()))
return false;
- }
- else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
- if ((ClassProperty->getPropertyAttributes()
- != Property->getPropertyAttributes()) ||
- !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
- return false;
- }
- else
+ } else if (auto *ClassProperty = R.find_first<ObjCPropertyDecl>()) {
+ if ((ClassProperty->getPropertyAttributes() !=
+ Property->getPropertyAttributes()) ||
+ !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
+ return false;
+ } else
return false;
}
@@ -645,12 +643,12 @@
if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
continue;
DeclContext::lookup_result R = ImpDecl->lookup(MD->getDeclName());
- if (R.size() == 0)
+ if (R.empty())
return false;
bool match = false;
HasAtleastOneRequiredMethod = true;
- for (unsigned I = 0, N = R.size(); I != N; ++I)
- if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
+ for (NamedDecl *ND : R)
+ if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(ND))
if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
match = true;
break;
diff --git a/src/llvm-project/clang/lib/ARCMigrate/PlistReporter.cpp b/src/llvm-project/clang/lib/ARCMigrate/PlistReporter.cpp
index d01563b..c233d6b 100644
--- a/src/llvm-project/clang/lib/ARCMigrate/PlistReporter.cpp
+++ b/src/llvm-project/clang/lib/ARCMigrate/PlistReporter.cpp
@@ -56,7 +56,7 @@
}
std::error_code EC;
- llvm::raw_fd_ostream o(outPath, EC, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream o(outPath, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
llvm::errs() << "error: could not create file: " << outPath << '\n';
return;
diff --git a/src/llvm-project/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/src/llvm-project/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index 5d0cfb8..e9c21b8 100644
--- a/src/llvm-project/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/src/llvm-project/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -52,7 +52,7 @@
if (AfterMacroLoc == SemiLoc)
return true;
- int RelOffs = 0;
+ SourceLocation::IntTy RelOffs = 0;
if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs))
return false;
if (RelOffs < 0)
diff --git a/src/llvm-project/clang/lib/AST/ASTContext.cpp b/src/llvm-project/clang/lib/AST/ASTContext.cpp
index cb7f00a..fdba204 100644
--- a/src/llvm-project/clang/lib/AST/ASTContext.cpp
+++ b/src/llvm-project/clang/lib/AST/ASTContext.cpp
@@ -56,8 +56,8 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/Module.h"
+#include "clang/Basic/NoSanitizeList.h"
#include "clang/Basic/ObjCRuntime.h"
-#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
@@ -84,6 +84,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -879,10 +880,15 @@
return CanonTTP;
}
+TargetCXXABI::Kind ASTContext::getCXXABIKind() const {
+ auto Kind = getTargetInfo().getCXXABI().getKind();
+ return getLangOpts().CXXABI.getValueOr(Kind);
+}
+
CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
if (!LangOpts.CPlusPlus) return nullptr;
- switch (T.getCXXABI().getKind()) {
+ switch (getCXXABIKind()) {
case TargetCXXABI::AppleARM64:
case TargetCXXABI::Fuchsia:
case TargetCXXABI::GenericARM: // Same as Itanium at this level
@@ -930,6 +936,11 @@
7, // cuda_device
8, // cuda_constant
9, // cuda_shared
+ 1, // sycl_global
+ 5, // sycl_global_device
+ 6, // sycl_global_host
+ 3, // sycl_local
+ 0, // sycl_private
10, // ptr32_sptr
11, // ptr32_uptr
12 // ptr64
@@ -955,23 +966,22 @@
ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
IdentifierTable &idents, SelectorTable &sels,
- Builtin::Context &builtins)
+ Builtin::Context &builtins, TranslationUnitKind TUKind)
: ConstantArrayTypes(this_()), FunctionProtoTypes(this_()),
TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()),
SubstTemplateTemplateParmPacks(this_()),
CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts),
- SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
+ NoSanitizeL(new NoSanitizeList(LangOpts.NoSanitizeFiles, SM)),
XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles,
LangOpts.XRayNeverInstrumentFiles,
LangOpts.XRayAttrListFiles, SM)),
ProfList(new ProfileList(LangOpts.ProfileListFiles, SM)),
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
- BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM),
- CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
+ BuiltinInfo(builtins), TUKind(TUKind), DeclarationNames(*this),
+ Comments(SM), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts),
CompCategories(this_()), LastSDM(nullptr, 0) {
- TUDecl = TranslationUnitDecl::Create(*this);
- TraversalScope = {TUDecl};
+ addTranslationUnitDecl();
}
ASTContext::~ASTContext() {
@@ -1185,9 +1195,10 @@
BuiltinTemplateDecl *
ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
const IdentifierInfo *II) const {
- auto *BuiltinTemplate = BuiltinTemplateDecl::Create(*this, TUDecl, II, BTK);
+ auto *BuiltinTemplate =
+ BuiltinTemplateDecl::Create(*this, getTranslationUnitDecl(), II, BTK);
BuiltinTemplate->setImplicit();
- TUDecl->addDecl(BuiltinTemplate);
+ getTranslationUnitDecl()->addDecl(BuiltinTemplate);
return BuiltinTemplate;
}
@@ -1436,6 +1447,12 @@
#include "clang/Basic/PPCTypes.def"
}
+ if (Target.hasRISCVVTypes()) {
+#define RVV_TYPE(Name, Id, SingletonId) \
+ InitBuiltinType(SingletonId, BuiltinType::Id);
+#include "clang/Basic/RISCVVTypes.def"
+ }
+
// Builtin type for __objc_yes and __objc_no
ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ?
SignedCharTy : BoolTy);
@@ -1445,7 +1462,7 @@
ObjCSuperType = QualType();
// void * type
- if (LangOpts.OpenCLVersion >= 200) {
+ if (LangOpts.OpenCLGenericAddressSpace) {
auto Q = VoidTy.getQualifiers();
Q.setAddressSpace(LangAS::opencl_generic);
VoidPtrTy = getPointerType(getCanonicalType(
@@ -1468,7 +1485,7 @@
// MSVC predeclares struct _GUID, and we need it to create MSGuidDecls.
if (LangOpts.MicrosoftExt || LangOpts.Borland) {
MSGuidTagDecl = buildImplicitRecord("_GUID");
- TUDecl->addDecl(MSGuidTagDecl);
+ getTranslationUnitDecl()->addDecl(MSGuidTagDecl);
}
}
@@ -1554,6 +1571,21 @@
InstantiatedFromUsingDecl[Inst] = Pattern;
}
+UsingEnumDecl *
+ASTContext::getInstantiatedFromUsingEnumDecl(UsingEnumDecl *UUD) {
+ auto Pos = InstantiatedFromUsingEnumDecl.find(UUD);
+ if (Pos == InstantiatedFromUsingEnumDecl.end())
+ return nullptr;
+
+ return Pos->second;
+}
+
+void ASTContext::setInstantiatedFromUsingEnumDecl(UsingEnumDecl *Inst,
+ UsingEnumDecl *Pattern) {
+ assert(!InstantiatedFromUsingEnumDecl[Inst] && "pattern already exists");
+ InstantiatedFromUsingEnumDecl[Inst] = Pattern;
+}
+
UsingShadowDecl *
ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) {
llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos
@@ -1776,6 +1808,13 @@
}
}
+ // Some targets have hard limitation on the maximum requestable alignment in
+ // aligned attribute for static variables.
+ const unsigned MaxAlignedAttr = getTargetInfo().getMaxAlignedAttribute();
+ const auto *VD = dyn_cast<VarDecl>(D);
+ if (MaxAlignedAttr && VD && VD->getStorageClass() == SC_Static)
+ Align = std::min(Align, MaxAlignedAttr);
+
return toCharUnitsFromBits(Align);
}
@@ -2167,6 +2206,18 @@
Align = Size; \
break;
#include "clang/Basic/PPCTypes.def"
+#define RVV_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, NF, IsSigned, \
+ IsFP) \
+ case BuiltinType::Id: \
+ Width = 0; \
+ Align = ElBits; \
+ break;
+#define RVV_PREDICATE_TYPE(Name, Id, SingletonId, ElKind) \
+ case BuiltinType::Id: \
+ Width = 0; \
+ Align = 8; \
+ break;
+#include "clang/Basic/RISCVVTypes.def"
}
break;
case Type::ObjCObjectPointer:
@@ -2422,7 +2473,7 @@
// The preferred alignment of member pointers is that of a pointer.
if (T->isMemberPointerType())
return getPreferredTypeAlign(getPointerDiffType().getTypePtr());
-
+
if (!Target->allowsLargerPreferedTypeAlignment())
return ABIAlign;
@@ -3811,6 +3862,19 @@
return SVE_ELTTY(BFloat16Ty, 8, 3);
case BuiltinType::SveBFloat16x4:
return SVE_ELTTY(BFloat16Ty, 8, 4);
+#define RVV_VECTOR_TYPE_INT(Name, Id, SingletonId, NumEls, ElBits, NF, \
+ IsSigned) \
+ case BuiltinType::Id: \
+ return {getIntTypeForBitwidth(ElBits, IsSigned), \
+ llvm::ElementCount::getScalable(NumEls), NF};
+#define RVV_VECTOR_TYPE_FLOAT(Name, Id, SingletonId, NumEls, ElBits, NF) \
+ case BuiltinType::Id: \
+ return {ElBits == 16 ? Float16Ty : (ElBits == 32 ? FloatTy : DoubleTy), \
+ llvm::ElementCount::getScalable(NumEls), NF};
+#define RVV_PREDICATE_TYPE(Name, Id, SingletonId, NumEls) \
+ case BuiltinType::Id: \
+ return {BoolTy, llvm::ElementCount::getScalable(NumEls), 1};
+#include "clang/Basic/RISCVVTypes.def"
}
}
@@ -3837,6 +3901,20 @@
if (EltTy->isBooleanType() && NumElts == NumEls) \
return SingletonId;
#include "clang/Basic/AArch64SVEACLETypes.def"
+ } else if (Target->hasRISCVVTypes()) {
+ uint64_t EltTySize = getTypeSize(EltTy);
+#define RVV_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, NF, IsSigned, \
+ IsFP) \
+ if (!EltTy->isBooleanType() && \
+ ((EltTy->hasIntegerRepresentation() && \
+ EltTy->hasSignedIntegerRepresentation() == IsSigned) || \
+ (EltTy->hasFloatingRepresentation() && IsFP)) && \
+ EltTySize == ElBits && NumElts == NumEls) \
+ return SingletonId;
+#define RVV_PREDICATE_TYPE(Name, Id, SingletonId, NumEls) \
+ if (EltTy->isBooleanType() && NumElts == NumEls) \
+ return SingletonId;
+#include "clang/Basic/RISCVVTypes.def"
}
return QualType();
}
@@ -5705,29 +5783,29 @@
/// Attempt to unwrap two types that may both be array types with the same bound
/// (or both be array types of unknown bound) for the purpose of comparing the
/// cv-decomposition of two types per C++ [conv.qual].
-bool ASTContext::UnwrapSimilarArrayTypes(QualType &T1, QualType &T2) {
- bool UnwrappedAny = false;
+void ASTContext::UnwrapSimilarArrayTypes(QualType &T1, QualType &T2) {
while (true) {
auto *AT1 = getAsArrayType(T1);
- if (!AT1) return UnwrappedAny;
+ if (!AT1)
+ return;
auto *AT2 = getAsArrayType(T2);
- if (!AT2) return UnwrappedAny;
+ if (!AT2)
+ return;
// If we don't have two array types with the same constant bound nor two
// incomplete array types, we've unwrapped everything we can.
if (auto *CAT1 = dyn_cast<ConstantArrayType>(AT1)) {
auto *CAT2 = dyn_cast<ConstantArrayType>(AT2);
if (!CAT2 || CAT1->getSize() != CAT2->getSize())
- return UnwrappedAny;
+ return;
} else if (!isa<IncompleteArrayType>(AT1) ||
!isa<IncompleteArrayType>(AT2)) {
- return UnwrappedAny;
+ return;
}
T1 = AT1->getElementType();
T2 = AT2->getElementType();
- UnwrappedAny = true;
}
}
@@ -5840,9 +5918,8 @@
} else {
DName = DeclarationNames.getCXXOperatorName(DTN->getOperator());
// DNInfo work in progress: FIXME: source locations?
- DeclarationNameLoc DNLoc;
- DNLoc.CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
- DNLoc.CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
+ DeclarationNameLoc DNLoc =
+ DeclarationNameLoc::makeCXXOperatorNameLoc(SourceRange());
return DeclarationNameInfo(DName, NameLoc, DNLoc);
}
}
@@ -5989,9 +6066,11 @@
NNS->getAsNamespaceAlias()->getNamespace()
->getOriginalNamespace());
+ // The difference between TypeSpec and TypeSpecWithTemplate is that the
+ // latter will have the 'template' keyword when printed.
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
- QualType T = getCanonicalType(QualType(NNS->getAsType(), 0));
+ const Type *T = getCanonicalType(NNS->getAsType());
// If we have some kind of dependent-named type (e.g., "typename T::type"),
// break it apart into its prefix and identifier, then reconsititute those
@@ -6001,14 +6080,16 @@
// typedef typename T::type T1;
// typedef typename T1::type T2;
if (const auto *DNT = T->getAs<DependentNameType>())
- return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
- const_cast<IdentifierInfo *>(DNT->getIdentifier()));
+ return NestedNameSpecifier::Create(
+ *this, DNT->getQualifier(),
+ const_cast<IdentifierInfo *>(DNT->getIdentifier()));
+ if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>())
+ return NestedNameSpecifier::Create(*this, DTST->getQualifier(), true,
+ const_cast<Type *>(T));
- // Otherwise, just canonicalize the type, and force it to be a TypeSpec.
- // FIXME: Why are TypeSpec and TypeSpecWithTemplate distinct in the
- // first place?
+ // TODO: Set 'Template' parameter to true for other template types.
return NestedNameSpecifier::Create(*this, nullptr, false,
- const_cast<Type *>(T.getTypePtr()));
+ const_cast<Type *>(T));
}
case NestedNameSpecifier::Global:
@@ -6545,7 +6626,7 @@
QualType ASTContext::getObjCSuperType() const {
if (ObjCSuperType.isNull()) {
RecordDecl *ObjCSuperTypeDecl = buildImplicitRecord("objc_super");
- TUDecl->addDecl(ObjCSuperTypeDecl);
+ getTranslationUnitDecl()->addDecl(ObjCSuperTypeDecl);
ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl);
}
return ObjCSuperType;
@@ -7213,13 +7294,15 @@
#define SVE_TYPE(Name, Id, SingletonId) \
case BuiltinType::Id:
#include "clang/Basic/AArch64SVEACLETypes.def"
- {
- DiagnosticsEngine &Diags = C->getDiagnostics();
- unsigned DiagID = Diags.getCustomDiagID(
- DiagnosticsEngine::Error, "cannot yet @encode type %0");
- Diags.Report(DiagID) << BT->getName(C->getPrintingPolicy());
- return ' ';
- }
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
+ {
+ DiagnosticsEngine &Diags = C->getDiagnostics();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot yet @encode type %0");
+ Diags.Report(DiagID) << BT->getName(C->getPrintingPolicy());
+ return ' ';
+ }
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
@@ -7306,6 +7389,40 @@
S += llvm::utostr(FD->getBitWidthValue(*Ctx));
}
+// Helper function for determining whether the encoded type string would include
+// a template specialization type.
+static bool hasTemplateSpecializationInEncodedString(const Type *T,
+ bool VisitBasesAndFields) {
+ T = T->getBaseElementTypeUnsafe();
+
+ if (auto *PT = T->getAs<PointerType>())
+ return hasTemplateSpecializationInEncodedString(
+ PT->getPointeeType().getTypePtr(), false);
+
+ auto *CXXRD = T->getAsCXXRecordDecl();
+
+ if (!CXXRD)
+ return false;
+
+ if (isa<ClassTemplateSpecializationDecl>(CXXRD))
+ return true;
+
+ if (!CXXRD->hasDefinition() || !VisitBasesAndFields)
+ return false;
+
+ for (auto B : CXXRD->bases())
+ if (hasTemplateSpecializationInEncodedString(B.getType().getTypePtr(),
+ true))
+ return true;
+
+ for (auto *FD : CXXRD->fields())
+ if (hasTemplateSpecializationInEncodedString(FD->getType().getTypePtr(),
+ true))
+ return true;
+
+ return false;
+}
+
// FIXME: Use SmallString for accumulating string.
void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
const ObjCEncOptions Options,
@@ -7398,6 +7515,15 @@
S += '@';
return;
}
+ // If the encoded string for the class includes template names, just emit
+ // "^v" for pointers to the class.
+ if (getLangOpts().CPlusPlus &&
+ (!getLangOpts().EncodeCXXClassTemplateSpec &&
+ hasTemplateSpecializationInEncodedString(
+ RTy, Options.ExpandPointedToStructures()))) {
+ S += "^v";
+ return;
+ }
// fall through...
}
S += '^';
@@ -7876,19 +8002,21 @@
static TypedefDecl *
CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) {
- // struct __va_list
RecordDecl *VaListTagDecl = Context->buildImplicitRecord("__va_list");
- if (Context->getLangOpts().CPlusPlus) {
- // namespace std { struct __va_list {
- NamespaceDecl *NS;
- NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
- Context->getTranslationUnitDecl(),
- /*Inline*/ false, SourceLocation(),
- SourceLocation(), &Context->Idents.get("std"),
- /*PrevDecl*/ nullptr);
- NS->setImplicit();
- VaListTagDecl->setDeclContext(NS);
- }
+ // namespace std { struct __va_list {
+ // Note that we create the namespace even in C. This is intentional so that
+ // the type is consistent between C and C++, which is important in cases where
+ // the types need to match between translation units (e.g. with
+ // -fsanitize=cfi-icall). Ideally we wouldn't have created this namespace at
+ // all, but it's now part of the ABI (e.g. in mangled names), so we can't
+ // change it.
+ auto *NS = NamespaceDecl::Create(
+ const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(),
+ /*Inline*/ false, SourceLocation(), SourceLocation(),
+ &Context->Idents.get("std"),
+ /*PrevDecl*/ nullptr);
+ NS->setImplicit();
+ VaListTagDecl->setDeclContext(NS);
VaListTagDecl->startDefinition();
@@ -8546,6 +8674,14 @@
return false;
}
+/// getSVETypeSize - Return SVE vector or predicate register size.
+static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty) {
+ assert(Ty->isVLSTBuiltinType() && "Invalid SVE Type");
+ return Ty->getKind() == BuiltinType::SveBool
+ ? Context.getLangOpts().ArmSveVectorBits / Context.getCharWidth()
+ : Context.getLangOpts().ArmSveVectorBits;
+}
+
bool ASTContext::areCompatibleSveTypes(QualType FirstType,
QualType SecondType) {
assert(((FirstType->isSizelessBuiltinType() && SecondType->isVectorType()) ||
@@ -8563,7 +8699,7 @@
return VT->getElementType().getCanonicalType() ==
FirstType->getSveEltType(*this);
else if (VT->getVectorKind() == VectorType::GenericVector)
- return getTypeSize(SecondType) == getLangOpts().ArmSveVectorBits &&
+ return getTypeSize(SecondType) == getSVETypeSize(*this, BT) &&
hasSameType(VT->getElementType(),
getBuiltinVectorTypeInfo(BT).ElementType);
}
@@ -8582,7 +8718,8 @@
"Expected SVE builtin type and vector type!");
auto IsLaxCompatible = [this](QualType FirstType, QualType SecondType) {
- if (!FirstType->getAs<BuiltinType>())
+ const auto *BT = FirstType->getAs<BuiltinType>();
+ if (!BT)
return false;
const auto *VecTy = SecondType->getAs<VectorType>();
@@ -8592,13 +8729,19 @@
const LangOptions::LaxVectorConversionKind LVCKind =
getLangOpts().getLaxVectorConversions();
+ // Can not convert between sve predicates and sve vectors because of
+ // different size.
+ if (BT->getKind() == BuiltinType::SveBool &&
+ VecTy->getVectorKind() == VectorType::SveFixedLengthDataVector)
+ return false;
+
// If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion.
// "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly
// converts to VLAT and VLAT implicitly converts to GNUT."
// ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and
// predicates.
if (VecTy->getVectorKind() == VectorType::GenericVector &&
- getTypeSize(SecondType) != getLangOpts().ArmSveVectorBits)
+ getTypeSize(SecondType) != getSVETypeSize(*this, BT))
return false;
// If -flax-vector-conversions=all is specified, the types are
@@ -10000,7 +10143,12 @@
return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()),
VTy->getNumElements(), VTy->getVectorKind());
- // For enums, we return the unsigned version of the base type.
+ // For _ExtInt, return an unsigned _ExtInt with same width.
+ if (const auto *EITy = T->getAs<ExtIntType>())
+ return getExtIntType(/*IsUnsigned=*/true, EITy->getNumBits());
+
+ // For enums, get the underlying integer type of the enum, and let the general
+ // integer type signchanging code handle it.
if (const auto *ETy = T->getAs<EnumType>())
T = ETy->getDecl()->getIntegerType();
@@ -10053,6 +10201,74 @@
}
}
+QualType ASTContext::getCorrespondingSignedType(QualType T) const {
+ assert((T->hasUnsignedIntegerRepresentation() ||
+ T->isUnsignedFixedPointType()) &&
+ "Unexpected type");
+
+ // Turn <4 x unsigned int> -> <4 x signed int>
+ if (const auto *VTy = T->getAs<VectorType>())
+ return getVectorType(getCorrespondingSignedType(VTy->getElementType()),
+ VTy->getNumElements(), VTy->getVectorKind());
+
+ // For _ExtInt, return a signed _ExtInt with same width.
+ if (const auto *EITy = T->getAs<ExtIntType>())
+ return getExtIntType(/*IsUnsigned=*/false, EITy->getNumBits());
+
+ // For enums, get the underlying integer type of the enum, and let the general
+ // integer type signchanging code handle it.
+ if (const auto *ETy = T->getAs<EnumType>())
+ T = ETy->getDecl()->getIntegerType();
+
+ switch (T->castAs<BuiltinType>()->getKind()) {
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ return SignedCharTy;
+ case BuiltinType::UShort:
+ return ShortTy;
+ case BuiltinType::UInt:
+ return IntTy;
+ case BuiltinType::ULong:
+ return LongTy;
+ case BuiltinType::ULongLong:
+ return LongLongTy;
+ case BuiltinType::UInt128:
+ return Int128Ty;
+ // wchar_t is special. It is either unsigned or not, but when it's unsigned,
+ // there's no matching "signed wchar_t". Therefore we return the signed
+ // version of it's underlying type instead.
+ case BuiltinType::WChar_U:
+ return getSignedWCharType();
+
+ case BuiltinType::UShortAccum:
+ return ShortAccumTy;
+ case BuiltinType::UAccum:
+ return AccumTy;
+ case BuiltinType::ULongAccum:
+ return LongAccumTy;
+ case BuiltinType::SatUShortAccum:
+ return SatShortAccumTy;
+ case BuiltinType::SatUAccum:
+ return SatAccumTy;
+ case BuiltinType::SatULongAccum:
+ return SatLongAccumTy;
+ case BuiltinType::UShortFract:
+ return ShortFractTy;
+ case BuiltinType::UFract:
+ return FractTy;
+ case BuiltinType::ULongFract:
+ return LongFractTy;
+ case BuiltinType::SatUShortFract:
+ return SatShortFractTy;
+ case BuiltinType::SatUFract:
+ return SatFractTy;
+ case BuiltinType::SatULongFract:
+ return SatLongFractTy;
+ default:
+ llvm_unreachable("Unexpected unsigned integer or fixed point type");
+ }
+}
+
ASTMutationListener::~ASTMutationListener() = default;
void ASTMutationListener::DeducedReturnType(const FunctionDecl *FD,
@@ -10173,6 +10389,11 @@
// Read the base type.
switch (*Str++) {
default: llvm_unreachable("Unknown builtin type letter!");
+ case 'x':
+ assert(HowLong == 0 && !Signed && !Unsigned &&
+ "Bad modifiers used with 'x'!");
+ Type = Context.Float16Ty;
+ break;
case 'y':
assert(HowLong == 0 && !Signed && !Unsigned &&
"Bad modifiers used with 'y'!");
@@ -10556,7 +10777,10 @@
return GVA_StrongODR;
// Single source offloading languages like CUDA/HIP need to be able to
// access static device variables from host code of the same compilation
- // unit. This is done by externalizing the static variable.
+ // unit. This is done by externalizing the static variable with a shared
+ // name between the host and device compilation which is the same for the
+ // same compilation unit whereas different among different compilation
+ // units.
if (Context.shouldExternalizeStaticVar(D))
return GVA_StrongExternal;
}
@@ -10799,6 +11023,9 @@
assert(FD->isMultiVersion() && "Only valid for multiversioned functions");
llvm::SmallDenseSet<const FunctionDecl*, 4> SeenDecls;
FD = FD->getMostRecentDecl();
+ // FIXME: The order of traversal here matters and depends on the order of
+ // lookup results, which happens to be (mostly) oldest-to-newest, but we
+ // shouldn't rely on that.
for (auto *CurDecl :
FD->getDeclContext()->getRedeclContext()->lookup(FD->getDeclName())) {
FunctionDecl *CurFD = CurDecl->getAsFunction()->getMostRecentDecl();
@@ -10889,6 +11116,33 @@
llvm_unreachable("Unsupported ABI");
}
+MangleContext *ASTContext::createDeviceMangleContext(const TargetInfo &T) {
+ assert(T.getCXXABI().getKind() != TargetCXXABI::Microsoft &&
+ "Device mangle context does not support Microsoft mangling.");
+ switch (T.getCXXABI().getKind()) {
+ case TargetCXXABI::AppleARM64:
+ case TargetCXXABI::Fuchsia:
+ case TargetCXXABI::GenericAArch64:
+ case TargetCXXABI::GenericItanium:
+ case TargetCXXABI::GenericARM:
+ case TargetCXXABI::GenericMIPS:
+ case TargetCXXABI::iOS:
+ case TargetCXXABI::WebAssembly:
+ case TargetCXXABI::WatchOS:
+ case TargetCXXABI::XL:
+ return ItaniumMangleContext::create(
+ *this, getDiagnostics(),
+ [](ASTContext &, const NamedDecl *ND) -> llvm::Optional<unsigned> {
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
+ return RD->getDeviceLambdaManglingNumber();
+ return llvm::None;
+ });
+ case TargetCXXABI::Microsoft:
+ return MicrosoftMangleContext::create(*this, getDiagnostics());
+ }
+ llvm_unreachable("Unsupported ABI");
+}
+
CXXABI::~CXXABI() = default;
size_t ASTContext::getSideTableAllocatedMemory() const {
@@ -11436,16 +11690,112 @@
}
bool ASTContext::mayExternalizeStaticVar(const Decl *D) const {
- return !getLangOpts().GPURelocatableDeviceCode &&
- ((D->hasAttr<CUDADeviceAttr>() &&
- !D->getAttr<CUDADeviceAttr>()->isImplicit()) ||
- (D->hasAttr<CUDAConstantAttr>() &&
- !D->getAttr<CUDAConstantAttr>()->isImplicit())) &&
- isa<VarDecl>(D) && cast<VarDecl>(D)->isFileVarDecl() &&
- cast<VarDecl>(D)->getStorageClass() == SC_Static;
+ bool IsStaticVar =
+ isa<VarDecl>(D) && cast<VarDecl>(D)->getStorageClass() == SC_Static;
+ bool IsExplicitDeviceVar = (D->hasAttr<CUDADeviceAttr>() &&
+ !D->getAttr<CUDADeviceAttr>()->isImplicit()) ||
+ (D->hasAttr<CUDAConstantAttr>() &&
+ !D->getAttr<CUDAConstantAttr>()->isImplicit());
+ // CUDA/HIP: static managed variables need to be externalized since it is
+ // a declaration in IR, therefore cannot have internal linkage.
+ return IsStaticVar &&
+ (D->hasAttr<HIPManagedAttr>() || IsExplicitDeviceVar);
}
bool ASTContext::shouldExternalizeStaticVar(const Decl *D) const {
return mayExternalizeStaticVar(D) &&
- CUDAStaticDeviceVarReferencedByHost.count(cast<VarDecl>(D));
+ (D->hasAttr<HIPManagedAttr>() ||
+ CUDADeviceVarODRUsedByHost.count(cast<VarDecl>(D)));
+}
+
+StringRef ASTContext::getCUIDHash() const {
+ if (!CUIDHash.empty())
+ return CUIDHash;
+ if (LangOpts.CUID.empty())
+ return StringRef();
+ CUIDHash = llvm::utohexstr(llvm::MD5Hash(LangOpts.CUID), /*LowerCase=*/true);
+ return CUIDHash;
+}
+
+// Get the closest named parent, so we can order the sycl naming decls somewhere
+// that mangling is meaningful.
+static const DeclContext *GetNamedParent(const CXXRecordDecl *RD) {
+ const DeclContext *DC = RD->getDeclContext();
+
+ while (!isa<NamedDecl, TranslationUnitDecl>(DC))
+ DC = DC->getParent();
+ return DC;
+}
+
+void ASTContext::AddSYCLKernelNamingDecl(const CXXRecordDecl *RD) {
+ assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
+ RD = RD->getCanonicalDecl();
+ const DeclContext *DC = GetNamedParent(RD);
+
+ assert(RD->getLocation().isValid() &&
+ "Invalid location on kernel naming decl");
+
+ (void)SYCLKernelNamingTypes[DC].insert(RD);
+}
+
+bool ASTContext::IsSYCLKernelNamingDecl(const NamedDecl *ND) const {
+ assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
+ const auto *RD = dyn_cast<CXXRecordDecl>(ND);
+ if (!RD)
+ return false;
+ RD = RD->getCanonicalDecl();
+ const DeclContext *DC = GetNamedParent(RD);
+
+ auto Itr = SYCLKernelNamingTypes.find(DC);
+
+ if (Itr == SYCLKernelNamingTypes.end())
+ return false;
+
+ return Itr->getSecond().count(RD);
+}
+
+// Filters the Decls list to those that share the lambda mangling with the
+// passed RD.
+void ASTContext::FilterSYCLKernelNamingDecls(
+ const CXXRecordDecl *RD,
+ llvm::SmallVectorImpl<const CXXRecordDecl *> &Decls) {
+
+ if (!SYCLKernelFilterContext)
+ SYCLKernelFilterContext.reset(
+ ItaniumMangleContext::create(*this, getDiagnostics()));
+
+ llvm::SmallString<128> LambdaSig;
+ llvm::raw_svector_ostream Out(LambdaSig);
+ SYCLKernelFilterContext->mangleLambdaSig(RD, Out);
+
+ llvm::erase_if(Decls, [this, &LambdaSig](const CXXRecordDecl *LocalRD) {
+ llvm::SmallString<128> LocalLambdaSig;
+ llvm::raw_svector_ostream LocalOut(LocalLambdaSig);
+ SYCLKernelFilterContext->mangleLambdaSig(LocalRD, LocalOut);
+ return LambdaSig != LocalLambdaSig;
+ });
+}
+
+unsigned ASTContext::GetSYCLKernelNamingIndex(const NamedDecl *ND) {
+ assert(getLangOpts().isSYCL() && "Only valid for SYCL programs");
+ assert(IsSYCLKernelNamingDecl(ND) &&
+ "Lambda not involved in mangling asked for a naming index?");
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(ND)->getCanonicalDecl();
+ const DeclContext *DC = GetNamedParent(RD);
+
+ auto Itr = SYCLKernelNamingTypes.find(DC);
+ assert(Itr != SYCLKernelNamingTypes.end() && "Not a valid DeclContext?");
+
+ const llvm::SmallPtrSet<const CXXRecordDecl *, 4> &Set = Itr->getSecond();
+
+ llvm::SmallVector<const CXXRecordDecl *> Decls{Set.begin(), Set.end()};
+
+ FilterSYCLKernelNamingDecls(RD, Decls);
+
+ llvm::sort(Decls, [](const CXXRecordDecl *LHS, const CXXRecordDecl *RHS) {
+ return LHS->getLambdaManglingNumber() < RHS->getLambdaManglingNumber();
+ });
+
+ return llvm::find(Decls, RD) - Decls.begin();
}
diff --git a/src/llvm-project/clang/lib/AST/ASTDiagnostic.cpp b/src/llvm-project/clang/lib/AST/ASTDiagnostic.cpp
index 2bc7317..dc22481 100644
--- a/src/llvm-project/clang/lib/AST/ASTDiagnostic.cpp
+++ b/src/llvm-project/clang/lib/AST/ASTDiagnostic.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -1756,7 +1757,7 @@
if (FromIntType->isBooleanType()) {
OS << ((FromInt == 0) ? "false" : "true");
} else {
- OS << FromInt.toString(10);
+ OS << toString(FromInt, 10);
}
return;
}
@@ -1800,7 +1801,7 @@
if (IntType->isBooleanType()) {
OS << ((Val == 0) ? "false" : "true");
} else {
- OS << Val.toString(10);
+ OS << toString(Val, 10);
}
} else if (E) {
PrintExpr(E);
diff --git a/src/llvm-project/clang/lib/AST/ASTImporter.cpp b/src/llvm-project/clang/lib/AST/ASTImporter.cpp
index 0d723fb..787e020 100644
--- a/src/llvm-project/clang/lib/AST/ASTImporter.cpp
+++ b/src/llvm-project/clang/lib/AST/ASTImporter.cpp
@@ -322,6 +322,21 @@
}
}
+ void updateLookupTableForTemplateParameters(TemplateParameterList &Params,
+ DeclContext *OldDC) {
+ ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable();
+ if (!LT)
+ return;
+
+ for (NamedDecl *TP : Params)
+ LT->update(TP, OldDC);
+ }
+
+ void updateLookupTableForTemplateParameters(TemplateParameterList &Params) {
+ updateLookupTableForTemplateParameters(
+ Params, Importer.getToContext().getTranslationUnitDecl());
+ }
+
public:
explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {}
@@ -358,6 +373,8 @@
ExpectedType VisitDecltypeType(const DecltypeType *T);
ExpectedType VisitUnaryTransformType(const UnaryTransformType *T);
ExpectedType VisitAutoType(const AutoType *T);
+ ExpectedType VisitDeducedTemplateSpecializationType(
+ const DeducedTemplateSpecializationType *T);
ExpectedType VisitInjectedClassNameType(const InjectedClassNameType *T);
// FIXME: DependentDecltypeType
ExpectedType VisitRecordType(const RecordType *T);
@@ -479,6 +496,7 @@
ExpectedDecl VisitAccessSpecDecl(AccessSpecDecl *D);
ExpectedDecl VisitStaticAssertDecl(StaticAssertDecl *D);
ExpectedDecl VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ ExpectedDecl VisitBindingDecl(BindingDecl *D);
ExpectedDecl VisitNamespaceDecl(NamespaceDecl *D);
ExpectedDecl VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
ExpectedDecl VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
@@ -510,6 +528,8 @@
ExpectedDecl VisitUsingDecl(UsingDecl *D);
ExpectedDecl VisitUsingShadowDecl(UsingShadowDecl *D);
ExpectedDecl VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ ExpectedDecl ImportUsingShadowDecls(BaseUsingDecl *D, BaseUsingDecl *ToSI);
+ ExpectedDecl VisitUsingEnumDecl(UsingEnumDecl *D);
ExpectedDecl VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
ExpectedDecl VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
ExpectedDecl VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D);
@@ -574,6 +594,7 @@
// Importing expressions
ExpectedStmt VisitExpr(Expr *E);
+ ExpectedStmt VisitSourceLocExpr(SourceLocExpr *E);
ExpectedStmt VisitVAArgExpr(VAArgExpr *E);
ExpectedStmt VisitChooseExpr(ChooseExpr *E);
ExpectedStmt VisitGNUNullExpr(GNUNullExpr *E);
@@ -1037,6 +1058,10 @@
case BuiltinType::Id: \
return Importer.getToContext().Id##Ty;
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ return Importer.getToContext().SingletonId;
+#include "clang/Basic/RISCVVTypes.def"
#define SHARED_SINGLETON_TYPE(Expansion)
#define BUILTIN_TYPE(Id, SingletonId) \
case BuiltinType::Id: return Importer.getToContext().SingletonId;
@@ -1371,6 +1396,20 @@
ToTemplateArgs);
}
+ExpectedType ASTNodeImporter::VisitDeducedTemplateSpecializationType(
+ const DeducedTemplateSpecializationType *T) {
+ // FIXME: Make sure that the "to" context supports C++17!
+ Expected<TemplateName> ToTemplateNameOrErr = import(T->getTemplateName());
+ if (!ToTemplateNameOrErr)
+ return ToTemplateNameOrErr.takeError();
+ ExpectedType ToDeducedTypeOrErr = import(T->getDeducedType());
+ if (!ToDeducedTypeOrErr)
+ return ToDeducedTypeOrErr.takeError();
+
+ return Importer.getToContext().getDeducedTemplateSpecializationType(
+ *ToTemplateNameOrErr, *ToDeducedTypeOrErr, T->isDependentType());
+}
+
ExpectedType ASTNodeImporter::VisitInjectedClassNameType(
const InjectedClassNameType *T) {
Expected<CXXRecordDecl *> ToDeclOrErr = import(T->getDecl());
@@ -2253,6 +2292,35 @@
return ToD;
}
+ExpectedDecl ASTNodeImporter::VisitBindingDecl(BindingDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToND;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToND, Loc))
+ return std::move(Err);
+ if (ToND)
+ return ToND;
+
+ BindingDecl *ToD;
+ if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc,
+ Name.getAsIdentifierInfo()))
+ return ToD;
+
+ Error Err = Error::success();
+ QualType ToType = importChecked(Err, D->getType());
+ Expr *ToBinding = importChecked(Err, D->getBinding());
+ ValueDecl *ToDecomposedDecl = importChecked(Err, D->getDecomposedDecl());
+ if (Err)
+ return std::move(Err);
+
+ ToD->setBinding(ToType, ToBinding);
+ ToD->setDecomposedDecl(ToDecomposedDecl);
+ addDeclToContexts(D, ToD);
+
+ return ToD;
+}
+
ExpectedDecl ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
ExpectedSLoc LocOrErr = import(D->getLocation());
if (!LocOrErr)
@@ -2586,6 +2654,8 @@
ToAlias->setAccess(D->getAccess());
ToAlias->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToAlias);
+ if (DC != Importer.getToContext().getTranslationUnitDecl())
+ updateLookupTableForTemplateParameters(*ToTemplateParameters);
return ToAlias;
}
@@ -2711,7 +2781,20 @@
D2->setBraceRange(ToBraceRange);
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
+ addDeclToContexts(D, D2);
+
+ if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) {
+ TemplateSpecializationKind SK = MemberInfo->getTemplateSpecializationKind();
+ EnumDecl *FromInst = D->getInstantiatedFromMemberEnum();
+ if (Expected<EnumDecl *> ToInstOrErr = import(FromInst))
+ D2->setInstantiationOfMemberEnum(*ToInstOrErr, SK);
+ else
+ return ToInstOrErr.takeError();
+ if (ExpectedSLoc POIOrErr = import(MemberInfo->getPointOfInstantiation()))
+ D2->getMemberSpecializationInfo()->setPointOfInstantiation(*POIOrErr);
+ else
+ return POIOrErr.takeError();
+ }
// Import the definition
if (D->isCompleteDefinition())
@@ -3423,11 +3506,13 @@
} else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
ExplicitSpecifier ESpec =
importExplicitSpecifier(Err, Guide->getExplicitSpecifier());
+ CXXConstructorDecl *Ctor =
+ importChecked(Err, Guide->getCorrespondingConstructor());
if (Err)
return std::move(Err);
if (GetImportedOrCreateDecl<CXXDeductionGuideDecl>(
ToFunction, D, Importer.getToContext(), DC, ToInnerLocStart, ESpec,
- NameInfo, T, TInfo, ToEndLoc))
+ NameInfo, T, TInfo, ToEndLoc, Ctor))
return ToFunction;
cast<CXXDeductionGuideDecl>(ToFunction)
->setIsCopyDeductionCandidate(Guide->isCopyDeductionCandidate());
@@ -3467,6 +3552,8 @@
for (auto *Param : Parameters) {
Param->setOwningFunction(ToFunction);
ToFunction->addDeclInternal(Param);
+ if (ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable())
+ LT->update(Param, Importer.getToContext().getTranslationUnitDecl());
}
ToFunction->setParams(Parameters);
@@ -3627,6 +3714,10 @@
auto ToInitializer = importChecked(Err, D->getInClassInitializer());
if (Err)
return std::move(Err);
+ const Type *ToCapturedVLAType = nullptr;
+ if (Error Err = Importer.importInto(
+ ToCapturedVLAType, cast_or_null<Type>(D->getCapturedVLAType())))
+ return std::move(Err);
FieldDecl *ToField;
if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC,
@@ -3640,6 +3731,8 @@
if (ToInitializer)
ToField->setInClassInitializer(ToInitializer);
ToField->setImplicit(D->isImplicit());
+ if (ToCapturedVLAType)
+ ToField->setCapturedVLAType(cast<VariableArrayType>(ToCapturedVLAType));
LexicalDC->addDeclInternal(ToField);
return ToField;
}
@@ -4005,15 +4098,28 @@
if (Err)
return std::move(Err);
- // Create the imported variable.
VarDecl *ToVar;
- if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC,
- ToInnerLocStart, Loc,
- Name.getAsIdentifierInfo(),
- ToType, ToTypeSourceInfo,
- D->getStorageClass()))
- return ToVar;
+ if (auto *FromDecomp = dyn_cast<DecompositionDecl>(D)) {
+ SmallVector<BindingDecl *> Bindings(FromDecomp->bindings().size());
+ if (Error Err =
+ ImportArrayChecked(FromDecomp->bindings(), Bindings.begin()))
+ return std::move(Err);
+ DecompositionDecl *ToDecomp;
+ if (GetImportedOrCreateDecl(
+ ToDecomp, FromDecomp, Importer.getToContext(), DC, ToInnerLocStart,
+ Loc, ToType, ToTypeSourceInfo, D->getStorageClass(), Bindings))
+ return ToDecomp;
+ ToVar = ToDecomp;
+ } else {
+ // Create the imported variable.
+ if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC,
+ ToInnerLocStart, Loc,
+ Name.getAsIdentifierInfo(), ToType,
+ ToTypeSourceInfo, D->getStorageClass()))
+ return ToVar;
+ }
+ ToVar->setTSCSpec(D->getTSCSpec());
ToVar->setQualifierInfo(ToQualifierLoc);
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
@@ -4519,6 +4625,19 @@
return ToLinkageSpec;
}
+ExpectedDecl ASTNodeImporter::ImportUsingShadowDecls(BaseUsingDecl *D,
+ BaseUsingDecl *ToSI) {
+ for (UsingShadowDecl *FromShadow : D->shadows()) {
+ if (Expected<UsingShadowDecl *> ToShadowOrErr = import(FromShadow))
+ ToSI->addShadowDecl(*ToShadowOrErr);
+ else
+ // FIXME: We return error here but the definition is already created
+ // and available with lookups. How to fix this?..
+ return ToShadowOrErr.takeError();
+ }
+ return ToSI;
+}
+
ExpectedDecl ASTNodeImporter::VisitUsingDecl(UsingDecl *D) {
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -4558,15 +4677,44 @@
return ToPatternOrErr.takeError();
}
- for (UsingShadowDecl *FromShadow : D->shadows()) {
- if (Expected<UsingShadowDecl *> ToShadowOrErr = import(FromShadow))
- ToUsing->addShadowDecl(*ToShadowOrErr);
+ return ImportUsingShadowDecls(D, ToUsing);
+}
+
+ExpectedDecl ASTNodeImporter::VisitUsingEnumDecl(UsingEnumDecl *D) {
+ DeclContext *DC, *LexicalDC;
+ DeclarationName Name;
+ SourceLocation Loc;
+ NamedDecl *ToD = nullptr;
+ if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ return std::move(Err);
+ if (ToD)
+ return ToD;
+
+ Error Err = Error::success();
+ auto ToUsingLoc = importChecked(Err, D->getUsingLoc());
+ auto ToEnumLoc = importChecked(Err, D->getEnumLoc());
+ auto ToEnumDecl = importChecked(Err, D->getEnumDecl());
+ if (Err)
+ return std::move(Err);
+
+ UsingEnumDecl *ToUsingEnum;
+ if (GetImportedOrCreateDecl(ToUsingEnum, D, Importer.getToContext(), DC,
+ ToUsingLoc, ToEnumLoc, Loc, ToEnumDecl))
+ return ToUsingEnum;
+
+ ToUsingEnum->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToUsingEnum);
+
+ if (UsingEnumDecl *FromPattern =
+ Importer.getFromContext().getInstantiatedFromUsingEnumDecl(D)) {
+ if (Expected<UsingEnumDecl *> ToPatternOrErr = import(FromPattern))
+ Importer.getToContext().setInstantiatedFromUsingEnumDecl(ToUsingEnum,
+ *ToPatternOrErr);
else
- // FIXME: We return error here but the definition is already created
- // and available with lookups. How to fix this?..
- return ToShadowOrErr.takeError();
+ return ToPatternOrErr.takeError();
}
- return ToUsing;
+
+ return ImportUsingShadowDecls(D, ToUsingEnum);
}
ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
@@ -4579,9 +4727,9 @@
if (ToD)
return ToD;
- Expected<UsingDecl *> ToUsingOrErr = import(D->getUsingDecl());
- if (!ToUsingOrErr)
- return ToUsingOrErr.takeError();
+ Expected<BaseUsingDecl *> ToIntroducerOrErr = import(D->getIntroducer());
+ if (!ToIntroducerOrErr)
+ return ToIntroducerOrErr.takeError();
Expected<NamedDecl *> ToTargetOrErr = import(D->getTargetDecl());
if (!ToTargetOrErr)
@@ -4589,7 +4737,7 @@
UsingShadowDecl *ToShadow;
if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc,
- *ToUsingOrErr, *ToTargetOrErr))
+ Name, *ToIntroducerOrErr, *ToTargetOrErr))
return ToShadow;
ToShadow->setLexicalDeclContext(LexicalDC);
@@ -5060,6 +5208,11 @@
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
if (auto *FoundProp = dyn_cast<ObjCPropertyDecl>(FoundDecl)) {
+ // Instance and class properties can share the same name but are different
+ // declarations.
+ if (FoundProp->isInstanceProperty() != D->isInstanceProperty())
+ continue;
+
// Check property types.
if (!Importer.IsStructurallyEquivalent(D->getType(),
FoundProp->getType())) {
@@ -5417,6 +5570,7 @@
D2->setLexicalDeclContext(LexicalDC);
addDeclToContexts(D, D2);
+ updateLookupTableForTemplateParameters(**TemplateParamsOrErr);
if (FoundByLookup) {
auto *Recent =
@@ -5560,6 +5714,7 @@
// Add this partial specialization to the class template.
ClassTemplate->AddPartialSpecialization(PartSpec2, InsertPos);
+ updateLookupTableForTemplateParameters(*ToTPList);
} else { // Not a partial specialization.
if (GetImportedOrCreateDecl(
D2, D, Importer.getToContext(), D->getTagKind(), DC,
@@ -5709,6 +5864,8 @@
ToVarTD->setAccess(D->getAccess());
ToVarTD->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToVarTD);
+ if (DC != Importer.getToContext().getTranslationUnitDecl())
+ updateLookupTableForTemplateParameters(**TemplateParamsOrErr);
if (FoundByLookup) {
auto *Recent =
@@ -5834,6 +5991,9 @@
D2 = ToPartial;
+ // FIXME: Use this update if VarTemplatePartialSpecializationDecl is fixed
+ // to adopt template parameters.
+ // updateLookupTableForTemplateParameters(**ToTPListOrErr);
} else { // Full specialization
if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC,
*BeginLocOrErr, *IdLocOrErr, VarTemplate,
@@ -5922,14 +6082,30 @@
auto ParamsOrErr = import(D->getTemplateParameters());
if (!ParamsOrErr)
return ParamsOrErr.takeError();
+ TemplateParameterList *Params = *ParamsOrErr;
FunctionDecl *TemplatedFD;
if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl()))
return std::move(Err);
+ // Template parameters of the ClassTemplateDecl and FunctionTemplateDecl are
+ // shared, if the FunctionTemplateDecl is a deduction guide for the class.
+ // At import the ClassTemplateDecl object is always created first (FIXME: is
+ // this really true?) because the dependency, then the FunctionTemplateDecl.
+ // The DeclContext of the template parameters is changed when the
+ // FunctionTemplateDecl is created, but was set already when the class
+ // template was created. So here it is not the TU (default value) any more.
+ // FIXME: The DeclContext of the parameters is now set finally to the
+ // CXXDeductionGuideDecl object that was imported later. This may not be the
+ // same that is in the original AST, specially if there are multiple deduction
+ // guides.
+ DeclContext *OldParamDC = nullptr;
+ if (Params->size() > 0)
+ OldParamDC = Params->getParam(0)->getDeclContext();
+
FunctionTemplateDecl *ToFunc;
if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name,
- *ParamsOrErr, TemplatedFD))
+ Params, TemplatedFD))
return ToFunc;
TemplatedFD->setDescribedFunctionTemplate(ToFunc);
@@ -5937,6 +6113,7 @@
ToFunc->setAccess(D->getAccess());
ToFunc->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(ToFunc);
+ updateLookupTableForTemplateParameters(*Params, OldParamDC);
if (FoundByLookup) {
auto *Recent =
@@ -6478,6 +6655,21 @@
return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
+ExpectedStmt ASTNodeImporter::VisitSourceLocExpr(SourceLocExpr *E) {
+ Error Err = Error::success();
+ auto BLoc = importChecked(Err, E->getBeginLoc());
+ auto RParenLoc = importChecked(Err, E->getEndLoc());
+ if (Err)
+ return std::move(Err);
+ auto ParentContextOrErr = Importer.ImportContext(E->getParentContext());
+ if (!ParentContextOrErr)
+ return ParentContextOrErr.takeError();
+
+ return new (Importer.getToContext())
+ SourceLocExpr(Importer.getToContext(), E->getIdentKind(), BLoc, RParenLoc,
+ *ParentContextOrErr);
+}
+
ExpectedStmt ASTNodeImporter::VisitVAArgExpr(VAArgExpr *E) {
Error Err = Error::success();
@@ -8147,28 +8339,37 @@
return make_error<ImportError>(ImportError::UnsupportedConstruct);
}
-Expected<QualType> ASTImporter::Import(QualType FromT) {
- if (FromT.isNull())
- return QualType{};
-
- const Type *FromTy = FromT.getTypePtr();
+Expected<const Type *> ASTImporter::Import(const Type *FromT) {
+ if (!FromT)
+ return FromT;
// Check whether we've already imported this type.
- llvm::DenseMap<const Type *, const Type *>::iterator Pos
- = ImportedTypes.find(FromTy);
+ llvm::DenseMap<const Type *, const Type *>::iterator Pos =
+ ImportedTypes.find(FromT);
if (Pos != ImportedTypes.end())
- return ToContext.getQualifiedType(Pos->second, FromT.getLocalQualifiers());
+ return Pos->second;
// Import the type
ASTNodeImporter Importer(*this);
- ExpectedType ToTOrErr = Importer.Visit(FromTy);
+ ExpectedType ToTOrErr = Importer.Visit(FromT);
if (!ToTOrErr)
return ToTOrErr.takeError();
// Record the imported type.
- ImportedTypes[FromTy] = (*ToTOrErr).getTypePtr();
+ ImportedTypes[FromT] = ToTOrErr->getTypePtr();
- return ToContext.getQualifiedType(*ToTOrErr, FromT.getLocalQualifiers());
+ return ToTOrErr->getTypePtr();
+}
+
+Expected<QualType> ASTImporter::Import(QualType FromT) {
+ if (FromT.isNull())
+ return QualType{};
+
+ Expected<const Type *> ToTyOrErr = Import(FromT.getTypePtr());
+ if (!ToTyOrErr)
+ return ToTyOrErr.takeError();
+
+ return ToContext.getQualifiedType(*ToTyOrErr, FromT.getLocalQualifiers());
}
Expected<TypeSourceInfo *> ASTImporter::Import(TypeSourceInfo *FromTSI) {
@@ -8313,7 +8514,11 @@
// traverse of the 'to' context).
auto PosF = ImportedFromDecls.find(ToD);
if (PosF != ImportedFromDecls.end()) {
- SharedState->removeDeclFromLookup(ToD);
+ // In the case of TypedefNameDecl we create the Decl first and only
+ // then we import and set its DeclContext. So, the DC might not be set
+ // when we reach here.
+ if (ToD->getDeclContext())
+ SharedState->removeDeclFromLookup(ToD);
ImportedFromDecls.erase(PosF);
}
@@ -8839,10 +9044,6 @@
assert(ToID.isValid() && "Unexpected invalid fileID was created.");
ImportedFileIDs[FromID] = ToID;
-
- if (FileIDImportHandler)
- FileIDImportHandler(ToID, FromID);
-
return ToID;
}
diff --git a/src/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp b/src/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp
index e17d608..b78cc0c 100644
--- a/src/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp
+++ b/src/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp
@@ -117,6 +117,19 @@
remove(ReDC, ND);
}
+void ASTImporterLookupTable::update(NamedDecl *ND, DeclContext *OldDC) {
+ assert(OldDC != ND->getDeclContext() &&
+ "DeclContext should be changed before update");
+ if (contains(ND->getDeclContext(), ND)) {
+ assert(!contains(OldDC, ND) &&
+ "Decl should not be found in the old context if already in the new");
+ return;
+ }
+
+ remove(OldDC, ND);
+ add(ND);
+}
+
ASTImporterLookupTable::LookupResult
ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
auto DCI = LookupTable.find(DC->getPrimaryContext());
@@ -131,6 +144,10 @@
return NamesI->second;
}
+bool ASTImporterLookupTable::contains(DeclContext *DC, NamedDecl *ND) const {
+ return 0 < lookup(DC, ND->getDeclName()).count(ND);
+}
+
void ASTImporterLookupTable::dump(DeclContext *DC) const {
auto DCI = LookupTable.find(DC->getPrimaryContext());
if (DCI == LookupTable.end())
diff --git a/src/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp b/src/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp
index d004e44..c4ff05b 100644
--- a/src/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/src/llvm-project/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -86,6 +86,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
@@ -1623,7 +1624,7 @@
diag::err_odr_tag_type_inconsistent))
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
- << EC1->getDeclName() << EC1->getInitVal().toString(10);
+ << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
Context.Diag2(D2->getLocation(), diag::note_odr_missing_enumerator);
}
return false;
@@ -1639,9 +1640,9 @@
diag::err_odr_tag_type_inconsistent))
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
- << EC2->getDeclName() << EC2->getInitVal().toString(10);
+ << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
Context.Diag1(EC1->getLocation(), diag::note_odr_enumerator)
- << EC1->getDeclName() << EC1->getInitVal().toString(10);
+ << EC1->getDeclName() << toString(EC1->getInitVal(), 10);
}
return false;
}
@@ -1653,7 +1654,7 @@
diag::err_odr_tag_type_inconsistent))
<< Context.ToCtx.getTypeDeclType(D2);
Context.Diag2(EC2->getLocation(), diag::note_odr_enumerator)
- << EC2->getDeclName() << EC2->getInitVal().toString(10);
+ << EC2->getDeclName() << toString(EC2->getInitVal(), 10);
Context.Diag1(D1->getLocation(), diag::note_odr_missing_enumerator);
}
return false;
diff --git a/src/llvm-project/clang/lib/AST/ASTTypeTraits.cpp b/src/llvm-project/clang/lib/AST/ASTTypeTraits.cpp
index 8f9ceea..4a033bf 100644
--- a/src/llvm-project/clang/lib/AST/ASTTypeTraits.cpp
+++ b/src/llvm-project/clang/lib/AST/ASTTypeTraits.cpp
@@ -140,9 +140,9 @@
void DynTypedNode::print(llvm::raw_ostream &OS,
const PrintingPolicy &PP) const {
if (const TemplateArgument *TA = get<TemplateArgument>())
- TA->print(PP, OS);
+ TA->print(PP, OS, /*IncludeType*/ true);
else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
- TAL->getArgument().print(PP, OS);
+ TAL->getArgument().print(PP, OS, /*IncludeType*/ true);
else if (const TemplateName *TN = get<TemplateName>())
TN->print(OS, PP);
else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
diff --git a/src/llvm-project/clang/lib/AST/AttrImpl.cpp b/src/llvm-project/clang/lib/AST/AttrImpl.cpp
index 09fdca6..662f867 100644
--- a/src/llvm-project/clang/lib/AST/AttrImpl.cpp
+++ b/src/llvm-project/clang/lib/AST/AttrImpl.cpp
@@ -141,57 +141,44 @@
OS << ' ' << ConvertMapTypeTyToStr(getMapType());
}
-llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
-OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {
+llvm::Optional<OMPDeclareTargetDeclAttr *>
+OMPDeclareTargetDeclAttr::getActiveAttr(const ValueDecl *VD) {
if (!VD->hasAttrs())
return llvm::None;
unsigned Level = 0;
- const OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
- for (const auto *Attr : VD->specific_attrs<OMPDeclareTargetDeclAttr>()) {
- if (Level < Attr->getLevel()) {
+ OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
+ for (auto *Attr : VD->specific_attrs<OMPDeclareTargetDeclAttr>()) {
+ if (Level <= Attr->getLevel()) {
Level = Attr->getLevel();
FoundAttr = Attr;
}
}
if (FoundAttr)
- return FoundAttr->getMapType();
+ return FoundAttr;
+ return llvm::None;
+}
+llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
+OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {
+ llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
+ if (ActiveAttr.hasValue())
+ return ActiveAttr.getValue()->getMapType();
return llvm::None;
}
llvm::Optional<OMPDeclareTargetDeclAttr::DevTypeTy>
OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) {
- if (!VD->hasAttrs())
- return llvm::None;
- unsigned Level = 0;
- const OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
- for (const auto *Attr : VD->specific_attrs<OMPDeclareTargetDeclAttr>()) {
- if (Level < Attr->getLevel()) {
- Level = Attr->getLevel();
- FoundAttr = Attr;
- }
- }
- if (FoundAttr)
- return FoundAttr->getDevType();
-
+ llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
+ if (ActiveAttr.hasValue())
+ return ActiveAttr.getValue()->getDevType();
return llvm::None;
}
llvm::Optional<SourceLocation>
OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) {
- if (!VD->hasAttrs())
- return llvm::None;
- unsigned Level = 0;
- const OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
- for (const auto *Attr : VD->specific_attrs<OMPDeclareTargetDeclAttr>()) {
- if (Level < Attr->getLevel()) {
- Level = Attr->getLevel();
- FoundAttr = Attr;
- }
- }
- if (FoundAttr)
- return FoundAttr->getRange().getBegin();
-
+ llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
+ if (ActiveAttr.hasValue())
+ return ActiveAttr.getValue()->getRange().getBegin();
return llvm::None;
}
diff --git a/src/llvm-project/clang/lib/AST/CXXInheritance.cpp b/src/llvm-project/clang/lib/AST/CXXInheritance.cpp
index c87bcf3..9027fa7 100644
--- a/src/llvm-project/clang/lib/AST/CXXInheritance.cpp
+++ b/src/llvm-project/clang/lib/AST/CXXInheritance.cpp
@@ -386,9 +386,9 @@
static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path,
DeclarationName Name) {
- Path.Decls = RD->lookup(Name);
- for (NamedDecl *ND : Path.Decls)
- if (isOrdinaryMember(ND))
+ Path.Decls = RD->lookup(Name).begin();
+ for (DeclContext::lookup_iterator I = Path.Decls, E = I.end(); I != E; ++I)
+ if (isOrdinaryMember(*I))
return true;
return false;
@@ -453,9 +453,10 @@
},
Paths, /*LookupInDependent=*/true))
return Results;
- for (const NamedDecl *ND : Paths.front().Decls) {
- if (isOrdinaryMember(ND) && Filter(ND))
- Results.push_back(ND);
+ for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
+ I != E; ++I) {
+ if (isOrdinaryMember(*I) && Filter(*I))
+ Results.push_back(*I);
}
return Results;
}
diff --git a/src/llvm-project/clang/lib/AST/ComputeDependence.cpp b/src/llvm-project/clang/lib/AST/ComputeDependence.cpp
index 4026fdc..5648cf2 100644
--- a/src/llvm-project/clang/lib/AST/ComputeDependence.cpp
+++ b/src/llvm-project/clang/lib/AST/ComputeDependence.cpp
@@ -556,6 +556,10 @@
return D;
}
+ExprDependence clang::computeDependence(SYCLUniqueStableNameExpr *E) {
+ return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence());
+}
+
ExprDependence clang::computeDependence(PredefinedExpr *E) {
return toExprDependence(E->getType()->getDependence()) &
~ExprDependence::UnexpandedPack;
@@ -744,6 +748,10 @@
return E->getExpr()->getDependence();
}
+ExprDependence clang::computeDependence(CXXDefaultArgExpr *E) {
+ return E->getExpr()->getDependence();
+}
+
ExprDependence clang::computeDependence(LambdaExpr *E,
bool ContainsUnexpandedParameterPack) {
auto D = toExprDependence(E->getType()->getDependence());
diff --git a/src/llvm-project/clang/lib/AST/Decl.cpp b/src/llvm-project/clang/lib/AST/Decl.cpp
index feb9b06..8f2ecb7 100644
--- a/src/llvm-project/clang/lib/AST/Decl.cpp
+++ b/src/llvm-project/clang/lib/AST/Decl.cpp
@@ -41,8 +41,8 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/Module.h"
+#include "clang/Basic/NoSanitizeList.h"
#include "clang/Basic/PartialDiagnostic.h"
-#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
@@ -102,7 +102,7 @@
TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, nullptr, SourceLocation()),
- DeclContext(TranslationUnit), Ctx(ctx) {}
+ DeclContext(TranslationUnit), redeclarable_base(ctx), Ctx(ctx) {}
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
@@ -1078,6 +1078,28 @@
return L == getCachedLinkage();
}
+ReservedIdentifierStatus
+NamedDecl::isReserved(const LangOptions &LangOpts) const {
+ const IdentifierInfo *II = getIdentifier();
+
+ // This triggers at least for CXXLiteralIdentifiers, which we already checked
+ // at lexing time.
+ if (!II)
+ return ReservedIdentifierStatus::NotReserved;
+
+ ReservedIdentifierStatus Status = II->isReserved(LangOpts);
+ if (Status == ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope) {
+ // Check if we're at TU level or not.
+ if (isa<ParmVarDecl>(this) || isTemplateParameter())
+ return ReservedIdentifierStatus::NotReserved;
+ const DeclContext *DC = getDeclContext()->getRedeclContext();
+ if (!DC->isTranslationUnit())
+ return ReservedIdentifierStatus::NotReserved;
+ }
+
+ return Status;
+}
+
ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
StringRef name = getName();
if (name.empty()) return SFF_None;
@@ -1347,6 +1369,7 @@
case Decl::NamespaceAlias:
case Decl::ParmVar:
case Decl::Using:
+ case Decl::UsingEnum:
case Decl::UsingShadow:
case Decl::UsingDirective:
return LinkageInfo::none();
@@ -1487,10 +1510,13 @@
}
LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
- return getLVForDecl(D,
- LVComputationKind(usesTypeVisibility(D)
- ? NamedDecl::VisibilityForType
- : NamedDecl::VisibilityForValue));
+ NamedDecl::ExplicitVisibilityKind EK = usesTypeVisibility(D)
+ ? NamedDecl::VisibilityForType
+ : NamedDecl::VisibilityForValue;
+ LVComputationKind CK(EK);
+ return getLVForDecl(D, D->getASTContext().getLangOpts().IgnoreXCOFFVisibility
+ ? CK.forLinkageOnly()
+ : CK);
}
Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
@@ -1609,8 +1635,7 @@
// Suppress inline namespace if it doesn't make the result ambiguous.
if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope &&
- Ctx->lookup(NameInScope).size() ==
- Ctx->getParent()->lookup(NameInScope).size())
+ cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope))
continue;
// Skip non-named contexts such as linkage specifications and ExportDecls.
@@ -2509,6 +2534,14 @@
return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref;
}
+bool VarDecl::hasDependentAlignment() const {
+ QualType T = getType();
+ return T->isDependentType() || T->isUndeducedAutoType() ||
+ llvm::any_of(specific_attrs<AlignedAttr>(), [](const AlignedAttr *AA) {
+ return AA->isAlignmentDependent();
+ });
+}
+
VarDecl *VarDecl::getTemplateInstantiationPattern() const {
const VarDecl *VD = this;
@@ -3263,6 +3296,8 @@
if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
+ } else if (const auto *BAA = getAttr<BuiltinAliasAttr>()) {
+ BuiltinID = BAA->getBuiltinName()->getBuiltinID();
} else if (const auto *A = getAttr<BuiltinAttr>()) {
BuiltinID = A->getID();
}
@@ -3273,7 +3308,7 @@
// If the function is marked "overloadable", it has a different mangled name
// and is not the C library function.
if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
- !hasAttr<ArmBuiltinAliasAttr>())
+ (!hasAttr<ArmBuiltinAliasAttr>() && !hasAttr<BuiltinAliasAttr>()))
return 0;
ASTContext &Context = getASTContext();
@@ -4553,6 +4588,13 @@
void RecordDecl::completeDefinition() {
assert(!isCompleteDefinition() && "Cannot redefine record!");
TagDecl::completeDefinition();
+
+ ASTContext &Ctx = getASTContext();
+
+ // Layouts are dumped when computed, so if we are dumping for all complete
+ // types, we need to force usage to get types that wouldn't be used elsewhere.
+ if (Ctx.getLangOpts().DumpRecordLayoutsComplete)
+ (void)Ctx.getASTRecordLayout(this);
}
/// isMsStruct - Get whether or not this record uses ms_struct layout.
@@ -4594,7 +4636,7 @@
(SanitizerKind::Address | SanitizerKind::KernelAddress);
if (!EnabledAsanMask || !Context.getLangOpts().SanitizeAddressFieldPadding)
return false;
- const auto &Blacklist = Context.getSanitizerBlacklist();
+ const auto &NoSanitizeList = Context.getNoSanitizeList();
const auto *CXXRD = dyn_cast<CXXRecordDecl>(this);
// We may be able to relax some of these requirements.
int ReasonToReject = -1;
@@ -4610,12 +4652,11 @@
ReasonToReject = 4; // has trivial destructor.
else if (CXXRD->isStandardLayout())
ReasonToReject = 5; // is standard layout.
- else if (Blacklist.isBlacklistedLocation(EnabledAsanMask, getLocation(),
+ else if (NoSanitizeList.containsLocation(EnabledAsanMask, getLocation(),
"field-padding"))
ReasonToReject = 6; // is in an excluded file.
- else if (Blacklist.isBlacklistedType(EnabledAsanMask,
- getQualifiedNameAsString(),
- "field-padding"))
+ else if (NoSanitizeList.containsType(
+ EnabledAsanMask, getQualifiedNameAsString(), "field-padding"))
ReasonToReject = 7; // The type is excluded.
if (EmitRemark) {
diff --git a/src/llvm-project/clang/lib/AST/DeclBase.cpp b/src/llvm-project/clang/lib/AST/DeclBase.cpp
index c26d6d1..3467da2 100644
--- a/src/llvm-project/clang/lib/AST/DeclBase.cpp
+++ b/src/llvm-project/clang/lib/AST/DeclBase.cpp
@@ -784,6 +784,7 @@
case Using:
case UsingPack:
+ case UsingEnum:
return IDNS_Using;
case ObjCProtocol:
@@ -811,6 +812,9 @@
case TypeAliasTemplate:
return IDNS_Ordinary | IDNS_Tag | IDNS_Type;
+ case UnresolvedUsingIfExists:
+ return IDNS_Type | IDNS_Ordinary;
+
case OMPDeclareReduction:
return IDNS_OMPReduction;
@@ -1215,7 +1219,6 @@
DeclContext *DeclContext::getPrimaryContext() {
switch (getDeclKind()) {
- case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::LinkageSpec:
case Decl::Export:
@@ -1227,6 +1230,8 @@
// There is only one DeclContext for these entities.
return this;
+ case Decl::TranslationUnit:
+ return static_cast<TranslationUnitDecl *>(this)->getFirstDecl();
case Decl::Namespace:
// The original namespace is our primary context.
return static_cast<NamespaceDecl *>(this)->getOriginalNamespace();
@@ -1281,23 +1286,27 @@
}
}
-void
-DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
- Contexts.clear();
-
- if (getDeclKind() != Decl::Namespace) {
- Contexts.push_back(this);
- return;
- }
-
- auto *Self = static_cast<NamespaceDecl *>(this);
- for (NamespaceDecl *N = Self->getMostRecentDecl(); N;
- N = N->getPreviousDecl())
- Contexts.push_back(N);
+template <typename T>
+void collectAllContextsImpl(T *Self, SmallVectorImpl<DeclContext *> &Contexts) {
+ for (T *D = Self->getMostRecentDecl(); D; D = D->getPreviousDecl())
+ Contexts.push_back(D);
std::reverse(Contexts.begin(), Contexts.end());
}
+void DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts) {
+ Contexts.clear();
+
+ Decl::Kind Kind = getDeclKind();
+
+ if (Kind == Decl::TranslationUnit)
+ collectAllContextsImpl(static_cast<TranslationUnitDecl *>(this), Contexts);
+ else if (Kind == Decl::Namespace)
+ collectAllContextsImpl(static_cast<NamespaceDecl *>(this), Contexts);
+ else
+ Contexts.push_back(this);
+}
+
std::pair<Decl *, Decl *>
DeclContext::BuildDeclChain(ArrayRef<Decl *> Decls,
bool FieldsAlreadyLoaded) {
@@ -1394,39 +1403,7 @@
DC->reconcileExternalVisibleStorage();
StoredDeclsList &List = (*Map)[Name];
-
- // Clear out any old external visible declarations, to avoid quadratic
- // performance in the redeclaration checks below.
- List.removeExternalDecls();
-
- if (!List.isNull()) {
- // We have both existing declarations and new declarations for this name.
- // Some of the declarations may simply replace existing ones. Handle those
- // first.
- llvm::SmallVector<unsigned, 8> Skip;
- for (unsigned I = 0, N = Decls.size(); I != N; ++I)
- if (List.HandleRedeclaration(Decls[I], /*IsKnownNewer*/false))
- Skip.push_back(I);
- Skip.push_back(Decls.size());
-
- // Add in any new declarations.
- unsigned SkipPos = 0;
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- if (I == Skip[SkipPos])
- ++SkipPos;
- else
- List.AddSubsequentDecl(Decls[I]);
- }
- } else {
- // Convert the array to a StoredDeclsList.
- for (auto *D : Decls) {
- if (List.isNull())
- List.setOnlyValue(D);
- else
- List.AddSubsequentDecl(D);
- }
- }
-
+ List.replaceExternalDecls(Decls);
return List.getLookupResult();
}
@@ -1538,10 +1515,7 @@
if (Map) {
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
assert(Pos != Map->end() && "no lookup entry for decl");
- // Remove the decl only if it is contained.
- StoredDeclsList::DeclsTy *Vec = Pos->second.getAsVector();
- if ((Vec && is_contained(*Vec, ND)) || Pos->second.getAsDecl() == ND)
- Pos->second.remove(ND);
+ Pos->second.remove(ND);
}
} while (DC->isTransparentContext() && (DC = DC->getParent()));
}
@@ -1658,8 +1632,6 @@
}
}
-NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr;
-
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) const {
assert(getDeclKind() != Decl::LinkageSpec &&
@@ -1935,23 +1907,11 @@
// In this case, we never try to replace an existing declaration; we'll
// handle that when we finalize the list of declarations for this name.
DeclNameEntries.setHasExternalDecls();
- DeclNameEntries.AddSubsequentDecl(D);
+ DeclNameEntries.prependDeclNoReplace(D);
return;
}
- if (DeclNameEntries.isNull()) {
- DeclNameEntries.setOnlyValue(D);
- return;
- }
-
- if (DeclNameEntries.HandleRedeclaration(D, /*IsKnownNewer*/!Internal)) {
- // This declaration has replaced an existing one for which
- // declarationReplaces returns true.
- return;
- }
-
- // Put this declaration into the appropriate slot.
- DeclNameEntries.AddSubsequentDecl(D);
+ DeclNameEntries.addOrReplaceDecl(D);
}
UsingDirectiveDecl *DeclContext::udir_iterator::operator*() const {
diff --git a/src/llvm-project/clang/lib/AST/DeclCXX.cpp b/src/llvm-project/clang/lib/AST/DeclCXX.cpp
index 0375f9b..aeee35d 100644
--- a/src/llvm-project/clang/lib/AST/DeclCXX.cpp
+++ b/src/llvm-project/clang/lib/AST/DeclCXX.cpp
@@ -108,7 +108,8 @@
ImplicitCopyConstructorCanHaveConstParamForNonVBase(true),
ImplicitCopyAssignmentHasConstParam(true),
HasDeclaredCopyConstructorWithConstParam(false),
- HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false),
+ HasDeclaredCopyAssignmentWithConstParam(false),
+ IsAnyDestructorNoReturn(false), IsLambda(false),
IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false),
HasODRHash(false), Definition(D) {}
@@ -424,6 +425,9 @@
if (!BaseClassDecl->hasIrrelevantDestructor())
data().HasIrrelevantDestructor = false;
+ if (BaseClassDecl->isAnyDestructorNoReturn())
+ data().IsAnyDestructorNoReturn = true;
+
// C++11 [class.copy]p18:
// The implicitly-declared copy assignment operator for a class X will
// have the form 'X& X::operator=(const X&)' if each direct base class B
@@ -836,6 +840,9 @@
data().HasTrivialSpecialMembers &= ~SMF_Destructor;
data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
}
+
+ if (DD->isNoReturn())
+ data().IsAnyDestructorNoReturn = true;
}
// Handle member functions.
@@ -1233,6 +1240,8 @@
data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
if (!FieldRec->hasIrrelevantDestructor())
data().HasIrrelevantDestructor = false;
+ if (FieldRec->isAnyDestructorNoReturn())
+ data().IsAnyDestructorNoReturn = true;
if (FieldRec->hasObjectMember())
setHasObjectMember(true);
if (FieldRec->hasVolatileMember())
@@ -1888,29 +1897,6 @@
return R.empty() ? nullptr : dyn_cast<CXXDestructorDecl>(R.front());
}
-bool CXXRecordDecl::isAnyDestructorNoReturn() const {
- // Destructor is noreturn.
- if (const CXXDestructorDecl *Destructor = getDestructor())
- if (Destructor->isNoReturn())
- return true;
-
- // Check base classes destructor for noreturn.
- for (const auto &Base : bases())
- if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl())
- if (RD->isAnyDestructorNoReturn())
- return true;
-
- // Check fields for noreturn.
- for (const auto *Field : fields())
- if (const CXXRecordDecl *RD =
- Field->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
- if (RD->isAnyDestructorNoReturn())
- return true;
-
- // All destructors are not noreturn.
- return false;
-}
-
static bool isDeclContextInNamespace(const DeclContext *DC) {
while (!DC->isTranslationUnit()) {
if (DC->isNamespace())
@@ -2073,19 +2059,21 @@
}
}
-CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
- ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
- TypeSourceInfo *TInfo, SourceLocation EndLocation) {
+CXXDeductionGuideDecl *
+CXXDeductionGuideDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, ExplicitSpecifier ES,
+ const DeclarationNameInfo &NameInfo, QualType T,
+ TypeSourceInfo *TInfo, SourceLocation EndLocation,
+ CXXConstructorDecl *Ctor) {
return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, ES, NameInfo, T,
- TInfo, EndLocation);
+ TInfo, EndLocation, Ctor);
}
CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) CXXDeductionGuideDecl(
C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
- QualType(), nullptr, SourceLocation());
+ QualType(), nullptr, SourceLocation(), nullptr);
}
RequiresExprBodyDecl *RequiresExprBodyDecl::Create(
@@ -2232,7 +2220,7 @@
// If the base expression (after skipping derived-to-base conversions) is a
// class prvalue, then we can devirtualize.
Base = Base->getBestDynamicClassTypeExpr();
- if (Base->isRValue() && Base->getType()->isRecordType())
+ if (Base->isPRValue() && Base->getType()->isRecordType())
return this;
// If we don't even know what we would call, we can't devirtualize.
@@ -2506,16 +2494,15 @@
SourceLocation L, Expr *Init,
SourceLocation R,
SourceLocation EllipsisLoc)
- : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init),
+ : Initializee(TInfo), Init(Init), MemberOrEllipsisLocation(EllipsisLoc),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual),
IsWritten(false), SourceOrder(0) {}
-CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
- FieldDecl *Member,
+CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
SourceLocation MemberLoc,
SourceLocation L, Expr *Init,
SourceLocation R)
- : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
+ : Initializee(Member), Init(Init), MemberOrEllipsisLocation(MemberLoc),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
IsWritten(false), SourceOrder(0) {}
@@ -2524,7 +2511,7 @@
SourceLocation MemberLoc,
SourceLocation L, Expr *Init,
SourceLocation R)
- : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
+ : Initializee(Member), Init(Init), MemberOrEllipsisLocation(MemberLoc),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
IsWritten(false), SourceOrder(0) {}
@@ -2601,19 +2588,19 @@
CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
unsigned ID,
uint64_t AllocKind) {
- bool hasTraillingExplicit = static_cast<bool>(AllocKind & TAKHasTailExplicit);
+ bool hasTrailingExplicit = static_cast<bool>(AllocKind & TAKHasTailExplicit);
bool isInheritingConstructor =
static_cast<bool>(AllocKind & TAKInheritsConstructor);
unsigned Extra =
additionalSizeToAlloc<InheritedConstructor, ExplicitSpecifier>(
- isInheritingConstructor, hasTraillingExplicit);
+ isInheritingConstructor, hasTrailingExplicit);
auto *Result = new (C, ID, Extra) CXXConstructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
ExplicitSpecifier(), false, false, ConstexprSpecKind::Unspecified,
InheritedConstructor(), nullptr);
Result->setInheritingConstructor(isInheritingConstructor);
Result->CXXConstructorDeclBits.HasTrailingExplicitSpecifier =
- hasTraillingExplicit;
+ hasTrailingExplicit;
Result->setExplicitSpecifier(ExplicitSpecifier());
return Result;
}
@@ -2982,10 +2969,10 @@
void UsingShadowDecl::anchor() {}
UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
- SourceLocation Loc, UsingDecl *Using,
- NamedDecl *Target)
- : NamedDecl(K, DC, Loc, Using ? Using->getDeclName() : DeclarationName()),
- redeclarable_base(C), UsingOrNextShadow(cast<NamedDecl>(Using)) {
+ SourceLocation Loc, DeclarationName Name,
+ BaseUsingDecl *Introducer, NamedDecl *Target)
+ : NamedDecl(K, DC, Loc, Name), redeclarable_base(C),
+ UsingOrNextShadow(Introducer) {
if (Target)
setTargetDecl(Target);
setImplicit();
@@ -3000,12 +2987,12 @@
return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell());
}
-UsingDecl *UsingShadowDecl::getUsingDecl() const {
+BaseUsingDecl *UsingShadowDecl::getIntroducer() const {
const UsingShadowDecl *Shadow = this;
while (const auto *NextShadow =
dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
Shadow = NextShadow;
- return cast<UsingDecl>(Shadow->UsingOrNextShadow);
+ return cast<BaseUsingDecl>(Shadow->UsingOrNextShadow);
}
void ConstructorUsingShadowDecl::anchor() {}
@@ -3024,25 +3011,25 @@
}
CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const {
- return getUsingDecl()->getQualifier()->getAsRecordDecl();
+ return getIntroducer()->getQualifier()->getAsRecordDecl();
}
-void UsingDecl::anchor() {}
+void BaseUsingDecl::anchor() {}
-void UsingDecl::addShadowDecl(UsingShadowDecl *S) {
+void BaseUsingDecl::addShadowDecl(UsingShadowDecl *S) {
assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() &&
"declaration already in set");
- assert(S->getUsingDecl() == this);
+ assert(S->getIntroducer() == this);
if (FirstUsingShadow.getPointer())
S->UsingOrNextShadow = FirstUsingShadow.getPointer();
FirstUsingShadow.setPointer(S);
}
-void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
+void BaseUsingDecl::removeShadowDecl(UsingShadowDecl *S) {
assert(std::find(shadow_begin(), shadow_end(), S) != shadow_end() &&
"declaration not in set");
- assert(S->getUsingDecl() == this);
+ assert(S->getIntroducer() == this);
// Remove S from the shadow decl chain. This is O(n) but hopefully rare.
@@ -3060,6 +3047,8 @@
S->UsingOrNextShadow = this;
}
+void UsingDecl::anchor() {}
+
UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo,
@@ -3079,6 +3068,23 @@
return SourceRange(Begin, getNameInfo().getEndLoc());
}
+void UsingEnumDecl::anchor() {}
+
+UsingEnumDecl *UsingEnumDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UL, SourceLocation EL,
+ SourceLocation NL, EnumDecl *Enum) {
+ return new (C, DC) UsingEnumDecl(DC, Enum->getDeclName(), UL, EL, NL, Enum);
+}
+
+UsingEnumDecl *UsingEnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) UsingEnumDecl(nullptr, DeclarationName(), SourceLocation(),
+ SourceLocation(), SourceLocation(), nullptr);
+}
+
+SourceRange UsingEnumDecl::getSourceRange() const {
+ return SourceRange(EnumLocation, getLocation());
+}
+
void UsingPackDecl::anchor() {}
UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC,
@@ -3149,6 +3155,25 @@
SourceLocation(), nullptr, SourceLocation());
}
+UnresolvedUsingIfExistsDecl *
+UnresolvedUsingIfExistsDecl::Create(ASTContext &Ctx, DeclContext *DC,
+ SourceLocation Loc, DeclarationName Name) {
+ return new (Ctx, DC) UnresolvedUsingIfExistsDecl(DC, Loc, Name);
+}
+
+UnresolvedUsingIfExistsDecl *
+UnresolvedUsingIfExistsDecl::CreateDeserialized(ASTContext &Ctx, unsigned ID) {
+ return new (Ctx, ID)
+ UnresolvedUsingIfExistsDecl(nullptr, SourceLocation(), DeclarationName());
+}
+
+UnresolvedUsingIfExistsDecl::UnresolvedUsingIfExistsDecl(DeclContext *DC,
+ SourceLocation Loc,
+ DeclarationName Name)
+ : NamedDecl(Decl::UnresolvedUsingIfExists, DC, Loc, Name) {}
+
+void UnresolvedUsingIfExistsDecl::anchor() {}
+
void StaticAssertDecl::anchor() {}
StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
@@ -3178,12 +3203,6 @@
return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr);
}
-ValueDecl *BindingDecl::getDecomposedDecl() const {
- ExternalASTSource *Source =
- Decomp.isOffset() ? getASTContext().getExternalSource() : nullptr;
- return cast_or_null<ValueDecl>(Decomp.get(Source));
-}
-
VarDecl *BindingDecl::getHoldingVar() const {
Expr *B = getBinding();
if (!B)
diff --git a/src/llvm-project/clang/lib/AST/DeclObjC.cpp b/src/llvm-project/clang/lib/AST/DeclObjC.cpp
index 5f82fce..6e790f0 100644
--- a/src/llvm-project/clang/lib/AST/DeclObjC.cpp
+++ b/src/llvm-project/clang/lib/AST/DeclObjC.cpp
@@ -826,7 +826,8 @@
}
bool ObjCMethodDecl::isDirectMethod() const {
- return hasAttr<ObjCDirectAttr>();
+ return hasAttr<ObjCDirectAttr>() &&
+ !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
}
bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
@@ -2295,6 +2296,11 @@
ObjCSubstitutionContext::Property);
}
+bool ObjCPropertyDecl::isDirectProperty() const {
+ return (PropertyAttributes & ObjCPropertyAttribute::kind_direct) &&
+ !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
+}
+
//===----------------------------------------------------------------------===//
// ObjCPropertyImplDecl
//===----------------------------------------------------------------------===//
diff --git a/src/llvm-project/clang/lib/AST/DeclPrinter.cpp b/src/llvm-project/clang/lib/AST/DeclPrinter.cpp
index ca64f8f..4dcf3d0 100644
--- a/src/llvm-project/clang/lib/AST/DeclPrinter.cpp
+++ b/src/llvm-project/clang/lib/AST/DeclPrinter.cpp
@@ -98,6 +98,7 @@
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingEnumDecl(UsingEnumDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
void VisitOMPAllocateDecl(OMPAllocateDecl *D);
@@ -110,8 +111,12 @@
void printTemplateParameters(const TemplateParameterList *Params,
bool OmitTemplateKW = false);
- void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args);
- void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args);
+ void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args,
+ const TemplateParameterList *Params,
+ bool TemplOverloaded);
+ void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
+ const TemplateParameterList *Params,
+ bool TemplOverloaded);
void prettyPrintAttributes(Decl *D);
void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
@@ -341,7 +346,8 @@
SimpleInit = Init;
if (SimpleInit)
- SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
+ SimpleInit->printPretty(Out, nullptr, Policy, Indentation, "\n",
+ &Context);
else {
for (unsigned I = 0; I != NumArgs; ++I) {
assert(Args[I] != nullptr && "Expected non-null Expr");
@@ -350,7 +356,8 @@
if (I)
Out << ", ";
- Args[I]->printPretty(Out, nullptr, Policy, Indentation);
+ Args[I]->printPretty(Out, nullptr, Policy, Indentation, "\n",
+ &Context);
}
}
}
@@ -568,13 +575,14 @@
}
static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
- PrintingPolicy &Policy,
- unsigned Indentation) {
+ PrintingPolicy &Policy, unsigned Indentation,
+ const ASTContext &Context) {
std::string Proto = "explicit";
llvm::raw_string_ostream EOut(Proto);
if (ES.getExpr()) {
EOut << "(";
- ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation);
+ ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation, "\n",
+ &Context);
EOut << ")";
}
EOut << " ";
@@ -616,7 +624,7 @@
if (D->isConsteval()) Out << "consteval ";
ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D);
if (ExplicitSpec.isSpecified())
- printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation);
+ printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation, Context);
}
PrintingPolicy SubPolicy(Policy);
@@ -641,11 +649,16 @@
llvm::raw_string_ostream POut(Proto);
DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();
+ const TemplateParameterList *TPL = D->getTemplateSpecializationInfo()
+ ->getTemplate()
+ ->getTemplateParameters();
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
- TArgPrinter.printTemplateArguments(TArgAsWritten->arguments());
+ TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), TPL,
+ /*TemplOverloaded*/ true);
else if (const TemplateArgumentList *TArgs =
D->getTemplateSpecializationArgs())
- TArgPrinter.printTemplateArguments(TArgs->asArray());
+ TArgPrinter.printTemplateArguments(TArgs->asArray(), TPL,
+ /*TemplOverloaded*/ true);
}
QualType Ty = D->getType();
@@ -720,7 +733,7 @@
Proto += "(";
llvm::raw_string_ostream EOut(Proto);
FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
- Indentation);
+ Indentation, "\n", &Context);
EOut.flush();
Proto += EOut.str();
Proto += ")";
@@ -744,7 +757,8 @@
if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) {
Out << " requires ";
- TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation);
+ TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation,
+ "\n", &Context);
}
} else {
Ty.print(Out, Policy, Proto);
@@ -776,7 +790,8 @@
Out << ' ';
if (D->getBody())
- D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
+ D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation, "\n",
+ &Context);
} else {
if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D))
Out << " {}";
@@ -821,7 +836,8 @@
if (D->isBitField()) {
Out << " : ";
- D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation);
+ D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation, "\n",
+ &Context);
}
Expr *Init = D->getInClassInitializer();
@@ -830,7 +846,7 @@
Out << " ";
else
Out << " = ";
- Init->printPretty(Out, nullptr, Policy, Indentation);
+ Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
}
prettyPrintAttributes(D);
}
@@ -895,7 +911,7 @@
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressSpecifiers = false;
SubPolicy.IncludeTagDefinition = false;
- Init->printPretty(Out, nullptr, SubPolicy, Indentation);
+ Init->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", &Context);
if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
Out << ")";
}
@@ -909,7 +925,8 @@
void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
Out << "__asm (";
- D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation);
+ D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation, "\n",
+ &Context);
Out << ")";
}
@@ -920,10 +937,11 @@
void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
Out << "static_assert(";
- D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation);
+ D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n",
+ &Context);
if (StringLiteral *SL = D->getMessage()) {
Out << ", ";
- SL->printPretty(Out, nullptr, Policy, Indentation);
+ SL->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
}
Out << ")";
}
@@ -980,7 +998,9 @@
if (const auto *TST =
dyn_cast<TemplateSpecializationType>(TSI->getType()))
Args = TST->template_arguments();
- printTemplateArguments(Args);
+ printTemplateArguments(
+ Args, S->getSpecializedTemplate()->getTemplateParameters(),
+ /*TemplOverloaded*/ false);
}
}
@@ -1072,22 +1092,36 @@
Out << ' ';
}
-void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args) {
+void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args,
+ const TemplateParameterList *Params,
+ bool TemplOverloaded) {
Out << "<";
for (size_t I = 0, E = Args.size(); I < E; ++I) {
if (I)
Out << ", ";
- Args[I].print(Policy, Out);
+ if (TemplOverloaded || !Params)
+ Args[I].print(Policy, Out, /*IncludeType*/ true);
+ else
+ Args[I].print(
+ Policy, Out,
+ TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
}
Out << ">";
}
-void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args) {
+void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
+ const TemplateParameterList *Params,
+ bool TemplOverloaded) {
Out << "<";
for (size_t I = 0, E = Args.size(); I < E; ++I) {
if (I)
Out << ", ";
- Args[I].getArgument().print(Policy, Out);
+ if (TemplOverloaded)
+ Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true);
+ else
+ Args[I].getArgument().print(
+ Policy, Out,
+ TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
}
Out << ">";
}
@@ -1110,9 +1144,8 @@
Visit(TD);
else if (const auto *Concept = dyn_cast<ConceptDecl>(D)) {
Out << "concept " << Concept->getName() << " = " ;
- Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy,
- Indentation);
- Out << ";";
+ Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy, Indentation,
+ "\n", &Context);
}
}
@@ -1271,7 +1304,8 @@
if (OMD->getBody() && !Policy.TerseOutput) {
Out << ' ';
- OMD->getBody()->printPretty(Out, nullptr, Policy);
+ OMD->getBody()->printPretty(Out, nullptr, Policy, Indentation, "\n",
+ &Context);
}
else if (Policy.PolishForDeclaration)
Out << ';';
@@ -1575,6 +1609,10 @@
Out << *D;
}
+void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) {
+ Out << "using enum " << D->getEnumDecl();
+}
+
void
DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
Out << "using typename ";
@@ -1651,7 +1689,7 @@
Out << " : ";
D->getType().print(Out, Policy);
Out << " : ";
- D->getCombiner()->printPretty(Out, nullptr, Policy, 0);
+ D->getCombiner()->printPretty(Out, nullptr, Policy, 0, "\n", &Context);
Out << ")";
if (auto *Init = D->getInitializer()) {
Out << " initializer(";
@@ -1665,7 +1703,7 @@
case OMPDeclareReductionDecl::CallInit:
break;
}
- Init->printPretty(Out, nullptr, Policy, 0);
+ Init->printPretty(Out, nullptr, Policy, 0, "\n", &Context);
if (D->getInitializerKind() == OMPDeclareReductionDecl::DirectInit)
Out << ")";
Out << ")";
@@ -1693,7 +1731,7 @@
}
void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
- D->getInit()->printPretty(Out, nullptr, Policy, Indentation);
+ D->getInit()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
}
void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {
@@ -1727,6 +1765,7 @@
if (NTTP->hasDefaultArgument()) {
Out << " = ";
- NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation);
+ NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation,
+ "\n", &Context);
}
}
diff --git a/src/llvm-project/clang/lib/AST/DeclTemplate.cpp b/src/llvm-project/clang/lib/AST/DeclTemplate.cpp
index 25235c5..ec8b00a 100644
--- a/src/llvm-project/clang/lib/AST/DeclTemplate.cpp
+++ b/src/llvm-project/clang/lib/AST/DeclTemplate.cpp
@@ -68,12 +68,16 @@
if (!IsPack &&
TTP->getTemplateParameters()->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
- } else if (const TypeConstraint *TC =
- cast<TemplateTypeParmDecl>(P)->getTypeConstraint()) {
- if (TC->getImmediatelyDeclaredConstraint()
- ->containsUnexpandedParameterPack())
- ContainsUnexpandedParameterPack = true;
- HasConstrainedParameters = true;
+ } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
+ if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
+ if (TC->getImmediatelyDeclaredConstraint()
+ ->containsUnexpandedParameterPack())
+ ContainsUnexpandedParameterPack = true;
+ }
+ if (TTP->hasTypeConstraint())
+ HasConstrainedParameters = true;
+ } else {
+ llvm_unreachable("unexpcted template parameter type");
}
// FIXME: If a default argument contains an unexpanded parameter pack, the
// template parameter list does too.
@@ -86,6 +90,30 @@
}
}
+bool TemplateParameterList::containsUnexpandedParameterPack() const {
+ if (ContainsUnexpandedParameterPack)
+ return true;
+ if (!HasConstrainedParameters)
+ return false;
+
+ // An implicit constrained parameter might have had a use of an unexpanded
+ // pack added to it after the template parameter list was created. All
+ // implicit parameters are at the end of the parameter list.
+ for (const NamedDecl *Param : llvm::reverse(asArray())) {
+ if (!Param->isImplicit())
+ break;
+
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ const auto *TC = TTP->getTypeConstraint();
+ if (TC && TC->getImmediatelyDeclaredConstraint()
+ ->containsUnexpandedParameterPack())
+ return true;
+ }
+ }
+
+ return false;
+}
+
TemplateParameterList *
TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
@@ -167,6 +195,18 @@
return HasRequiresClause || HasConstrainedParameters;
}
+bool TemplateParameterList::shouldIncludeTypeForArgument(
+ const TemplateParameterList *TPL, unsigned Idx) {
+ if (!TPL || Idx >= TPL->size())
+ return true;
+ const NamedDecl *TemplParam = TPL->getParam(Idx);
+ if (const auto *ParamValueDecl =
+ dyn_cast<NonTypeTemplateParmDecl>(TemplParam))
+ if (ParamValueDecl->getType()->getContainedDeducedType())
+ return true;
+ return false;
+}
+
namespace clang {
void *allocateDefaultArgStorageChain(const ASTContext &C) {
@@ -1420,8 +1460,9 @@
ConceptName.printName(OS, Policy);
if (hasExplicitTemplateArgs()) {
OS << "<";
+ // FIXME: Find corresponding parameter for argument
for (auto &ArgLoc : ArgsAsWritten->arguments())
- ArgLoc.getArgument().print(Policy, OS);
+ ArgLoc.getArgument().print(Policy, OS, /*IncludeType*/ false);
OS << ">";
}
}
diff --git a/src/llvm-project/clang/lib/AST/DeclarationName.cpp b/src/llvm-project/clang/lib/AST/DeclarationName.cpp
index ecf676c..56cf4b4 100644
--- a/src/llvm-project/clang/lib/AST/DeclarationName.cpp
+++ b/src/llvm-project/clang/lib/AST/DeclarationName.cpp
@@ -392,14 +392,13 @@
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
- NamedType.TInfo = nullptr;
+ setNamedTypeLoc(nullptr);
break;
case DeclarationName::CXXOperatorName:
- CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
- CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
+ setCXXOperatorNameRange(SourceRange());
break;
case DeclarationName::CXXLiteralOperatorName:
- CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
+ setCXXLiteralOperatorNameLoc(SourceLocation());
break;
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
@@ -426,7 +425,7 @@
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
- if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
+ if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
return TInfo->getType()->containsUnexpandedParameterPack();
return Name.getCXXNameType()->containsUnexpandedParameterPack();
@@ -449,7 +448,7 @@
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
- if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
+ if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
return TInfo->getType()->isInstantiationDependentType();
return Name.getCXXNameType()->isInstantiationDependentType();
@@ -486,7 +485,7 @@
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
- if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
+ if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo()) {
if (Name.getNameKind() == DeclarationName::CXXDestructorName)
OS << '~';
else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
@@ -508,20 +507,16 @@
case DeclarationName::CXXDeductionGuideName:
return NameLoc;
- case DeclarationName::CXXOperatorName: {
- unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
- return SourceLocation::getFromRawEncoding(raw);
- }
+ case DeclarationName::CXXOperatorName:
+ return LocInfo.getCXXOperatorNameEndLoc();
- case DeclarationName::CXXLiteralOperatorName: {
- unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
- return SourceLocation::getFromRawEncoding(raw);
- }
+ case DeclarationName::CXXLiteralOperatorName:
+ return LocInfo.getCXXLiteralOperatorNameLoc();
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
- if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
+ if (TypeSourceInfo *TInfo = LocInfo.getNamedTypeInfo())
return TInfo->getTypeLoc().getEndLoc();
else
return NameLoc;
diff --git a/src/llvm-project/clang/lib/AST/Expr.cpp b/src/llvm-project/clang/lib/AST/Expr.cpp
index adb3303..11f10d4 100644
--- a/src/llvm-project/clang/lib/AST/Expr.cpp
+++ b/src/llvm-project/clang/lib/AST/Expr.cpp
@@ -32,6 +32,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
@@ -111,7 +112,7 @@
}
} else if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
if (BO->getOpcode() == BO_PtrMemD) {
- assert(BO->getRHS()->isRValue());
+ assert(BO->getRHS()->isPRValue());
E = BO->getLHS();
const MemberPointerType *MPT =
BO->getRHS()->getType()->getAs<MemberPointerType>();
@@ -489,6 +490,8 @@
void DeclRefExpr::setDecl(ValueDecl *NewD) {
D = NewD;
+ if (getType()->isUndeducedType())
+ setType(NewD->getType());
setDependence(computeDependence(this, NewD->getASTContext()));
}
@@ -503,6 +506,70 @@
return getNameInfo().getEndLoc();
}
+SYCLUniqueStableNameExpr::SYCLUniqueStableNameExpr(SourceLocation OpLoc,
+ SourceLocation LParen,
+ SourceLocation RParen,
+ QualType ResultTy,
+ TypeSourceInfo *TSI)
+ : Expr(SYCLUniqueStableNameExprClass, ResultTy, VK_PRValue, OK_Ordinary),
+ OpLoc(OpLoc), LParen(LParen), RParen(RParen) {
+ setTypeSourceInfo(TSI);
+ setDependence(computeDependence(this));
+}
+
+SYCLUniqueStableNameExpr::SYCLUniqueStableNameExpr(EmptyShell Empty,
+ QualType ResultTy)
+ : Expr(SYCLUniqueStableNameExprClass, ResultTy, VK_PRValue, OK_Ordinary) {}
+
+SYCLUniqueStableNameExpr *
+SYCLUniqueStableNameExpr::Create(const ASTContext &Ctx, SourceLocation OpLoc,
+ SourceLocation LParen, SourceLocation RParen,
+ TypeSourceInfo *TSI) {
+ QualType ResultTy = Ctx.getPointerType(Ctx.CharTy.withConst());
+ return new (Ctx)
+ SYCLUniqueStableNameExpr(OpLoc, LParen, RParen, ResultTy, TSI);
+}
+
+SYCLUniqueStableNameExpr *
+SYCLUniqueStableNameExpr::CreateEmpty(const ASTContext &Ctx) {
+ QualType ResultTy = Ctx.getPointerType(Ctx.CharTy.withConst());
+ return new (Ctx) SYCLUniqueStableNameExpr(EmptyShell(), ResultTy);
+}
+
+std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context) const {
+ return SYCLUniqueStableNameExpr::ComputeName(Context,
+ getTypeSourceInfo()->getType());
+}
+
+std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context,
+ QualType Ty) {
+ auto MangleCallback = [](ASTContext &Ctx,
+ const NamedDecl *ND) -> llvm::Optional<unsigned> {
+ // This replaces the 'lambda number' in the mangling with a unique number
+ // based on its order in the declaration. To provide some level of visual
+ // notability (actual uniqueness from normal lambdas isn't necessary, as
+ // these are used differently), we add 10,000 to the number.
+ // For example:
+ // _ZTSZ3foovEUlvE10005_
+ // Demangles to: typeinfo name for foo()::'lambda10005'()
+ // Note that the mangler subtracts 2, since with normal lambdas the lambda
+ // mangling number '0' is an anonymous struct mangle, and '1' is omitted.
+ // So 10,002 results in the first number being 10,000.
+ if (Ctx.IsSYCLKernelNamingDecl(ND))
+ return 10'002 + Ctx.GetSYCLKernelNamingIndex(ND);
+ return llvm::None;
+ };
+ std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
+ Context, Context.getDiagnostics(), MangleCallback)};
+
+ std::string Buffer;
+ Buffer.reserve(128);
+ llvm::raw_string_ostream Out(Buffer);
+ Ctx->mangleTypeName(Ty, Out);
+
+ return Out.str();
+}
+
PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
StringLiteral *SL)
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) {
@@ -705,7 +772,9 @@
StringRef Param = Params->getParam(i)->getName();
if (Param.empty()) continue;
TOut << Param << " = ";
- Args.get(i).print(Policy, TOut);
+ Args.get(i).print(
+ Policy, TOut,
+ TemplateParameterList::shouldIncludeTypeForArgument(Params, i));
TOut << ", ";
}
}
@@ -721,7 +790,7 @@
StringRef Param = Params->getParam(i)->getName();
if (Param.empty()) continue;
TOut << Param << " = ";
- Args->get(i).print(Policy, TOut);
+ Args->get(i).print(Policy, TOut, /*IncludeType*/ true);
TOut << ", ";
}
}
@@ -811,7 +880,7 @@
IntegerLiteral::IntegerLiteral(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l)
- : Expr(IntegerLiteralClass, type, VK_RValue, OK_Ordinary), Loc(l) {
+ : Expr(IntegerLiteralClass, type, VK_PRValue, OK_Ordinary), Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
assert(V.getBitWidth() == C.getIntWidth(type) &&
"Integer type is not the correct size for constant.");
@@ -833,7 +902,7 @@
FixedPointLiteral::FixedPointLiteral(const ASTContext &C, const llvm::APInt &V,
QualType type, SourceLocation l,
unsigned Scale)
- : Expr(FixedPointLiteralClass, type, VK_RValue, OK_Ordinary), Loc(l),
+ : Expr(FixedPointLiteralClass, type, VK_PRValue, OK_Ordinary), Loc(l),
Scale(Scale) {
assert(type->isFixedPointType() && "Illegal type in FixedPointLiteral");
assert(V.getBitWidth() == C.getTypeInfo(type).Width &&
@@ -865,9 +934,79 @@
return std::string(S.str());
}
+void CharacterLiteral::print(unsigned Val, CharacterKind Kind,
+ raw_ostream &OS) {
+ switch (Kind) {
+ case CharacterLiteral::Ascii:
+ break; // no prefix.
+ case CharacterLiteral::Wide:
+ OS << 'L';
+ break;
+ case CharacterLiteral::UTF8:
+ OS << "u8";
+ break;
+ case CharacterLiteral::UTF16:
+ OS << 'u';
+ break;
+ case CharacterLiteral::UTF32:
+ OS << 'U';
+ break;
+ }
+
+ switch (Val) {
+ case '\\':
+ OS << "'\\\\'";
+ break;
+ case '\'':
+ OS << "'\\''";
+ break;
+ case '\a':
+ // TODO: K&R: the meaning of '\\a' is different in traditional C
+ OS << "'\\a'";
+ break;
+ case '\b':
+ OS << "'\\b'";
+ break;
+ // Nonstandard escape sequence.
+ /*case '\e':
+ OS << "'\\e'";
+ break;*/
+ case '\f':
+ OS << "'\\f'";
+ break;
+ case '\n':
+ OS << "'\\n'";
+ break;
+ case '\r':
+ OS << "'\\r'";
+ break;
+ case '\t':
+ OS << "'\\t'";
+ break;
+ case '\v':
+ OS << "'\\v'";
+ break;
+ default:
+ // A character literal might be sign-extended, which
+ // would result in an invalid \U escape sequence.
+ // FIXME: multicharacter literals such as '\xFF\xFF\xFF\xFF'
+ // are not correctly handled.
+ if ((Val & ~0xFFu) == ~0xFFu && Kind == CharacterLiteral::Ascii)
+ Val &= 0xFFu;
+ if (Val < 256 && isPrintable((unsigned char)Val))
+ OS << "'" << (char)Val << "'";
+ else if (Val < 256)
+ OS << "'\\x" << llvm::format("%02x", Val) << "'";
+ else if (Val <= 0xFFFF)
+ OS << "'\\u" << llvm::format("%04x", Val) << "'";
+ else
+ OS << "'\\U" << llvm::format("%08x", Val) << "'";
+ }
+}
+
FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
- : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary), Loc(L) {
+ : Expr(FloatingLiteralClass, Type, VK_PRValue, OK_Ordinary), Loc(L) {
setSemantics(V.getSemantics());
FloatingLiteralBits.IsExact = isexact;
setValue(C, V);
@@ -1261,7 +1400,7 @@
for (unsigned I = Args.size(); I != NumArgs; ++I)
setArg(I, nullptr);
- setDependence(computeDependence(this, PreArgs));
+ this->computeDependence();
CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
if (hasStoredFPFeatures())
@@ -1391,8 +1530,15 @@
if (isa<CXXPseudoDestructorExpr>(Callee->IgnoreParens()))
return Ctx.VoidTy;
+ if (isa<UnresolvedMemberExpr>(Callee->IgnoreParens()))
+ return Ctx.DependentTy;
+
// This should never be overloaded and so should never return null.
CalleeType = Expr::findBoundMemberType(Callee);
+ assert(!CalleeType.isNull());
+ } else if (CalleeType->isDependentType() ||
+ CalleeType->isSpecificPlaceholderType(BuiltinType::Overload)) {
+ return Ctx.DependentTy;
}
const FunctionType *FnType = CalleeType->castAs<FunctionType>();
@@ -1455,7 +1601,7 @@
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr *> exprs,
SourceLocation RParenLoc)
- : Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary),
+ : Expr(OffsetOfExprClass, type, VK_PRValue, OK_Ordinary),
OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi),
NumComps(comps.size()), NumExprs(exprs.size()) {
for (unsigned i = 0; i != comps.size(); ++i)
@@ -1477,7 +1623,7 @@
UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
UnaryExprOrTypeTrait ExprKind, Expr *E, QualType resultType,
SourceLocation op, SourceLocation rp)
- : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary),
+ : Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_PRValue, OK_Ordinary),
OpLoc(op), RParenLoc(rp) {
assert(ExprKind <= UETT_Last && "invalid enum value!");
UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
@@ -1578,8 +1724,10 @@
return new (Mem) MemberExpr(EmptyShell());
}
-void MemberExpr::setMemberDecl(ValueDecl *D) {
- MemberDecl = D;
+void MemberExpr::setMemberDecl(ValueDecl *NewD) {
+ MemberDecl = NewD;
+ if (getType()->isUndeducedType())
+ setType(NewD->getType());
setDependence(computeDependence(this));
}
@@ -1663,7 +1811,7 @@
auto Ty = getType();
auto SETy = getSubExpr()->getType();
assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy));
- if (isRValue() && !Ty->isDependentType() && !SETy->isDependentType()) {
+ if (isPRValue() && !Ty->isDependentType() && !SETy->isDependentType()) {
Ty = Ty->getPointeeType();
SETy = SETy->getPointeeType();
}
@@ -1708,6 +1856,7 @@
case CK_FixedPointCast:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
goto CheckNoBasePath;
@@ -1768,6 +1917,7 @@
SubExpr =
skipImplicitTemporary(cast<CXXConstructExpr>(SubExpr->IgnoreImplicit())->getArg(0));
else if (E->getCastKind() == CK_UserDefinedConversion) {
+ SubExpr = SubExpr->IgnoreImplicit();
assert((isa<CXXMemberCallExpr>(SubExpr) ||
isa<BlockExpr>(SubExpr)) &&
"Unexpected SubExpr for CK_UserDefinedConversion.");
@@ -2037,7 +2187,7 @@
SourceLocation BLoc, SourceLocation RParenLoc,
DeclContext *ParentContext)
: Expr(SourceLocExprClass, getDecayedSourceLocExprType(Ctx, Kind),
- VK_RValue, OK_Ordinary),
+ VK_PRValue, OK_Ordinary),
BuiltinLoc(BLoc), RParenLoc(RParenLoc), ParentContext(ParentContext) {
SourceLocExprBits.Kind = Kind;
setDependence(ExprDependence::None);
@@ -2083,8 +2233,11 @@
};
switch (getIdentKind()) {
- case SourceLocExpr::File:
- return MakeStringLiteral(PLoc.getFilename());
+ case SourceLocExpr::File: {
+ SmallString<256> Path(PLoc.getFilename());
+ Ctx.getLangOpts().remapPathPrefix(Path);
+ return MakeStringLiteral(Path);
+ }
case SourceLocExpr::Function: {
const Decl *CurDecl = dyn_cast_or_null<Decl>(Context);
return MakeStringLiteral(
@@ -2105,7 +2258,7 @@
InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
ArrayRef<Expr *> initExprs, SourceLocation rbraceloc)
- : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary),
+ : Expr(InitListExprClass, QualType(), VK_PRValue, OK_Ordinary),
InitExprs(C, initExprs.size()), LBraceLoc(lbraceloc),
RBraceLoc(rbraceloc), AltForm(nullptr, true) {
sawArrayRangeDesignator(false);
@@ -2175,7 +2328,7 @@
// Don't confuse aggregate initialization of a struct X { X &x; }; with a
// transparent struct copy.
- if (!getInit(0)->isRValue() && getType()->isRecordType())
+ if (!getInit(0)->isPRValue() && getType()->isRecordType())
return false;
return getType().getCanonicalType() ==
@@ -2256,7 +2409,7 @@
// In C++11, discarded-value expressions of a certain form are special,
// according to [expr]p10:
// The lvalue-to-rvalue conversion (4.1) is applied only if the
- // expression is an lvalue of volatile-qualified type and it has
+ // expression is a glvalue of volatile-qualified type and it has
// one of the following forms:
if (!isGLValue() || !getType().isVolatileQualified())
return false;
@@ -3300,6 +3453,7 @@
case SourceLocExprClass:
case ConceptSpecializationExprClass:
case RequiresExprClass:
+ case SYCLUniqueStableNameExprClass:
// These never have a side-effect.
return false;
@@ -3723,8 +3877,7 @@
const ObjCPropertyRefExpr *Expr::getObjCProperty() const {
const Expr *E = this;
while (true) {
- assert((E->getValueKind() == VK_LValue &&
- E->getObjectKind() == OK_ObjCProperty) &&
+ assert((E->isLValue() && E->getObjectKind() == OK_ObjCProperty) &&
"expression is not a property reference");
E = E->IgnoreParenCasts();
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
@@ -3763,7 +3916,7 @@
while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CK_LValueToRValue ||
- (ICE->getValueKind() != VK_RValue && ICE->getCastKind() == CK_NoOp))
+ (ICE->isGLValue() && ICE->getCastKind() == CK_NoOp))
E = ICE->getSubExpr()->IgnoreParens();
else
break;
@@ -3810,8 +3963,7 @@
const Expr *E = this->IgnoreParens();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->getValueKind() != VK_RValue &&
- ICE->getCastKind() == CK_NoOp)
+ if (ICE->isGLValue() && ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr()->IgnoreParens();
else
break;
@@ -3860,7 +4012,7 @@
// template parameters.
const auto *DRE1 = cast<DeclRefExpr>(E1);
const auto *DRE2 = cast<DeclRefExpr>(E2);
- return DRE1->isRValue() && DRE2->isRValue() &&
+ return DRE1->isPRValue() && DRE2->isPRValue() &&
DRE1->getDecl() == DRE2->getDecl();
}
case ImplicitCastExprClass: {
@@ -4018,7 +4170,7 @@
ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr *> args,
QualType Type, SourceLocation BLoc,
SourceLocation RP)
- : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary),
+ : Expr(ShuffleVectorExprClass, Type, VK_PRValue, OK_Ordinary),
BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(args.size()) {
SubExprs = new (C) Stmt*[args.size()];
for (unsigned i = 0; i != args.size(); i++)
@@ -4065,7 +4217,7 @@
ArrayRef<TypeSourceInfo *> AssocTypes, ArrayRef<Expr *> AssocExprs,
SourceLocation DefaultLoc, SourceLocation RParenLoc,
bool ContainsUnexpandedParameterPack)
- : Expr(GenericSelectionExprClass, Context.DependentTy, VK_RValue,
+ : Expr(GenericSelectionExprClass, Context.DependentTy, VK_PRValue,
OK_Ordinary),
NumAssocs(AssocExprs.size()), ResultIndex(ResultDependentIndex),
DefaultLoc(DefaultLoc), RParenLoc(RParenLoc) {
@@ -4269,7 +4421,7 @@
SourceLocation lBraceLoc,
Expr *baseExpr,
SourceLocation rBraceLoc)
- : Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_RValue,
+ : Expr(DesignatedInitUpdateExprClass, baseExpr->getType(), VK_PRValue,
OK_Ordinary) {
BaseAndUpdaterExprs[0] = baseExpr;
@@ -4291,7 +4443,7 @@
ParenListExpr::ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs,
SourceLocation RParenLoc)
- : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary),
+ : Expr(ParenListExprClass, QualType(), VK_PRValue, OK_Ordinary),
LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
ParenListExprBits.NumExprs = Exprs.size();
@@ -4467,7 +4619,7 @@
ExprValueKind VK;
if (resultIndex == NoResult) {
type = C.VoidTy;
- VK = VK_RValue;
+ VK = VK_PRValue;
} else {
assert(resultIndex < semantics.size());
type = semantics[resultIndex]->getType();
@@ -4527,7 +4679,7 @@
AtomicExpr::AtomicExpr(SourceLocation BLoc, ArrayRef<Expr *> args, QualType t,
AtomicOp op, SourceLocation RP)
- : Expr(AtomicExprClass, t, VK_RValue, OK_Ordinary),
+ : Expr(AtomicExprClass, t, VK_PRValue, OK_Ordinary),
NumSubExprs(args.size()), BuiltinLoc(BLoc), RParenLoc(RP), Op(op) {
assert(args.size() == getNumSubExprs(op) && "wrong number of subexpressions");
for (unsigned i = 0; i != args.size(); i++)
diff --git a/src/llvm-project/clang/lib/AST/ExprCXX.cpp b/src/llvm-project/clang/lib/AST/ExprCXX.cpp
index 8dc9d42..c98cfd7 100644
--- a/src/llvm-project/clang/lib/AST/ExprCXX.cpp
+++ b/src/llvm-project/clang/lib/AST/ExprCXX.cpp
@@ -187,7 +187,7 @@
Expr *Initializer, QualType Ty,
TypeSourceInfo *AllocatedTypeInfo, SourceRange Range,
SourceRange DirectInitRange)
- : Expr(CXXNewExprClass, Ty, VK_RValue, OK_Ordinary),
+ : Expr(CXXNewExprClass, Ty, VK_PRValue, OK_Ordinary),
OperatorNew(OperatorNew), OperatorDelete(OperatorDelete),
AllocatedTypeInfo(AllocatedTypeInfo), Range(Range),
DirectInitRange(DirectInitRange) {
@@ -275,7 +275,8 @@
}
bool CXXNewExpr::shouldNullCheckAllocation() const {
- return getOperatorNew()
+ return !getOperatorNew()->hasAttr<ReturnsNonNullAttr>() &&
+ getOperatorNew()
->getType()
->castAs<FunctionProtoType>()
->isNothrow() &&
@@ -321,7 +322,7 @@
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc,
SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType)
- : Expr(CXXPseudoDestructorExprClass, Context.BoundMemberTy, VK_RValue,
+ : Expr(CXXPseudoDestructorExprClass, Context.BoundMemberTy, VK_PRValue,
OK_Ordinary),
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
OperatorLoc(OperatorLoc), QualifierLoc(QualifierLoc),
@@ -670,6 +671,7 @@
return cast<CXXMethodDecl>(MemExpr->getMemberDecl());
// FIXME: Will eventually need to cope with member pointers.
+ // NOTE: Update makeTailCallIfSwiftAsync on fixing this.
return nullptr;
}
@@ -951,9 +953,9 @@
SourceLocation Loc, FieldDecl *Field,
QualType Ty, DeclContext *UsedContext)
: Expr(CXXDefaultInitExprClass, Ty.getNonLValueExprType(Ctx),
- Ty->isLValueReferenceType()
- ? VK_LValue
- : Ty->isRValueReferenceType() ? VK_XValue : VK_RValue,
+ Ty->isLValueReferenceType() ? VK_LValue
+ : Ty->isRValueReferenceType() ? VK_XValue
+ : VK_PRValue,
/*FIXME*/ OK_Ordinary),
Field(Field), UsedContext(UsedContext) {
CXXDefaultInitExprBits.Loc = Loc;
@@ -1057,7 +1059,7 @@
bool ListInitialization, bool StdInitListInitialization,
bool ZeroInitialization, ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange)
- : Expr(SC, Ty, VK_RValue, OK_Ordinary), Constructor(Ctor),
+ : Expr(SC, Ty, VK_PRValue, OK_Ordinary), Constructor(Ctor),
ParenOrBraceRange(ParenOrBraceRange), NumArgs(Args.size()) {
CXXConstructExprBits.Elidable = Elidable;
CXXConstructExprBits.HadMultipleCandidates = HadMultipleCandidates;
@@ -1125,7 +1127,7 @@
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack)
- : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary),
+ : Expr(LambdaExprClass, T, VK_PRValue, OK_Ordinary),
IntroducerRange(IntroducerRange), CaptureDefaultLoc(CaptureDefaultLoc),
ClosingBrace(ClosingBrace) {
LambdaExprBits.NumCaptures = CaptureInits.size();
@@ -1326,10 +1328,9 @@
ArrayRef<Expr *> Args,
SourceLocation RParenLoc)
: Expr(CXXUnresolvedConstructExprClass, T,
- (TSI->getType()->isLValueReferenceType()
- ? VK_LValue
- : TSI->getType()->isRValueReferenceType() ? VK_XValue
- : VK_RValue),
+ (TSI->getType()->isLValueReferenceType() ? VK_LValue
+ : TSI->getType()->isRValueReferenceType() ? VK_XValue
+ : VK_PRValue),
OK_Ordinary),
TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
CXXUnresolvedConstructExprBits.NumArgs = Args.size();
@@ -1668,7 +1669,7 @@
TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc, bool Value)
- : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary), Loc(Loc),
+ : Expr(TypeTraitExprClass, T, VK_PRValue, OK_Ordinary), Loc(Loc),
RParenLoc(RParenLoc) {
assert(Kind <= TT_Last && "invalid enum value!");
TypeTraitExprBits.Kind = Kind;
diff --git a/src/llvm-project/clang/lib/AST/ExprClassification.cpp b/src/llvm-project/clang/lib/AST/ExprClassification.cpp
index 0286c73..6998e28 100644
--- a/src/llvm-project/clang/lib/AST/ExprClassification.cpp
+++ b/src/llvm-project/clang/lib/AST/ExprClassification.cpp
@@ -53,8 +53,12 @@
// Enable this assertion for testing.
switch (kind) {
- case Cl::CL_LValue: assert(getValueKind() == VK_LValue); break;
- case Cl::CL_XValue: assert(getValueKind() == VK_XValue); break;
+ case Cl::CL_LValue:
+ assert(isLValue());
+ break;
+ case Cl::CL_XValue:
+ assert(isXValue());
+ break;
case Cl::CL_Function:
case Cl::CL_Void:
case Cl::CL_AddressableVoid:
@@ -64,7 +68,9 @@
case Cl::CL_ClassTemporary:
case Cl::CL_ArrayTemporary:
case Cl::CL_ObjCMessageRValue:
- case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break;
+ case Cl::CL_PRValue:
+ assert(isPRValue());
+ break;
}
Cl::ModifiableType modifiable = Cl::CM_Untested;
@@ -89,7 +95,7 @@
const Expr *E,
ExprValueKind Kind) {
switch (Kind) {
- case VK_RValue:
+ case VK_PRValue:
return Lang.CPlusPlus ? ClassifyTemporary(E->getType()) : Cl::CL_PRValue;
case VK_LValue:
return Cl::CL_LValue;
@@ -424,7 +430,7 @@
// contains only one element. In that case, we look at that element
// for an exact classification. Init list creation takes care of the
// value kind for us, so we only need to fine-tune.
- if (E->isRValue())
+ if (E->isPRValue())
return ClassifyExprValueKind(Lang, E, E->getValueKind());
assert(cast<InitListExpr>(E)->getNumInits() == 1 &&
"Only 1-element init lists can be glvalues.");
@@ -433,6 +439,9 @@
case Expr::CoawaitExprClass:
case Expr::CoyieldExprClass:
return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr());
+ case Expr::SYCLUniqueStableNameExprClass:
+ return Cl::CL_PRValue;
+ break;
}
llvm_unreachable("unhandled expression kind in classification");
diff --git a/src/llvm-project/clang/lib/AST/ExprConcepts.cpp b/src/llvm-project/clang/lib/AST/ExprConcepts.cpp
index d00d832..8cb8625 100644
--- a/src/llvm-project/clang/lib/AST/ExprConcepts.cpp
+++ b/src/llvm-project/clang/lib/AST/ExprConcepts.cpp
@@ -37,7 +37,7 @@
const ASTTemplateArgumentListInfo *ArgsAsWritten,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction)
- : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
+ : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
NamedConcept, ArgsAsWritten),
NumTemplateArgs(ConvertedArgs.size()),
@@ -91,7 +91,7 @@
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack)
- : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
+ : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
DeclarationNameInfo(), NamedConcept, NamedConcept,
nullptr),
@@ -146,7 +146,7 @@
ArrayRef<ParmVarDecl *> LocalParameters,
ArrayRef<concepts::Requirement *> Requirements,
SourceLocation RBraceLoc)
- : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
+ : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
NumLocalParameters(LocalParameters.size()),
NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
RequiresExprBits.IsSatisfied = false;
diff --git a/src/llvm-project/clang/lib/AST/ExprConstant.cpp b/src/llvm-project/clang/lib/AST/ExprConstant.cpp
index 1bdad77..01c0168 100644
--- a/src/llvm-project/clang/lib/AST/ExprConstant.cpp
+++ b/src/llvm-project/clang/lib/AST/ExprConstant.cpp
@@ -101,15 +101,18 @@
/// Given an expression, determine the type used to store the result of
/// evaluating that expression.
static QualType getStorageType(const ASTContext &Ctx, const Expr *E) {
- if (E->isRValue())
+ if (E->isPRValue())
return E->getType();
return Ctx.getLValueReferenceType(E->getType());
}
/// Given a CallExpr, try to get the alloc_size attribute. May return null.
static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) {
- const FunctionDecl *Callee = CE->getDirectCallee();
- return Callee ? Callee->getAttr<AllocSizeAttr>() : nullptr;
+ if (const FunctionDecl *DirectCallee = CE->getDirectCallee())
+ return DirectCallee->getAttr<AllocSizeAttr>();
+ if (const Decl *IndirectCallee = CE->getCalleeDecl())
+ return IndirectCallee->getAttr<AllocSizeAttr>();
+ return nullptr;
}
/// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr.
@@ -926,6 +929,9 @@
/// Whether we're checking for an expression that has undefined behavior.
/// If so, we will produce warnings if we encounter an operation that is
/// always undefined.
+ ///
+ /// Note that we still need to evaluate the expression normally when this
+ /// is set; this is used when evaluating ICEs in C.
bool CheckingForUndefinedBehavior = false;
enum EvaluationMode {
@@ -2294,7 +2300,7 @@
/// produce an appropriate diagnostic.
static bool CheckLiteralType(EvalInfo &Info, const Expr *E,
const LValue *This = nullptr) {
- if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx))
+ if (!E->isPRValue() || E->getType()->isLiteralType(Info.Ctx))
return true;
// C++1y: A constant initializer for an object o [...] may also invoke
@@ -2499,7 +2505,7 @@
static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result,
EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && "missing lvalue-to-rvalue conv in bool condition");
+ assert(E->isPRValue() && "missing lvalue-to-rvalue conv in bool condition");
APValue Val;
if (!Evaluate(Val, Info, E))
return false;
@@ -2714,9 +2720,8 @@
if (Info.checkingForUndefinedBehavior())
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_integer_constant_overflow)
- << Result.toString(10) << E->getType();
- else
- return HandleOverflow(Info, E, Value, E->getType());
+ << toString(Result, 10) << E->getType();
+ return HandleOverflow(Info, E, Value, E->getType());
}
return true;
}
@@ -4563,7 +4568,7 @@
/// Build an lvalue for the object argument of a member function call.
static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object,
LValue &This) {
- if (Object->getType()->isPointerType() && Object->isRValue())
+ if (Object->getType()->isPointerType() && Object->isPRValue())
return EvaluatePointer(Object, This, Info);
if (Object->isGLValue())
@@ -6363,7 +6368,7 @@
// Invent an expression for location purposes.
// FIXME: We shouldn't need to do this.
- OpaqueValueExpr LocE(CallLoc, Info.Ctx.IntTy, VK_RValue);
+ OpaqueValueExpr LocE(CallLoc, Info.Ctx.IntTy, VK_PRValue);
// For arrays, destroy elements right-to-left.
if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(T)) {
@@ -6710,9 +6715,12 @@
if (Pointer.Designator.Invalid)
return false;
- // Deleting a null pointer has no effect.
- if (Pointer.isNullPointer())
+ // Deleting a null pointer would have no effect, but it's not permitted by
+ // std::allocator<T>::deallocate's contract.
+ if (Pointer.isNullPointer()) {
+ Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_deallocate_null);
return true;
+ }
if (!CheckDeleteKind(Info, E, Pointer, DynAlloc::StdAllocator))
return false;
@@ -6956,7 +6964,7 @@
llvm::NoneType unrepresentableValue(QualType Ty, const APSInt &Val) {
Info.FFDiag(BCE->getBeginLoc(),
diag::note_constexpr_bit_cast_unrepresentable_value)
- << Ty << Val.toString(/*Radix=*/10);
+ << Ty << toString(Val, /*Radix=*/10);
return None;
}
@@ -7846,8 +7854,8 @@
bool VisitStmtExpr(const StmtExpr *E) {
// We will have checked the full-expressions inside the statement expression
// when they were completed, and don't need to check them again now.
- if (Info.checkingForUndefinedBehavior())
- return Error(E);
+ llvm::SaveAndRestore<bool> NotCheckingForUB(
+ Info.CheckingForUndefinedBehavior, false);
const CompoundStmt *CS = E->getSubStmt();
if (CS->body_empty())
@@ -7940,7 +7948,7 @@
if (E->isArrow()) {
EvalOK = evaluatePointer(E->getBase(), Result);
BaseTy = E->getBase()->getType()->castAs<PointerType>()->getPointeeType();
- } else if (E->getBase()->isRValue()) {
+ } else if (E->getBase()->isPRValue()) {
assert(E->getBase()->getType()->isRecordType());
EvalOK = EvaluateTemporary(E->getBase(), Result, this->Info);
BaseTy = E->getBase()->getType();
@@ -8661,6 +8669,26 @@
return true;
}
+ bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E) {
+ std::string ResultStr = E->ComputeName(Info.Ctx);
+
+ Info.Ctx.SYCLUniqueStableNameEvaluatedValues[E] = ResultStr;
+
+ QualType CharTy = Info.Ctx.CharTy.withConst();
+ APInt Size(Info.Ctx.getTypeSize(Info.Ctx.getSizeType()),
+ ResultStr.size() + 1);
+ QualType ArrayTy = Info.Ctx.getConstantArrayType(CharTy, Size, nullptr,
+ ArrayType::Normal, 0);
+
+ StringLiteral *SL =
+ StringLiteral::Create(Info.Ctx, ResultStr, StringLiteral::Ascii,
+ /*Pascal*/ false, ArrayTy, E->getLocation());
+
+ evaluateLValue(SL, Result);
+ Result.addArray(Info, E, cast<ConstantArrayType>(ArrayTy));
+ return true;
+ }
+
// FIXME: Missing: @protocol, @selector
};
} // end anonymous namespace
@@ -8668,7 +8696,7 @@
static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info,
bool InvalidBaseOK) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->hasPointerRepresentation());
+ assert(E->isPRValue() && E->getType()->hasPointerRepresentation());
return PointerExprEvaluator(Info, Result, InvalidBaseOK).Visit(E);
}
@@ -9237,7 +9265,7 @@
llvm::APInt::udivrem(OrigN, TSize, N, Remainder);
if (Remainder) {
Info.FFDiag(E, diag::note_constexpr_memcpy_unsupported)
- << Move << WChar << 0 << T << OrigN.toString(10, /*Signed*/false)
+ << Move << WChar << 0 << T << toString(OrigN, 10, /*Signed*/false)
<< (unsigned)TSize;
return false;
}
@@ -9251,7 +9279,7 @@
if (N.ugt(RemainingSrcSize) || N.ugt(RemainingDestSize)) {
Info.FFDiag(E, diag::note_constexpr_memcpy_unsupported)
<< Move << WChar << (N.ugt(RemainingSrcSize) ? 1 : 2) << T
- << N.toString(10, /*Signed*/false);
+ << toString(N, 10, /*Signed*/false);
return false;
}
uint64_t NElems = N.getZExtValue();
@@ -9426,8 +9454,8 @@
return ZeroInitialization(E);
Info.FFDiag(*ArraySize, diag::note_constexpr_new_too_small)
- << AllocBound.toString(10, /*Signed=*/false)
- << InitBound.toString(10, /*Signed=*/false)
+ << toString(AllocBound, 10, /*Signed=*/false)
+ << toString(InitBound, 10, /*Signed=*/false)
<< (*ArraySize)->getSourceRange();
return false;
}
@@ -9556,7 +9584,7 @@
static bool EvaluateMemberPointer(const Expr *E, MemberPtr &Result,
EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isMemberPointerType());
+ assert(E->isPRValue() && E->getType()->isMemberPointerType());
return MemberPointerExprEvaluator(Info, Result).Visit(E);
}
@@ -9798,7 +9826,14 @@
ThisOverrideRAII ThisOverride(*Info.CurrentCall, &This,
isa<CXXDefaultInitExpr>(InitExpr));
- return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr);
+ if (EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr)) {
+ if (Field->isBitField())
+ return truncateBitfieldValue(Info, InitExpr, Result.getUnionValue(),
+ Field);
+ return true;
+ }
+
+ return false;
}
if (!Result.hasValue())
@@ -10039,7 +10074,7 @@
static bool EvaluateRecord(const Expr *E, const LValue &This,
APValue &Result, EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isRecordType() &&
+ assert(E->isPRValue() && E->getType()->isRecordType() &&
"can't evaluate expression as a record rvalue");
return RecordExprEvaluator(Info, This, Result).Visit(E);
}
@@ -10095,7 +10130,7 @@
/// Evaluate an expression of record type as a temporary.
static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isRecordType());
+ assert(E->isPRValue() && E->getType()->isRecordType());
return TemporaryExprEvaluator(Info, Result).Visit(E);
}
@@ -10137,7 +10172,8 @@
} // end anonymous namespace
static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) {
- assert(E->isRValue() && E->getType()->isVectorType() &&"not a vector rvalue");
+ assert(E->isPRValue() && E->getType()->isVectorType() &&
+ "not a vector prvalue");
return VectorExprEvaluator(Info, Result).Visit(E);
}
@@ -10199,7 +10235,7 @@
Elt = SValInt.rotl(i*EltSize+EltSize).zextOrTrunc(EltSize);
else
Elt = SValInt.rotr(i*EltSize).zextOrTrunc(EltSize);
- Elts.push_back(APValue(APSInt(Elt, EltTy->isSignedIntegerType())));
+ Elts.push_back(APValue(APSInt(Elt, !EltTy->isSignedIntegerType())));
}
} else {
return Error(E);
@@ -10295,10 +10331,10 @@
"Must both be vector types");
// Checking JUST the types are the same would be fine, except shifts don't
// need to have their types be the same (since you always shift by an int).
- assert(LHS->getType()->getAs<VectorType>()->getNumElements() ==
- E->getType()->getAs<VectorType>()->getNumElements() &&
- RHS->getType()->getAs<VectorType>()->getNumElements() ==
- E->getType()->getAs<VectorType>()->getNumElements() &&
+ assert(LHS->getType()->castAs<VectorType>()->getNumElements() ==
+ E->getType()->castAs<VectorType>()->getNumElements() &&
+ RHS->getType()->castAs<VectorType>()->getNumElements() ==
+ E->getType()->castAs<VectorType>()->getNumElements() &&
"All operands must be the same size.");
APValue LHSValue;
@@ -10352,7 +10388,8 @@
Result = APValue(APValue::UninitArray(), 0,
CAT->getSize().getZExtValue());
- if (!Result.hasArrayFiller()) return true;
+ if (!Result.hasArrayFiller())
+ return true;
// Zero-initialize all elements.
LValue Subobject = This;
@@ -10382,7 +10419,8 @@
static bool EvaluateArray(const Expr *E, const LValue &This,
APValue &Result, EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isArrayType() && "not an array rvalue");
+ assert(E->isPRValue() && E->getType()->isArrayType() &&
+ "not an array prvalue");
return ArrayExprEvaluator(Info, This, Result).Visit(E);
}
@@ -10390,8 +10428,8 @@
APValue &Result, const InitListExpr *ILE,
QualType AllocType) {
assert(!ILE->isValueDependent());
- assert(ILE->isRValue() && ILE->getType()->isArrayType() &&
- "not an array rvalue");
+ assert(ILE->isPRValue() && ILE->getType()->isArrayType() &&
+ "not an array prvalue");
return ArrayExprEvaluator(Info, This, Result)
.VisitInitListExpr(ILE, AllocType);
}
@@ -10401,8 +10439,8 @@
const CXXConstructExpr *CCE,
QualType AllocType) {
assert(!CCE->isValueDependent());
- assert(CCE->isRValue() && CCE->getType()->isArrayType() &&
- "not an array rvalue");
+ assert(CCE->isPRValue() && CCE->getType()->isArrayType() &&
+ "not an array prvalue");
return ArrayExprEvaluator(Info, This, Result)
.VisitCXXConstructExpr(CCE, This, &Result, AllocType);
}
@@ -10779,7 +10817,7 @@
static bool EvaluateIntegerOrLValue(const Expr *E, APValue &Result,
EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isIntegralOrEnumerationType());
+ assert(E->isPRValue() && E->getType()->isIntegralOrEnumerationType());
return IntExprEvaluator(Info, Result).Visit(E);
}
@@ -10977,6 +11015,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
return GCCTypeClass::None;
case BuiltinType::Dependent:
@@ -11146,7 +11186,7 @@
///
/// Always returns an RValue with a pointer representation.
static const Expr *ignorePointerCastsAndParens(const Expr *E) {
- assert(E->isRValue() && E->getType()->hasPointerRepresentation());
+ assert(E->isPRValue() && E->getType()->hasPointerRepresentation());
auto *NoParens = E->IgnoreParens();
auto *Cast = dyn_cast<CastExpr>(NoParens);
@@ -11161,7 +11201,7 @@
return NoParens;
auto *SubExpr = Cast->getSubExpr();
- if (!SubExpr->getType()->hasPointerRepresentation() || !SubExpr->isRValue())
+ if (!SubExpr->getType()->hasPointerRepresentation() || !SubExpr->isPRValue())
return NoParens;
return ignorePointerCastsAndParens(SubExpr);
}
@@ -11996,9 +12036,6 @@
return BuiltinOp == Builtin::BI__atomic_always_lock_free ?
Success(0, E) : Error(E);
}
- case Builtin::BIomp_is_initial_device:
- // We can decide statically which value the runtime would return if called.
- return Success(Info.getLangOpts().OpenMPIsDevice ? 0 : 1, E);
case Builtin::BI__builtin_add_overflow:
case Builtin::BI__builtin_sub_overflow:
case Builtin::BI__builtin_mul_overflow:
@@ -12199,7 +12236,7 @@
/// with integral or enumeration type.
static bool shouldEnqueue(const BinaryOperator *E) {
return E->getOpcode() == BO_Comma || E->isLogicalOp() ||
- (E->isRValue() && E->getType()->isIntegralOrEnumerationType() &&
+ (E->isPRValue() && E->getType()->isIntegralOrEnumerationType() &&
E->getLHS()->getType()->isIntegralOrEnumerationType() &&
E->getRHS()->getType()->isIntegralOrEnumerationType());
}
@@ -12458,25 +12495,6 @@
}
namespace {
-/// Used when we determine that we should fail, but can keep evaluating prior to
-/// noting that we had a failure.
-class DelayedNoteFailureRAII {
- EvalInfo &Info;
- bool NoteFailure;
-
-public:
- DelayedNoteFailureRAII(EvalInfo &Info, bool NoteFailure = true)
- : Info(Info), NoteFailure(NoteFailure) {}
- ~DelayedNoteFailureRAII() {
- if (NoteFailure) {
- bool ContinueAfterFailure = Info.noteFailure();
- (void)ContinueAfterFailure;
- assert(ContinueAfterFailure &&
- "Shouldn't have kept evaluating on failure.");
- }
- }
-};
-
enum class CmpResult {
Unequal,
Less,
@@ -12844,12 +12862,14 @@
}
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- // We don't call noteFailure immediately because the assignment happens after
- // we evaluate LHS and RHS.
- if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp())
- return Error(E);
+ // We don't support assignment in C. C++ assignments don't get here because
+ // assignment is an lvalue in C++.
+ if (E->isAssignmentOp()) {
+ Error(E);
+ if (!Info.noteFailure())
+ return false;
+ }
- DelayedNoteFailureRAII MaybeNoteFailureLater(Info, E->isAssignmentOp());
if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E))
return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E);
@@ -13186,6 +13206,7 @@
case CK_FixedPointToFloating:
case CK_FixedPointCast:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
llvm_unreachable("invalid cast kind for integral value");
case CK_BitCast:
@@ -13403,7 +13424,7 @@
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_fixedpoint_constant_overflow)
<< Result.toString() << E->getType();
- else if (!HandleOverflow(Info, E, Result, E->getType()))
+ if (!HandleOverflow(Info, E, Result, E->getType()))
return false;
}
return Success(Result, E);
@@ -13422,7 +13443,7 @@
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_fixedpoint_constant_overflow)
<< IntResult.toString() << E->getType();
- else if (!HandleOverflow(Info, E, IntResult, E->getType()))
+ if (!HandleOverflow(Info, E, IntResult, E->getType()))
return false;
}
@@ -13442,7 +13463,7 @@
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_fixedpoint_constant_overflow)
<< Result.toString() << E->getType();
- else if (!HandleOverflow(Info, E, Result, E->getType()))
+ if (!HandleOverflow(Info, E, Result, E->getType()))
return false;
}
@@ -13530,7 +13551,7 @@
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_fixedpoint_constant_overflow)
<< Result.toString() << E->getType();
- else if (!HandleOverflow(Info, E, Result, E->getType()))
+ if (!HandleOverflow(Info, E, Result, E->getType()))
return false;
}
return Success(Result, E);
@@ -13574,7 +13595,7 @@
static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isRealFloatingType());
+ assert(E->isPRValue() && E->getType()->isRealFloatingType());
return FloatExprEvaluator(Info, Result).Visit(E);
}
@@ -13671,6 +13692,9 @@
Result.changeSign();
return true;
+ case Builtin::BI__arithmetic_fence:
+ return EvaluateFloat(E->getArg(0), Result, Info);
+
// FIXME: Builtin::BI__builtin_powi
// FIXME: Builtin::BI__builtin_powif
// FIXME: Builtin::BI__builtin_powil
@@ -13827,7 +13851,7 @@
static bool EvaluateComplex(const Expr *E, ComplexValue &Result,
EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isAnyComplexType());
+ assert(E->isPRValue() && E->getType()->isAnyComplexType());
return ComplexExprEvaluator(Info, Result).Visit(E);
}
@@ -13926,6 +13950,7 @@
case CK_FixedPointToBoolean:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
@@ -14354,7 +14379,7 @@
static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result,
EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isAtomicType());
+ assert(E->isPRValue() && E->getType()->isAtomicType());
return AtomicExprEvaluator(Info, This, Result).Visit(E);
}
@@ -14479,7 +14504,7 @@
static bool EvaluateVoid(const Expr *E, EvalInfo &Info) {
assert(!E->isValueDependent());
- assert(E->isRValue() && E->getType()->isVoidType());
+ assert(E->isPRValue() && E->getType()->isVoidType());
return VoidExprEvaluator(Info).Visit(E);
}
@@ -14579,7 +14604,7 @@
if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This))
return false;
- if (E->isRValue()) {
+ if (E->isPRValue()) {
// Evaluate arrays and record types in-place, so that later initializers can
// refer to earlier-initialized members of the object.
QualType T = E->getType();
@@ -14649,8 +14674,8 @@
// FIXME: Evaluating values of large array and record types can cause
// performance problems. Only do so in C++11 for now.
- if (Exp->isRValue() && (Exp->getType()->isArrayType() ||
- Exp->getType()->isRecordType()) &&
+ if (Exp->isPRValue() &&
+ (Exp->getType()->isArrayType() || Exp->getType()->isRecordType()) &&
!Ctx.getLangOpts().CPlusPlus11) {
IsConst = false;
return true;
@@ -14873,7 +14898,7 @@
// FIXME: Evaluating initializers for large array and record types can cause
// performance problems. Only do so in C++11 for now.
- if (isRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&
+ if (isPRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&
!Ctx.getLangOpts().CPlusPlus11)
return false;
@@ -15155,6 +15180,7 @@
case Expr::CoawaitExprClass:
case Expr::DependentCoawaitExprClass:
case Expr::CoyieldExprClass:
+ case Expr::SYCLUniqueStableNameExprClass:
return ICEDiag(IK_NotICE, E->getBeginLoc());
case Expr::InitListExprClass: {
@@ -15162,7 +15188,7 @@
// form "T x = { a };" is equivalent to "T x = a;".
// Unless we're initializing a reference, T is a scalar as it is known to be
// of integral or enumeration type.
- if (E->isRValue())
+ if (E->isPRValue())
if (cast<InitListExpr>(E)->getNumInits() == 1)
return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx);
return ICEDiag(IK_NotICE, E->getBeginLoc());
diff --git a/src/llvm-project/clang/lib/AST/ExprObjC.cpp b/src/llvm-project/clang/lib/AST/ExprObjC.cpp
index 662bc32..7d932c8 100644
--- a/src/llvm-project/clang/lib/AST/ExprObjC.cpp
+++ b/src/llvm-project/clang/lib/AST/ExprObjC.cpp
@@ -27,7 +27,7 @@
ObjCArrayLiteral::ObjCArrayLiteral(ArrayRef<Expr *> Elements, QualType T,
ObjCMethodDecl *Method, SourceRange SR)
- : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary),
+ : Expr(ObjCArrayLiteralClass, T, VK_PRValue, OK_Ordinary),
NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method) {
Expr **SaveElements = getElements();
for (unsigned I = 0, N = Elements.size(); I != N; ++I)
@@ -54,7 +54,7 @@
bool HasPackExpansions, QualType T,
ObjCMethodDecl *method,
SourceRange SR)
- : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary),
+ : Expr(ObjCDictionaryLiteralClass, T, VK_PRValue, OK_Ordinary),
NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR),
DictWithObjectsMethod(method) {
KeyValuePair *KeyValues = getTrailingObjects<KeyValuePair>();
@@ -281,7 +281,7 @@
return Ctx.getLValueReferenceType(QT);
case VK_XValue:
return Ctx.getRValueReferenceType(QT);
- case VK_RValue:
+ case VK_PRValue:
return QT;
}
llvm_unreachable("Unsupported ExprValueKind");
diff --git a/src/llvm-project/clang/lib/AST/ExternalASTMerger.cpp b/src/llvm-project/clang/lib/AST/ExternalASTMerger.cpp
index 88bbe90..c7789b7 100644
--- a/src/llvm-project/clang/lib/AST/ExternalASTMerger.cpp
+++ b/src/llvm-project/clang/lib/AST/ExternalASTMerger.cpp
@@ -64,24 +64,24 @@
Source<DeclarationName> SourceName = *SourceNameOrErr;
DeclContext::lookup_result SearchResult =
SourceParentDC.get()->lookup(SourceName.get());
- size_t SearchResultSize = SearchResult.size();
- if (SearchResultSize == 0 || SearchResultSize > 1) {
- // There are two cases here. First, we might not find the name.
- // We might also find multiple copies, in which case we have no
- // guarantee that the one we wanted is the one we pick. (E.g.,
- // if we have two specializations of the same template it is
- // very hard to determine which is the one you want.)
- //
- // The Origins map fixes this problem by allowing the origin to be
- // explicitly recorded, so we trigger that recording by returning
- // nothing (rather than a possibly-inaccurate guess) here.
- return nullptr;
- } else {
- NamedDecl *SearchResultDecl = SearchResult[0];
+
+ // There are two cases here. First, we might not find the name.
+ // We might also find multiple copies, in which case we have no
+ // guarantee that the one we wanted is the one we pick. (E.g.,
+ // if we have two specializations of the same template it is
+ // very hard to determine which is the one you want.)
+ //
+ // The Origins map fixes this problem by allowing the origin to be
+ // explicitly recorded, so we trigger that recording by returning
+ // nothing (rather than a possibly-inaccurate guess) here.
+ if (SearchResult.isSingleResult()) {
+ NamedDecl *SearchResultDecl = SearchResult.front();
if (isa<DeclContext>(SearchResultDecl) &&
SearchResultDecl->getKind() == DC->getDeclKind())
return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
return nullptr; // This type of lookup is unsupported
+ } else {
+ return nullptr;
}
}
diff --git a/src/llvm-project/clang/lib/AST/Interp/Context.h b/src/llvm-project/clang/lib/AST/Interp/Context.h
index e4d831c..e8238ee 100644
--- a/src/llvm-project/clang/lib/AST/Interp/Context.h
+++ b/src/llvm-project/clang/lib/AST/Interp/Context.h
@@ -16,7 +16,6 @@
#ifndef LLVM_CLANG_AST_INTERP_CONTEXT_H
#define LLVM_CLANG_AST_INTERP_CONTEXT_H
-#include "Context.h"
#include "InterpStack.h"
#include "clang/AST/APValue.h"
#include "llvm/ADT/PointerIntPair.h"
diff --git a/src/llvm-project/clang/lib/AST/Interp/Interp.h b/src/llvm-project/clang/lib/AST/Interp/Interp.h
index a63c5a8..e2f7bf0 100644
--- a/src/llvm-project/clang/lib/AST/Interp/Interp.h
+++ b/src/llvm-project/clang/lib/AST/Interp/Interp.h
@@ -118,7 +118,8 @@
const Expr *E = S.Current->getExpr(OpPC);
QualType Type = E->getType();
if (S.checkingForUndefinedBehavior()) {
- auto Trunc = Value.trunc(Result.bitWidth()).toString(10);
+ SmallString<32> Trunc;
+ Value.trunc(Result.bitWidth()).toString(Trunc, 10);
auto Loc = E->getExprLoc();
S.report(Loc, diag::warn_integer_constant_overflow) << Trunc << Type;
return true;
diff --git a/src/llvm-project/clang/lib/AST/ItaniumMangle.cpp b/src/llvm-project/clang/lib/AST/ItaniumMangle.cpp
index 5cad84a..8cbac66 100644
--- a/src/llvm-project/clang/lib/AST/ItaniumMangle.cpp
+++ b/src/llvm-project/clang/lib/AST/ItaniumMangle.cpp
@@ -14,7 +14,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/Mangle.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
@@ -23,14 +22,16 @@
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Mangle.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Thunk.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -124,13 +125,16 @@
typedef std::pair<const DeclContext*, IdentifierInfo*> DiscriminatorKeyTy;
llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
+ const DiscriminatorOverrideTy DiscriminatorOverride = nullptr;
- bool IsDevCtx = false;
+ bool NeedsUniqueInternalLinkageNames = false;
public:
- explicit ItaniumMangleContextImpl(ASTContext &Context,
- DiagnosticsEngine &Diags)
- : ItaniumMangleContext(Context, Diags) {}
+ explicit ItaniumMangleContextImpl(
+ ASTContext &Context, DiagnosticsEngine &Diags,
+ DiscriminatorOverrideTy DiscriminatorOverride)
+ : ItaniumMangleContext(Context, Diags),
+ DiscriminatorOverride(DiscriminatorOverride) {}
/// @name Mangler Entry Points
/// @{
@@ -140,8 +144,10 @@
return false;
}
- bool isDeviceMangleContext() const override { return IsDevCtx; }
- void setDeviceMangleContext(bool IsDev) override { IsDevCtx = IsDev; }
+ bool isUniqueInternalLinkageDecl(const NamedDecl *ND) override;
+ void needsUniqueInternalLinkageNames() override {
+ NeedsUniqueInternalLinkageNames = true;
+ }
void mangleCXXName(GlobalDecl GD, raw_ostream &) override;
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
@@ -209,6 +215,40 @@
disc = discriminator-2;
return true;
}
+
+ std::string getLambdaString(const CXXRecordDecl *Lambda) override {
+ // This function matches the one in MicrosoftMangle, which returns
+ // the string that is used in lambda mangled names.
+ assert(Lambda->isLambda() && "RD must be a lambda!");
+ std::string Name("<lambda");
+ Decl *LambdaContextDecl = Lambda->getLambdaContextDecl();
+ unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber();
+ unsigned LambdaId;
+ const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
+ const FunctionDecl *Func =
+ Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
+
+ if (Func) {
+ unsigned DefaultArgNo =
+ Func->getNumParams() - Parm->getFunctionScopeIndex();
+ Name += llvm::utostr(DefaultArgNo);
+ Name += "_";
+ }
+
+ if (LambdaManglingNumber)
+ LambdaId = LambdaManglingNumber;
+ else
+ LambdaId = getAnonymousStructIdForDebugInfo(Lambda);
+
+ Name += llvm::utostr(LambdaId);
+ Name += '>';
+ return Name;
+ }
+
+ DiscriminatorOverrideTy getDiscriminatorOverride() const override {
+ return DiscriminatorOverride;
+ }
+
/// @}
};
@@ -502,11 +542,16 @@
void mangleNestedName(const TemplateDecl *TD,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
+ void mangleNestedNameWithClosurePrefix(GlobalDecl GD,
+ const NamedDecl *PrefixND,
+ const AbiTagList *AdditionalAbiTags);
void manglePrefix(NestedNameSpecifier *qualifier);
void manglePrefix(const DeclContext *DC, bool NoFunction=false);
void manglePrefix(QualType type);
void mangleTemplatePrefix(GlobalDecl GD, bool NoFunction=false);
void mangleTemplatePrefix(TemplateName Template);
+ const NamedDecl *getClosurePrefix(const Decl *ND);
+ void mangleClosurePrefix(const NamedDecl *ND, bool NoFunction = false);
bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType,
StringRef Prefix = "");
void mangleOperatorName(DeclarationName Name, unsigned Arity);
@@ -583,6 +628,36 @@
}
+static bool isInternalLinkageDecl(const NamedDecl *ND) {
+ if (ND && ND->getFormalLinkage() == InternalLinkage &&
+ !ND->isExternallyVisible() &&
+ getEffectiveDeclContext(ND)->isFileContext() &&
+ !ND->isInAnonymousNamespace())
+ return true;
+ return false;
+}
+
+// Check if this Function Decl needs a unique internal linkage name.
+bool ItaniumMangleContextImpl::isUniqueInternalLinkageDecl(
+ const NamedDecl *ND) {
+ if (!NeedsUniqueInternalLinkageNames || !ND)
+ return false;
+
+ const auto *FD = dyn_cast<FunctionDecl>(ND);
+ if (!FD)
+ return false;
+
+ // For C functions without prototypes, return false as their
+ // names should not be mangled.
+ if (!FD->getType()->getAs<FunctionProtoType>())
+ return false;
+
+ if (isInternalLinkageDecl(ND))
+ return true;
+
+ return false;
+}
+
bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (FD) {
@@ -916,6 +991,13 @@
if (Module *M = ND->getOwningModuleForLinkage())
mangleModuleName(M);
+ // Closures can require a nested-name mangling even if they're semantically
+ // in the global namespace.
+ if (const NamedDecl *PrefixND = getClosurePrefix(ND)) {
+ mangleNestedNameWithClosurePrefix(GD, PrefixND, AdditionalAbiTags);
+ return;
+ }
+
if (DC->isTranslationUnit() || isStdNamespace(DC)) {
// Check if we have a template.
const TemplateArgumentList *TemplateArgs = nullptr;
@@ -1346,10 +1428,7 @@
// 12_GLOBAL__N_1 mangling is quite sufficient there, and this better
// matches GCC anyway, because GCC does not treat anonymous namespaces as
// implying internal linkage.
- if (ND && ND->getFormalLinkage() == InternalLinkage &&
- !ND->isExternallyVisible() &&
- getEffectiveDeclContext(ND)->isFileContext() &&
- !ND->isInAnonymousNamespace())
+ if (isInternalLinkageDecl(ND))
Out << 'L';
auto *FD = dyn_cast<FunctionDecl>(ND);
@@ -1439,7 +1518,9 @@
// <lambda-sig> ::= <template-param-decl>* <parameter-type>+
// # Parameter types or 'v' for 'void'.
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
- if (Record->isLambda() && Record->getLambdaManglingNumber()) {
+ if (Record->isLambda() && (Record->getLambdaManglingNumber() ||
+ Context.getDiscriminatorOverride()(
+ Context.getASTContext(), Record))) {
assert(!AdditionalAbiTags &&
"Lambda type cannot have additional abi tags");
mangleLambda(Record);
@@ -1593,8 +1674,7 @@
if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
mangleTemplatePrefix(TD, NoFunction);
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
- }
- else {
+ } else {
manglePrefix(DC, NoFunction);
mangleUnqualifiedName(GD, AdditionalAbiTags);
}
@@ -1614,6 +1694,23 @@
Out << 'E';
}
+void CXXNameMangler::mangleNestedNameWithClosurePrefix(
+ GlobalDecl GD, const NamedDecl *PrefixND,
+ const AbiTagList *AdditionalAbiTags) {
+ // A <closure-prefix> represents a variable or field, not a regular
+ // DeclContext, so needs special handling. In this case we're mangling a
+ // limited form of <nested-name>:
+ //
+ // <nested-name> ::= N <closure-prefix> <closure-type-name> E
+
+ Out << 'N';
+
+ mangleClosurePrefix(PrefixND);
+ mangleUnqualifiedName(GD, AdditionalAbiTags);
+
+ Out << 'E';
+}
+
static GlobalDecl getParentOfLocalEntity(const DeclContext *DC) {
GlobalDecl GD;
// The Itanium spec says:
@@ -1689,7 +1786,10 @@
if (D == RD) {
mangleUnqualifiedName(RD, AdditionalAbiTags);
} else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
- manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/);
+ if (const NamedDecl *PrefixND = getClosurePrefix(BD))
+ mangleClosurePrefix(PrefixND, true /*NoFunction*/);
+ else
+ manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/);
assert(!AdditionalAbiTags && "Block cannot have additional abi tags");
mangleUnqualifiedBlock(BD);
} else {
@@ -1739,13 +1839,20 @@
mangleLocalName(Block, /* AdditionalAbiTags */ nullptr);
return;
}
- manglePrefix(getEffectiveDeclContext(Block));
+ if (const NamedDecl *PrefixND = getClosurePrefix(Block))
+ mangleClosurePrefix(PrefixND);
+ else
+ manglePrefix(DC);
mangleUnqualifiedBlock(Block);
}
void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
+ // When trying to be ABI-compatibility with clang 12 and before, mangle a
+ // <data-member-prefix> now, with no substitutions and no <template-args>.
if (Decl *Context = Block->getBlockManglingContextDecl()) {
- if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
+ if (getASTContext().getLangOpts().getClangABICompat() <=
+ LangOptions::ClangABI::Ver12 &&
+ (isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
Context->getDeclContext()->isRecord()) {
const auto *ND = cast<NamedDecl>(Context);
if (ND->getIdentifier()) {
@@ -1818,20 +1925,13 @@
}
void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
- // If the context of a closure type is an initializer for a class member
- // (static or nonstatic), it is encoded in a qualified name with a final
- // <prefix> of the form:
- //
- // <data-member-prefix> := <member source-name> M
- //
- // Technically, the data-member-prefix is part of the <prefix>. However,
- // since a closure type will always be mangled with a prefix, it's easier
- // to emit that last part of the prefix here.
+ // When trying to be ABI-compatibility with clang 12 and before, mangle a
+ // <data-member-prefix> now, with no substitutions.
if (Decl *Context = Lambda->getLambdaContextDecl()) {
- if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
+ if (getASTContext().getLangOpts().getClangABICompat() <=
+ LangOptions::ClangABI::Ver12 &&
+ (isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
!isa<ParmVarDecl>(Context)) {
- // FIXME: 'inline auto [a, b] = []{ return ... };' does not get a
- // reasonable mangling here.
if (const IdentifierInfo *Name
= cast<NamedDecl>(Context)->getIdentifier()) {
mangleSourceName(Name);
@@ -1858,9 +1958,11 @@
// if the host-side CXX ABI has different numbering for lambda. In such case,
// if the mangle context is that device-side one, use the device-side lambda
// mangling number for this lambda.
- unsigned Number = Context.isDeviceMangleContext()
- ? Lambda->getDeviceLambdaManglingNumber()
- : Lambda->getLambdaManglingNumber();
+ llvm::Optional<unsigned> DeviceNumber =
+ Context.getDiscriminatorOverride()(Context.getASTContext(), Lambda);
+ unsigned Number = DeviceNumber.hasValue() ? *DeviceNumber
+ : Lambda->getLambdaManglingNumber();
+
assert(Number > 0 && "Lambda should be mangled as an unnamed class");
if (Number > 1)
mangleNumber(Number - 2);
@@ -1914,6 +2016,7 @@
void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
// <prefix> ::= <prefix> <unqualified-name>
// ::= <template-prefix> <template-args>
+ // ::= <closure-prefix>
// ::= <template-param>
// ::= # empty
// ::= <substitution>
@@ -1932,11 +2035,14 @@
if (mangleSubstitution(ND))
return;
- // Check if we have a template.
+ // Check if we have a template-prefix or a closure-prefix.
const TemplateArgumentList *TemplateArgs = nullptr;
if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) {
mangleTemplatePrefix(TD);
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
+ } else if (const NamedDecl *PrefixND = getClosurePrefix(ND)) {
+ mangleClosurePrefix(PrefixND, NoFunction);
+ mangleUnqualifiedName(ND, nullptr);
} else {
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
mangleUnqualifiedName(ND, nullptr);
@@ -2002,6 +2108,50 @@
addSubstitution(ND);
}
+const NamedDecl *CXXNameMangler::getClosurePrefix(const Decl *ND) {
+ if (getASTContext().getLangOpts().getClangABICompat() <=
+ LangOptions::ClangABI::Ver12)
+ return nullptr;
+
+ const NamedDecl *Context = nullptr;
+ if (auto *Block = dyn_cast<BlockDecl>(ND)) {
+ Context = dyn_cast_or_null<NamedDecl>(Block->getBlockManglingContextDecl());
+ } else if (auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
+ if (RD->isLambda())
+ Context = dyn_cast_or_null<NamedDecl>(RD->getLambdaContextDecl());
+ }
+ if (!Context)
+ return nullptr;
+
+ // Only lambdas within the initializer of a non-local variable or non-static
+ // data member get a <closure-prefix>.
+ if ((isa<VarDecl>(Context) && cast<VarDecl>(Context)->hasGlobalStorage()) ||
+ isa<FieldDecl>(Context))
+ return Context;
+
+ return nullptr;
+}
+
+void CXXNameMangler::mangleClosurePrefix(const NamedDecl *ND, bool NoFunction) {
+ // <closure-prefix> ::= [ <prefix> ] <unqualified-name> M
+ // ::= <template-prefix> <template-args> M
+ if (mangleSubstitution(ND))
+ return;
+
+ const TemplateArgumentList *TemplateArgs = nullptr;
+ if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) {
+ mangleTemplatePrefix(TD, NoFunction);
+ mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
+ } else {
+ manglePrefix(getEffectiveDeclContext(ND), NoFunction);
+ mangleUnqualifiedName(ND, nullptr);
+ }
+
+ Out << 'M';
+
+ addSubstitution(ND);
+}
+
/// Mangles a template name under the production <type>. Required for
/// template template arguments.
/// <type> ::= <class-enum-type>
@@ -2399,7 +2549,8 @@
if (Context.getASTContext().addressSpaceMapManglingFor(AS)) {
// <target-addrspace> ::= "AS" <address-space-number>
unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS);
- if (TargetAS != 0)
+ if (TargetAS != 0 ||
+ Context.getASTContext().getTargetAddressSpace(LangAS::Default) != 0)
ASString = "AS" + llvm::utostr(TargetAS);
} else {
switch (AS) {
@@ -2428,6 +2579,23 @@
case LangAS::opencl_generic:
ASString = "CLgeneric";
break;
+ // <SYCL-addrspace> ::= "SY" [ "global" | "local" | "private" |
+ // "device" | "host" ]
+ case LangAS::sycl_global:
+ ASString = "SYglobal";
+ break;
+ case LangAS::sycl_global_device:
+ ASString = "SYdevice";
+ break;
+ case LangAS::sycl_global_host:
+ ASString = "SYhost";
+ break;
+ case LangAS::sycl_local:
+ ASString = "SYlocal";
+ break;
+ case LangAS::sycl_private:
+ ASString = "SYprivate";
+ break;
// <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]
case LangAS::cuda_device:
ASString = "CUdevice";
@@ -2891,6 +3059,13 @@
Out << 'u' << type_name.size() << type_name; \
break;
#include "clang/Basic/PPCTypes.def"
+ // TODO: Check the mangling scheme for RISC-V V.
+#define RVV_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ type_name = Name; \
+ Out << 'u' << type_name.size() << type_name; \
+ break;
+#include "clang/Basic/RISCVVTypes.def"
}
}
@@ -2931,6 +3106,8 @@
return "ms_abi";
case CC_Swift:
return "swiftcall";
+ case CC_SwiftAsync:
+ return "swiftasynccall";
}
llvm_unreachable("bad calling convention");
}
@@ -2965,6 +3142,7 @@
// All of these start with "swift", so they come before "ns_consumed".
case ParameterABI::SwiftContext:
+ case ParameterABI::SwiftAsyncContext:
case ParameterABI::SwiftErrorResult:
case ParameterABI::SwiftIndirectResult:
mangleVendorQualifier(getParameterABISpelling(PI.getABI()));
@@ -3134,7 +3312,11 @@
}
void CXXNameMangler::mangleType(const DependentSizedArrayType *T) {
Out << 'A';
- mangleExpression(T->getSizeExpr());
+ // A DependentSizedArrayType might not have size expression as below
+ //
+ // template<int ...N> int arr[] = {N...};
+ if (T->getSizeExpr())
+ mangleExpression(T->getSizeExpr());
Out << '_';
mangleType(T->getElementType());
}
@@ -4854,6 +5036,16 @@
Out << "v18co_yield";
mangleExpression(cast<CoawaitExpr>(E)->getOperand());
break;
+ case Expr::SYCLUniqueStableNameExprClass: {
+ const auto *USN = cast<SYCLUniqueStableNameExpr>(E);
+ NotPrimaryExpr();
+
+ Out << "u33__builtin_sycl_unique_stable_name";
+ mangleType(USN->getTypeSourceInfo()->getType());
+
+ Out << "E";
+ break;
+ }
}
if (AsTemplateArg && !IsPrimaryExpr)
@@ -6206,7 +6398,17 @@
Mangler.mangleLambdaSig(Lambda);
}
+ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context,
+ DiagnosticsEngine &Diags) {
+ return new ItaniumMangleContextImpl(
+ Context, Diags,
+ [](ASTContext &, const NamedDecl *) -> llvm::Optional<unsigned> {
+ return llvm::None;
+ });
+}
+
ItaniumMangleContext *
-ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
- return new ItaniumMangleContextImpl(Context, Diags);
+ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags,
+ DiscriminatorOverrideTy DiscriminatorOverride) {
+ return new ItaniumMangleContextImpl(Context, Diags, DiscriminatorOverride);
}
diff --git a/src/llvm-project/clang/lib/AST/JSONNodeDumper.cpp b/src/llvm-project/clang/lib/AST/JSONNodeDumper.cpp
index 7b99546..f09f9d3 100644
--- a/src/llvm-project/clang/lib/AST/JSONNodeDumper.cpp
+++ b/src/llvm-project/clang/lib/AST/JSONNodeDumper.cpp
@@ -59,7 +59,9 @@
switch (E->getValueKind()) {
case VK_LValue: Category = "lvalue"; break;
case VK_XValue: Category = "xvalue"; break;
- case VK_RValue: Category = "rvalue"; break;
+ case VK_PRValue:
+ Category = "prvalue";
+ break;
}
JOS.attribute("valueCategory", Category);
}
@@ -183,6 +185,35 @@
attributeOnlyIfTrue("selected", A.isSelected());
}
+void JSONNodeDumper::Visit(const concepts::Requirement *R) {
+ if (!R)
+ return;
+
+ switch (R->getKind()) {
+ case concepts::Requirement::RK_Type:
+ JOS.attribute("kind", "TypeRequirement");
+ break;
+ case concepts::Requirement::RK_Simple:
+ JOS.attribute("kind", "SimpleRequirement");
+ break;
+ case concepts::Requirement::RK_Compound:
+ JOS.attribute("kind", "CompoundRequirement");
+ break;
+ case concepts::Requirement::RK_Nested:
+ JOS.attribute("kind", "NestedRequirement");
+ break;
+ }
+
+ if (auto *ER = dyn_cast<concepts::ExprRequirement>(R))
+ attributeOnlyIfTrue("noexcept", ER->hasNoexceptRequirement());
+
+ attributeOnlyIfTrue("isDependent", R->isDependent());
+ if (!R->isDependent())
+ JOS.attribute("satisfied", R->isSatisfied());
+ attributeOnlyIfTrue("containsUnexpandedPack",
+ R->containsUnexpandedParameterPack());
+}
+
void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) {
std::string Str;
llvm::raw_string_ostream OS(Str);
@@ -711,9 +742,13 @@
void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) {
if (ND && ND->getDeclName()) {
JOS.attribute("name", ND->getNameAsString());
- std::string MangledName = ASTNameGen.getName(ND);
- if (!MangledName.empty())
- JOS.attribute("mangledName", MangledName);
+ // FIXME: There are likely other contexts in which it makes no sense to ask
+ // for a mangled name.
+ if (!isa<RequiresExprBodyDecl>(ND->getDeclContext())) {
+ std::string MangledName = ASTNameGen.getName(ND);
+ if (!MangledName.empty())
+ JOS.attribute("mangledName", MangledName);
+ }
}
}
@@ -756,6 +791,10 @@
JOS.attribute("name", Name);
}
+void JSONNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *UED) {
+ JOS.attribute("target", createBareDeclRef(UED->getEnumDecl()));
+}
+
void JSONNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *USD) {
JOS.attribute("target", createBareDeclRef(USD->getTargetDecl()));
}
@@ -887,9 +926,10 @@
if (D->hasDefaultArgument())
JOS.attributeObject("defaultArg", [=] {
+ const auto *InheritedFrom = D->getDefaultArgStorage().getInheritedFrom();
Visit(D->getDefaultArgument().getArgument(),
- D->getDefaultArgStorage().getInheritedFrom()->getSourceRange(),
- D->getDefaultArgStorage().getInheritedFrom(),
+ InheritedFrom ? InheritedFrom->getSourceRange() : SourceLocation{},
+ InheritedFrom,
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
});
}
@@ -1163,6 +1203,12 @@
}
}
+void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
+ const SYCLUniqueStableNameExpr *E) {
+ JOS.attribute("typeSourceInfo",
+ createQualType(E->getTypeSourceInfo()->getType()));
+}
+
void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));
}
@@ -1402,10 +1448,16 @@
}
}
+void JSONNodeDumper::VisitRequiresExpr(const RequiresExpr *RE) {
+ if (!RE->isValueDependent())
+ JOS.attribute("satisfied", RE->isSatisfied());
+}
+
void JSONNodeDumper::VisitIntegerLiteral(const IntegerLiteral *IL) {
- JOS.attribute("value",
- IL->getValue().toString(
- /*Radix=*/10, IL->getType()->isSignedIntegerType()));
+ llvm::SmallString<16> Buffer;
+ IL->getValue().toString(Buffer,
+ /*Radix=*/10, IL->getType()->isSignedIntegerType());
+ JOS.attribute("value", Buffer);
}
void JSONNodeDumper::VisitCharacterLiteral(const CharacterLiteral *CL) {
// FIXME: This should probably print the character literal as a string,
@@ -1450,6 +1502,7 @@
void JSONNodeDumper::VisitLabelStmt(const LabelStmt *LS) {
JOS.attribute("name", LS->getName());
JOS.attribute("declId", createPointerRepresentation(LS->getDecl()));
+ attributeOnlyIfTrue("sideEntry", LS->isSideEntry());
}
void JSONNodeDumper::VisitGotoStmt(const GotoStmt *GS) {
JOS.attribute("targetLabelDeclId",
diff --git a/src/llvm-project/clang/lib/AST/Mangle.cpp b/src/llvm-project/clang/lib/AST/Mangle.cpp
index 3282fcb..54dbf48 100644
--- a/src/llvm-project/clang/lib/AST/Mangle.cpp
+++ b/src/llvm-project/clang/lib/AST/Mangle.cpp
@@ -116,6 +116,12 @@
if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage())
return true;
+ // C functions with internal linkage have to be mangled with option
+ // -funique-internal-linkage-names.
+ if (!getASTContext().getLangOpts().CPlusPlus &&
+ isUniqueInternalLinkageDecl(D))
+ return true;
+
// In C, functions with no attributes never need to be mangled. Fastpath them.
if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
return false;
@@ -133,7 +139,9 @@
}
void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
+ const ASTContext &ASTContext = getASTContext();
const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
+
// Any decl can be declared with __asm("foo") on it, and this takes precedence
// over all other naming in the .o file.
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
@@ -151,9 +159,16 @@
// tricks normally used for producing aliases (PR9177). Fortunately the
// llvm mangler on ELF is a nop, so we can just avoid adding the \01
// marker.
+ StringRef UserLabelPrefix =
+ getASTContext().getTargetInfo().getUserLabelPrefix();
+#ifndef NDEBUG
char GlobalPrefix =
- getASTContext().getTargetInfo().getDataLayout().getGlobalPrefix();
- if (GlobalPrefix)
+ llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString())
+ .getGlobalPrefix();
+ assert((UserLabelPrefix.empty() && !GlobalPrefix) ||
+ (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix));
+#endif
+ if (!UserLabelPrefix.empty())
Out << '\01'; // LLVM IR Marker for __asm("foo")
Out << ALA->getLabel();
@@ -163,7 +178,6 @@
if (auto *GD = dyn_cast<MSGuidDecl>(D))
return mangleMSGuidDecl(GD, Out);
- const ASTContext &ASTContext = getASTContext();
CCMangling CC = getCallingConvMangling(ASTContext, D);
if (CC == CCM_WasmMainArgcArgv) {
@@ -377,8 +391,8 @@
public:
explicit Implementation(ASTContext &Ctx)
- : MC(Ctx.createMangleContext()), DL(Ctx.getTargetInfo().getDataLayout()) {
- }
+ : MC(Ctx.createMangleContext()),
+ DL(Ctx.getTargetInfo().getDataLayoutString()) {}
bool writeName(const Decl *D, raw_ostream &OS) {
// First apply frontend mangling.
diff --git a/src/llvm-project/clang/lib/AST/MicrosoftMangle.cpp b/src/llvm-project/clang/lib/AST/MicrosoftMangle.cpp
index df6c566..d89cddd 100644
--- a/src/llvm-project/clang/lib/AST/MicrosoftMangle.cpp
+++ b/src/llvm-project/clang/lib/AST/MicrosoftMangle.cpp
@@ -228,6 +228,34 @@
return true;
}
+ std::string getLambdaString(const CXXRecordDecl *Lambda) override {
+ assert(Lambda->isLambda() && "RD must be a lambda!");
+ std::string Name("<lambda_");
+
+ Decl *LambdaContextDecl = Lambda->getLambdaContextDecl();
+ unsigned LambdaManglingNumber = Lambda->getLambdaManglingNumber();
+ unsigned LambdaId;
+ const ParmVarDecl *Parm = dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
+ const FunctionDecl *Func =
+ Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
+
+ if (Func) {
+ unsigned DefaultArgNo =
+ Func->getNumParams() - Parm->getFunctionScopeIndex();
+ Name += llvm::utostr(DefaultArgNo);
+ Name += "_";
+ }
+
+ if (LambdaManglingNumber)
+ LambdaId = LambdaManglingNumber;
+ else
+ LambdaId = getLambdaIdForDebugInfo(Lambda);
+
+ Name += llvm::utostr(LambdaId);
+ Name += ">";
+ return Name;
+ }
+
unsigned getLambdaId(const CXXRecordDecl *RD) {
assert(RD->isLambda() && "RD must be a lambda!");
assert(!RD->isExternallyVisible() && "RD must not be visible!");
@@ -238,6 +266,19 @@
return Result.first->second;
}
+ unsigned getLambdaIdForDebugInfo(const CXXRecordDecl *RD) {
+ assert(RD->isLambda() && "RD must be a lambda!");
+ assert(!RD->isExternallyVisible() && "RD must not be visible!");
+ assert(RD->getLambdaManglingNumber() == 0 &&
+ "RD must not have a mangling number!");
+ llvm::DenseMap<const CXXRecordDecl *, unsigned>::iterator Result =
+ LambdaIds.find(RD);
+ // The lambda should exist, but return 0 in case it doesn't.
+ if (Result == LambdaIds.end())
+ return 0;
+ return Result->second;
+ }
+
/// Return a character sequence that is (somewhat) unique to the TU suitable
/// for mangling anonymous namespaces.
StringRef getAnonymousNamespaceHash() const {
@@ -2398,6 +2439,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
case BuiltinType::ShortAccum:
case BuiltinType::Accum:
case BuiltinType::LongAccum:
@@ -2684,6 +2727,9 @@
// ::= I # __fastcall
// ::= J # __export __fastcall
// ::= Q # __vectorcall
+ // ::= S # __attribute__((__swiftcall__)) // Clang-only
+ // ::= T # __attribute__((__swiftasynccall__))
+ // // Clang-only
// ::= w # __regcall
// The 'export' calling conventions are from a bygone era
// (*cough*Win16*cough*) when functions were declared for export with
@@ -2703,6 +2749,7 @@
case CC_X86FastCall: Out << 'I'; break;
case CC_X86VectorCall: Out << 'Q'; break;
case CC_Swift: Out << 'S'; break;
+ case CC_SwiftAsync: Out << 'W'; break;
case CC_PreserveMost: Out << 'U'; break;
case CC_X86RegCall: Out << 'w'; break;
}
@@ -3632,7 +3679,7 @@
assert(VFTableMangling.startswith("??_7") ||
VFTableMangling.startswith("??_S"));
- Out << "??_R4" << StringRef(VFTableMangling).drop_front(4);
+ Out << "??_R4" << VFTableMangling.str().drop_front(4);
}
void MicrosoftMangleContextImpl::mangleSEHFilterExpression(
diff --git a/src/llvm-project/clang/lib/AST/NSAPI.cpp b/src/llvm-project/clang/lib/AST/NSAPI.cpp
index cf4b42d..861060d 100644
--- a/src/llvm-project/clang/lib/AST/NSAPI.cpp
+++ b/src/llvm-project/clang/lib/AST/NSAPI.cpp
@@ -477,6 +477,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
case BuiltinType::BoundMember:
case BuiltinType::Dependent:
case BuiltinType::Overload:
diff --git a/src/llvm-project/clang/lib/AST/NestedNameSpecifier.cpp b/src/llvm-project/clang/lib/AST/NestedNameSpecifier.cpp
index 08e8819..21afdd1 100644
--- a/src/llvm-project/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/src/llvm-project/clang/lib/AST/NestedNameSpecifier.cpp
@@ -288,8 +288,9 @@
if (ResolveTemplateArguments && Record) {
// Print the type trait with resolved template parameters.
Record->printName(OS);
- printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(),
- Policy);
+ printTemplateArgumentList(
+ OS, Record->getTemplateArgs().asArray(), Policy,
+ Record->getSpecializedTemplate()->getTemplateParameters());
break;
}
const Type *T = getAsType();
@@ -355,7 +356,7 @@
assert(Qualifier && "Expected a non-NULL qualifier");
// Location of the trailing '::'.
- unsigned Length = sizeof(unsigned);
+ unsigned Length = sizeof(SourceLocation::UIntTy);
switch (Qualifier->getKind()) {
case NestedNameSpecifier::Global:
@@ -367,7 +368,7 @@
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Super:
// The location of the identifier or namespace name.
- Length += sizeof(unsigned);
+ Length += sizeof(SourceLocation::UIntTy);
break;
case NestedNameSpecifier::TypeSpecWithTemplate:
@@ -392,8 +393,8 @@
/// Load a (possibly unaligned) source location from a given address
/// and offset.
static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
- unsigned Raw;
- memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
+ SourceLocation::UIntTy Raw;
+ memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(Raw));
return SourceLocation::getFromRawEncoding(Raw);
}
@@ -430,8 +431,9 @@
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Super:
- return SourceRange(LoadSourceLocation(Data, Offset),
- LoadSourceLocation(Data, Offset + sizeof(unsigned)));
+ return SourceRange(
+ LoadSourceLocation(Data, Offset),
+ LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy)));
case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
@@ -486,10 +488,10 @@
/// Save a source location to the given buffer.
static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
unsigned &BufferSize, unsigned &BufferCapacity) {
- unsigned Raw = Loc.getRawEncoding();
+ SourceLocation::UIntTy Raw = Loc.getRawEncoding();
Append(reinterpret_cast<char *>(&Raw),
- reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
- Buffer, BufferSize, BufferCapacity);
+ reinterpret_cast<char *>(&Raw) + sizeof(Raw), Buffer, BufferSize,
+ BufferCapacity);
}
/// Save a pointer to the given buffer.
diff --git a/src/llvm-project/clang/lib/AST/OpenMPClause.cpp b/src/llvm-project/clang/lib/AST/OpenMPClause.cpp
index cab5db6..50f4039 100644
--- a/src/llvm-project/clang/lib/AST/OpenMPClause.cpp
+++ b/src/llvm-project/clang/lib/AST/OpenMPClause.cpp
@@ -96,10 +96,17 @@
return static_cast<const OMPFinalClause *>(C);
case OMPC_priority:
return static_cast<const OMPPriorityClause *>(C);
+ case OMPC_novariants:
+ return static_cast<const OMPNovariantsClause *>(C);
+ case OMPC_nocontext:
+ return static_cast<const OMPNocontextClause *>(C);
+ case OMPC_filter:
+ return static_cast<const OMPFilterClause *>(C);
case OMPC_default:
case OMPC_proc_bind:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
@@ -188,6 +195,7 @@
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
@@ -242,6 +250,8 @@
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_novariants:
+ case OMPC_nocontext:
case OMPC_detach:
case OMPC_inclusive:
case OMPC_exclusive:
@@ -298,6 +308,18 @@
return child_range(&Priority, &Priority + 1);
}
+OMPClause::child_range OMPNovariantsClause::used_children() {
+ if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
+ return child_range(C, C + 1);
+ return child_range(&Condition, &Condition + 1);
+}
+
+OMPClause::child_range OMPNocontextClause::used_children() {
+ if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt()))
+ return child_range(C, C + 1);
+ return child_range(&Condition, &Condition + 1);
+}
+
OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num,
unsigned NumLoops,
SourceLocation StartLoc,
@@ -901,6 +923,55 @@
return new (Mem) OMPInReductionClause(N);
}
+OMPSizesClause *OMPSizesClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> Sizes) {
+ OMPSizesClause *Clause = CreateEmpty(C, Sizes.size());
+ Clause->setLocStart(StartLoc);
+ Clause->setLParenLoc(LParenLoc);
+ Clause->setLocEnd(EndLoc);
+ Clause->setSizesRefs(Sizes);
+ return Clause;
+}
+
+OMPSizesClause *OMPSizesClause::CreateEmpty(const ASTContext &C,
+ unsigned NumSizes) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumSizes));
+ return new (Mem) OMPSizesClause(NumSizes);
+}
+
+OMPFullClause *OMPFullClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ OMPFullClause *Clause = CreateEmpty(C);
+ Clause->setLocStart(StartLoc);
+ Clause->setLocEnd(EndLoc);
+ return Clause;
+}
+
+OMPFullClause *OMPFullClause::CreateEmpty(const ASTContext &C) {
+ return new (C) OMPFullClause();
+}
+
+OMPPartialClause *OMPPartialClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ Expr *Factor) {
+ OMPPartialClause *Clause = CreateEmpty(C);
+ Clause->setLocStart(StartLoc);
+ Clause->setLParenLoc(LParenLoc);
+ Clause->setLocEnd(EndLoc);
+ Clause->setFactor(Factor);
+ return Clause;
+}
+
+OMPPartialClause *OMPPartialClause::CreateEmpty(const ASTContext &C) {
+ return new (C) OMPPartialClause();
+}
+
OMPAllocateClause *
OMPAllocateClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, Expr *Allocator,
@@ -1492,6 +1563,27 @@
return new (Mem) OMPAffinityClause(N);
}
+OMPInitClause *OMPInitClause::Create(const ASTContext &C, Expr *InteropVar,
+ ArrayRef<Expr *> PrefExprs, bool IsTarget,
+ bool IsTargetSync, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation VarLoc,
+ SourceLocation EndLoc) {
+
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(PrefExprs.size() + 1));
+ auto *Clause =
+ new (Mem) OMPInitClause(IsTarget, IsTargetSync, StartLoc, LParenLoc,
+ VarLoc, EndLoc, PrefExprs.size() + 1);
+ Clause->setInteropVar(InteropVar);
+ llvm::copy(PrefExprs, Clause->getTrailingObjects<Expr *>() + 1);
+ return Clause;
+}
+
+OMPInitClause *OMPInitClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
+ return new (Mem) OMPInitClause(N);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clauses printing methods
//===----------------------------------------------------------------------===//
@@ -1528,6 +1620,30 @@
OS << ")";
}
+void OMPClausePrinter::VisitOMPSizesClause(OMPSizesClause *Node) {
+ OS << "sizes(";
+ bool First = true;
+ for (auto Size : Node->getSizesRefs()) {
+ if (!First)
+ OS << ", ";
+ Size->printPretty(OS, nullptr, Policy, 0);
+ First = false;
+ }
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPFullClause(OMPFullClause *Node) { OS << "full"; }
+
+void OMPClausePrinter::VisitOMPPartialClause(OMPPartialClause *Node) {
+ OS << "partial";
+
+ if (Expr *Factor = Node->getFactor()) {
+ OS << '(';
+ Factor->printPretty(OS, nullptr, Policy, 0);
+ OS << ')';
+ }
+}
+
void OMPClausePrinter::VisitOMPAllocatorClause(OMPAllocatorClause *Node) {
OS << "allocator(";
Node->getAllocator()->printPretty(OS, nullptr, Policy, 0);
@@ -1722,8 +1838,62 @@
OS << ")";
}
-void OMPClausePrinter::VisitOMPDestroyClause(OMPDestroyClause *) {
+void OMPClausePrinter::VisitOMPInitClause(OMPInitClause *Node) {
+ OS << "init(";
+ bool First = true;
+ for (const Expr *E : Node->prefs()) {
+ if (First)
+ OS << "prefer_type(";
+ else
+ OS << ",";
+ E->printPretty(OS, nullptr, Policy);
+ First = false;
+ }
+ if (!First)
+ OS << "), ";
+ if (Node->getIsTarget())
+ OS << "target";
+ if (Node->getIsTargetSync()) {
+ if (Node->getIsTarget())
+ OS << ", ";
+ OS << "targetsync";
+ }
+ OS << " : ";
+ Node->getInteropVar()->printPretty(OS, nullptr, Policy);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPUseClause(OMPUseClause *Node) {
+ OS << "use(";
+ Node->getInteropVar()->printPretty(OS, nullptr, Policy);
+ OS << ")";
+}
+
+void OMPClausePrinter::VisitOMPDestroyClause(OMPDestroyClause *Node) {
OS << "destroy";
+ if (Expr *E = Node->getInteropVar()) {
+ OS << "(";
+ E->printPretty(OS, nullptr, Policy);
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPNovariantsClause(OMPNovariantsClause *Node) {
+ OS << "novariants";
+ if (Expr *E = Node->getCondition()) {
+ OS << "(";
+ E->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+ }
+}
+
+void OMPClausePrinter::VisitOMPNocontextClause(OMPNocontextClause *Node) {
+ OS << "nocontext";
+ if (Expr *E = Node->getCondition()) {
+ OS << "(";
+ E->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+ }
}
template<typename T>
@@ -2119,6 +2289,12 @@
OS << ")";
}
+void OMPClausePrinter::VisitOMPFilterClause(OMPFilterClause *Node) {
+ OS << "filter(";
+ Node->getThreadID()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
VariantMatchInfo &VMI) const {
for (const OMPTraitSet &Set : Sets) {
diff --git a/src/llvm-project/clang/lib/AST/ParentMapContext.cpp b/src/llvm-project/clang/lib/AST/ParentMapContext.cpp
index cb49953..4a3e0a9 100644
--- a/src/llvm-project/clang/lib/AST/ParentMapContext.cpp
+++ b/src/llvm-project/clang/lib/AST/ParentMapContext.cpp
@@ -49,7 +49,17 @@
return N;
}
+template <typename T, typename... U>
+std::tuple<bool, DynTypedNodeList, const T *, const U *...>
+matchParents(const DynTypedNodeList &NodeList,
+ ParentMapContext::ParentMap *ParentMap);
+
+template <typename, typename...> struct MatchParents;
+
class ParentMapContext::ParentMap {
+
+ template <typename, typename...> friend struct ::MatchParents;
+
/// Contains parents of a node.
using ParentVector = llvm::SmallVector<DynTypedNode, 2>;
@@ -117,11 +127,72 @@
if (Node.getNodeKind().hasPointerIdentity()) {
auto ParentList =
getDynNodeFromMap(Node.getMemoizationData(), PointerParents);
- if (ParentList.size() == 1 && TK == TK_IgnoreUnlessSpelledInSource) {
- const auto *E = ParentList[0].get<Expr>();
- const auto *Child = Node.get<Expr>();
- if (E && Child)
- return AscendIgnoreUnlessSpelledInSource(E, Child);
+ if (ParentList.size() > 0 && TK == TK_IgnoreUnlessSpelledInSource) {
+
+ const auto *ChildExpr = Node.get<Expr>();
+
+ {
+ // Don't match explicit node types because different stdlib
+ // implementations implement this in different ways and have
+ // different intermediate nodes.
+ // Look up 4 levels for a cxxRewrittenBinaryOperator as that is
+ // enough for the major stdlib implementations.
+ auto RewrittenBinOpParentsList = ParentList;
+ int I = 0;
+ while (ChildExpr && RewrittenBinOpParentsList.size() == 1 &&
+ I++ < 4) {
+ const auto *S = RewrittenBinOpParentsList[0].get<Stmt>();
+ if (!S)
+ break;
+
+ const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S);
+ if (!RWBO) {
+ RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents);
+ continue;
+ }
+ if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr &&
+ RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr)
+ break;
+ return DynTypedNode::create(*RWBO);
+ }
+ }
+
+ const auto *ParentExpr = ParentList[0].get<Expr>();
+ if (ParentExpr && ChildExpr)
+ return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr);
+
+ {
+ auto AncestorNodes =
+ matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this);
+ if (std::get<bool>(AncestorNodes) &&
+ std::get<const CXXForRangeStmt *>(AncestorNodes)
+ ->getLoopVarStmt() ==
+ std::get<const DeclStmt *>(AncestorNodes))
+ return std::get<DynTypedNodeList>(AncestorNodes);
+ }
+ {
+ auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>(
+ ParentList, this);
+ if (std::get<bool>(AncestorNodes) &&
+ std::get<const CXXForRangeStmt *>(AncestorNodes)
+ ->getRangeStmt() ==
+ std::get<const DeclStmt *>(AncestorNodes))
+ return std::get<DynTypedNodeList>(AncestorNodes);
+ }
+ {
+ auto AncestorNodes =
+ matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList,
+ this);
+ if (std::get<bool>(AncestorNodes))
+ return std::get<DynTypedNodeList>(AncestorNodes);
+ }
+ {
+ auto AncestorNodes =
+ matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>(
+ ParentList, this);
+ if (std::get<bool>(AncestorNodes))
+ return std::get<DynTypedNodeList>(AncestorNodes);
+ }
}
return ParentList;
}
@@ -194,6 +265,59 @@
}
};
+template <typename Tuple, std::size_t... Is>
+auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
+ return std::make_tuple(std::get<1 + Is>(tuple)...);
+}
+
+template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
+ return tuple_pop_front_impl(
+ tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
+}
+
+template <typename T, typename... U> struct MatchParents {
+ static std::tuple<bool, DynTypedNodeList, const T *, const U *...>
+ match(const DynTypedNodeList &NodeList,
+ ParentMapContext::ParentMap *ParentMap) {
+ if (const auto *TypedNode = NodeList[0].get<T>()) {
+ auto NextParentList =
+ ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
+ if (NextParentList.size() == 1) {
+ auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap);
+ if (std::get<bool>(TailTuple)) {
+ return std::tuple_cat(
+ std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple),
+ TypedNode),
+ tuple_pop_front(tuple_pop_front(TailTuple)));
+ }
+ }
+ }
+ return std::tuple_cat(std::make_tuple(false, NodeList),
+ std::tuple<const T *, const U *...>());
+ }
+};
+
+template <typename T> struct MatchParents<T> {
+ static std::tuple<bool, DynTypedNodeList, const T *>
+ match(const DynTypedNodeList &NodeList,
+ ParentMapContext::ParentMap *ParentMap) {
+ if (const auto *TypedNode = NodeList[0].get<T>()) {
+ auto NextParentList =
+ ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
+ if (NextParentList.size() == 1)
+ return std::make_tuple(true, NodeList, TypedNode);
+ }
+ return std::make_tuple(false, NodeList, nullptr);
+ }
+};
+
+template <typename T, typename... U>
+std::tuple<bool, DynTypedNodeList, const T *, const U *...>
+matchParents(const DynTypedNodeList &NodeList,
+ ParentMapContext::ParentMap *ParentMap) {
+ return MatchParents<T, U...>::match(NodeList, ParentMap);
+}
+
/// Template specializations to abstract away from pointers and TypeLocs.
/// @{
template <typename T> static DynTypedNode createDynTypedNode(const T &Node) {
diff --git a/src/llvm-project/clang/lib/AST/PrintfFormatString.cpp b/src/llvm-project/clang/lib/AST/PrintfFormatString.cpp
index a1abaf2..4806c55 100644
--- a/src/llvm-project/clang/lib/AST/PrintfFormatString.cpp
+++ b/src/llvm-project/clang/lib/AST/PrintfFormatString.cpp
@@ -794,6 +794,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
#define SIGNED_TYPE(Id, SingletonId)
#define UNSIGNED_TYPE(Id, SingletonId)
#define FLOATING_TYPE(Id, SingletonId)
diff --git a/src/llvm-project/clang/lib/AST/QualTypeNames.cpp b/src/llvm-project/clang/lib/AST/QualTypeNames.cpp
index 73a33a2..9a1b418 100644
--- a/src/llvm-project/clang/lib/AST/QualTypeNames.cpp
+++ b/src/llvm-project/clang/lib/AST/QualTypeNames.cpp
@@ -356,11 +356,19 @@
const TypeDecl *TD,
bool FullyQualify,
bool WithGlobalNsPrefix) {
+ const Type *TypePtr = TD->getTypeForDecl();
+ if (isa<const TemplateSpecializationType>(TypePtr) ||
+ isa<const RecordType>(TypePtr)) {
+ // We are asked to fully qualify and we have a Record Type (which
+ // may point to a template specialization) or Template
+ // Specialization Type. We need to fully qualify their arguments.
+
+ TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix);
+ }
+
return NestedNameSpecifier::Create(
- Ctx,
- createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
- false /*No TemplateKeyword*/,
- TD->getTypeForDecl());
+ Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
+ false /*No TemplateKeyword*/, TypePtr);
}
/// Return the fully qualified type, including fully-qualified
diff --git a/src/llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp b/src/llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp
index 95d69fa..972690b 100644
--- a/src/llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/src/llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -1528,12 +1528,17 @@
UpdateAlignment(TypeAlign);
}
+static bool isAIXLayout(const ASTContext &Context) {
+ return Context.getTargetInfo().getTriple().getOS() == llvm::Triple::AIX;
+}
+
void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
uint64_t FieldSize = D->getBitWidthValue(Context);
TypeInfo FieldInfo = Context.getTypeInfo(D->getType());
uint64_t StorageUnitSize = FieldInfo.Width;
unsigned FieldAlign = FieldInfo.Align;
+ bool AlignIsRequired = FieldInfo.AlignIsRequired;
// UnfilledBitsInLastUnit is the difference between the end of the
// last allocated bitfield (i.e. the first bit offset available for
@@ -1611,9 +1616,33 @@
}
}
+ if (isAIXLayout(Context)) {
+ if (StorageUnitSize < Context.getTypeSize(Context.UnsignedIntTy)) {
+ // On AIX, [bool, char, short] bitfields have the same alignment
+ // as [unsigned].
+ StorageUnitSize = Context.getTypeSize(Context.UnsignedIntTy);
+ } else if (StorageUnitSize > Context.getTypeSize(Context.UnsignedIntTy) &&
+ Context.getTargetInfo().getTriple().isArch32Bit() &&
+ FieldSize <= 32) {
+ // Under 32-bit compile mode, the bitcontainer is 32 bits if a single
+ // long long bitfield has length no greater than 32 bits.
+ StorageUnitSize = 32;
+
+ if (!AlignIsRequired)
+ FieldAlign = 32;
+ }
+
+ if (FieldAlign < StorageUnitSize) {
+ // The bitfield alignment should always be greater than or equal to
+ // bitcontainer size.
+ FieldAlign = StorageUnitSize;
+ }
+ }
+
// If the field is wider than its declared type, it follows
- // different rules in all cases.
- if (FieldSize > StorageUnitSize) {
+ // different rules in all cases, except on AIX.
+ // On AIX, wide bitfield follows the same rules as normal bitfield.
+ if (FieldSize > StorageUnitSize && !isAIXLayout(Context)) {
LayoutWideBitField(FieldSize, StorageUnitSize, FieldPacked, D);
return;
}
@@ -1627,12 +1656,17 @@
// Some such targets do honor it on zero-width bitfields.
if (FieldSize == 0 &&
Context.getTargetInfo().useZeroLengthBitfieldAlignment()) {
- // The alignment to round up to is the max of the field's natural
- // alignment and a target-specific fixed value (sometimes zero).
- unsigned ZeroLengthBitfieldBoundary =
- Context.getTargetInfo().getZeroLengthBitfieldBoundary();
- FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
-
+ // Some targets don't honor leading zero-width bitfield.
+ if (!IsUnion && FieldOffset == 0 &&
+ !Context.getTargetInfo().useLeadingZeroLengthBitfield())
+ FieldAlign = 1;
+ else {
+ // The alignment to round up to is the max of the field's natural
+ // alignment and a target-specific fixed value (sometimes zero).
+ unsigned ZeroLengthBitfieldBoundary =
+ Context.getTargetInfo().getZeroLengthBitfieldBoundary();
+ FieldAlign = std::max(FieldAlign, ZeroLengthBitfieldBoundary);
+ }
// If that doesn't apply, just ignore the field alignment.
} else {
FieldAlign = 1;
@@ -1741,6 +1775,12 @@
!D->getIdentifier())
FieldAlign = UnpackedFieldAlign = 1;
+ // On AIX, zero-width bitfields pad out to the alignment boundary, but then
+ // do not affect overall record alignment if there is a pragma pack or
+ // pragma align(packed).
+ if (isAIXLayout(Context) && !MaxFieldAlignment.isZero() && !FieldSize)
+ FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
+
// Diagnose differences in layout due to padding or packing.
if (!UseExternalLayout)
CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset,
@@ -2288,7 +2328,8 @@
// If the key function is dllimport but the class isn't, then the class has
// no key function. The DLL that exports the key function won't export the
// vtable in this case.
- if (MD->hasAttr<DLLImportAttr>() && !RD->hasAttr<DLLImportAttr>())
+ if (MD->hasAttr<DLLImportAttr>() && !RD->hasAttr<DLLImportAttr>() &&
+ !Context.getTargetInfo().hasPS4DLLImportExport())
return nullptr;
// We found it.
@@ -3542,7 +3583,10 @@
} else {
PrintOffset(OS, FieldOffset, IndentLevel);
}
- OS << Field.getType().getAsString() << ' ' << Field << '\n';
+ const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical
+ ? Field.getType().getCanonicalType()
+ : Field.getType();
+ OS << FieldType.getAsString() << ' ' << Field << '\n';
}
// Dump virtual bases.
diff --git a/src/llvm-project/clang/lib/AST/Stmt.cpp b/src/llvm-project/clang/lib/AST/Stmt.cpp
index 83821ea..47693ef9 100644
--- a/src/llvm-project/clang/lib/AST/Stmt.cpp
+++ b/src/llvm-project/clang/lib/AST/Stmt.cpp
@@ -646,6 +646,8 @@
continue;
}
+ const TargetInfo &TI = C.getTargetInfo();
+
// Escaped "%" character in asm string.
if (CurPtr == StrEnd) {
// % at end of string is invalid (no escape).
@@ -656,6 +658,11 @@
char EscapedChar = *CurPtr++;
switch (EscapedChar) {
default:
+ // Handle target-specific escaped characters.
+ if (auto MaybeReplaceStr = TI.handleAsmEscapedChar(EscapedChar)) {
+ CurStringPiece += *MaybeReplaceStr;
+ continue;
+ }
break;
case '%': // %% -> %
case '{': // %{ -> {
@@ -688,7 +695,6 @@
EscapedChar = *CurPtr++;
}
- const TargetInfo &TI = C.getTargetInfo();
const SourceManager &SM = C.getSourceManager();
const LangOptions &LO = C.getLangOpts();
@@ -989,12 +995,20 @@
return isa<ObjCAvailabilityCheckExpr>(getCond());
}
-Optional<const Stmt*> IfStmt::getNondiscardedCase(const ASTContext &Ctx) const {
+Optional<Stmt *> IfStmt::getNondiscardedCase(const ASTContext &Ctx) {
if (!isConstexpr() || getCond()->isValueDependent())
return None;
return !getCond()->EvaluateKnownConstInt(Ctx) ? getElse() : getThen();
}
+Optional<const Stmt *>
+IfStmt::getNondiscardedCase(const ASTContext &Ctx) const {
+ if (Optional<Stmt *> Result =
+ const_cast<IfStmt *>(this)->getNondiscardedCase(Ctx))
+ return *Result;
+ return None;
+}
+
ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
SourceLocation RP)
@@ -1266,13 +1280,6 @@
break;
case VCK_ByCopy:
assert(Var && "capturing by copy must have a variable!");
- assert(
- (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() &&
- Var->getType()
- ->castAs<ReferenceType>()
- ->getPointeeType()
- ->isScalarType())) &&
- "captures by copy are expected to have a scalar type!");
break;
case VCK_VLAType:
assert(!Var &&
diff --git a/src/llvm-project/clang/lib/AST/StmtOpenMP.cpp b/src/llvm-project/clang/lib/AST/StmtOpenMP.cpp
index c858261..b0ef2f4 100644
--- a/src/llvm-project/clang/lib/AST/StmtOpenMP.cpp
+++ b/src/llvm-project/clang/lib/AST/StmtOpenMP.cpp
@@ -74,8 +74,9 @@
return getRawStmt();
}
-Stmt *OMPLoopDirective::tryToFindNextInnerLoop(Stmt *CurStmt,
- bool TryImperfectlyNestedLoops) {
+Stmt *
+OMPLoopBasedDirective::tryToFindNextInnerLoop(Stmt *CurStmt,
+ bool TryImperfectlyNestedLoops) {
Stmt *OrigStmt = CurStmt;
CurStmt = CurStmt->IgnoreContainers();
// Additional work for imperfectly nested loops, introduced in OpenMP 5.0.
@@ -91,7 +92,10 @@
for (Stmt *S : CS->body()) {
if (!S)
continue;
- if (isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) {
+ if (auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S))
+ S = CanonLoop->getLoopStmt();
+ if (isa<ForStmt>(S) || isa<CXXForRangeStmt>(S) ||
+ (isa<OMPLoopBasedDirective>(S) && !isa<OMPLoopDirective>(S))) {
// Only single loop construct is allowed.
if (CurStmt) {
CurStmt = OrigStmt;
@@ -118,75 +122,133 @@
return CurStmt;
}
+bool OMPLoopBasedDirective::doForAllLoops(
+ Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
+ llvm::function_ref<bool(unsigned, Stmt *)> Callback,
+ llvm::function_ref<void(OMPLoopBasedDirective *)>
+ OnTransformationCallback) {
+ CurStmt = CurStmt->IgnoreContainers();
+ for (unsigned Cnt = 0; Cnt < NumLoops; ++Cnt) {
+ while (true) {
+ auto *OrigStmt = CurStmt;
+ if (auto *Dir = dyn_cast<OMPTileDirective>(OrigStmt)) {
+ OnTransformationCallback(Dir);
+ CurStmt = Dir->getTransformedStmt();
+ } else if (auto *Dir = dyn_cast<OMPUnrollDirective>(OrigStmt)) {
+ OnTransformationCallback(Dir);
+ CurStmt = Dir->getTransformedStmt();
+ } else {
+ break;
+ }
+
+ if (!CurStmt) {
+ // May happen if the loop transformation does not result in a generated
+ // loop (such as full unrolling).
+ CurStmt = OrigStmt;
+ break;
+ }
+ }
+ if (auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(CurStmt))
+ CurStmt = CanonLoop->getLoopStmt();
+ if (Callback(Cnt, CurStmt))
+ return false;
+ // Move on to the next nested for loop, or to the loop body.
+ // OpenMP [2.8.1, simd construct, Restrictions]
+ // All loops associated with the construct must be perfectly nested; that
+ // is, there must be no intervening code nor any OpenMP directive between
+ // any two loops.
+ if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
+ CurStmt = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(CurStmt) &&
+ "Expected canonical for or range-based for loops.");
+ CurStmt = cast<CXXForRangeStmt>(CurStmt)->getBody();
+ }
+ CurStmt = OMPLoopBasedDirective::tryToFindNextInnerLoop(
+ CurStmt, TryImperfectlyNestedLoops);
+ }
+ return true;
+}
+
+void OMPLoopBasedDirective::doForAllLoopsBodies(
+ Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
+ llvm::function_ref<void(unsigned, Stmt *, Stmt *)> Callback) {
+ bool Res = OMPLoopBasedDirective::doForAllLoops(
+ CurStmt, TryImperfectlyNestedLoops, NumLoops,
+ [Callback](unsigned Cnt, Stmt *Loop) {
+ Stmt *Body = nullptr;
+ if (auto *For = dyn_cast<ForStmt>(Loop)) {
+ Body = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(Loop) &&
+ "Expected canonical for or range-based for loops.");
+ Body = cast<CXXForRangeStmt>(Loop)->getBody();
+ }
+ if (auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(Body))
+ Body = CanonLoop->getLoopStmt();
+ Callback(Cnt, Loop, Body);
+ return false;
+ });
+ assert(Res && "Expected only loops");
+ (void)Res;
+}
+
Stmt *OMPLoopDirective::getBody() {
// This relies on the loop form is already checked by Sema.
- Stmt *Body = Data->getRawStmt()->IgnoreContainers();
- if (auto *For = dyn_cast<ForStmt>(Body)) {
- Body = For->getBody();
- } else {
- assert(isa<CXXForRangeStmt>(Body) &&
- "Expected canonical for loop or range-based for loop.");
- Body = cast<CXXForRangeStmt>(Body)->getBody();
- }
- for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
- Body = tryToFindNextInnerLoop(Body, /*TryImperfectlyNestedLoops=*/true);
- if (auto *For = dyn_cast<ForStmt>(Body)) {
- Body = For->getBody();
- } else {
- assert(isa<CXXForRangeStmt>(Body) &&
- "Expected canonical for loop or range-based for loop.");
- Body = cast<CXXForRangeStmt>(Body)->getBody();
- }
- }
+ Stmt *Body = nullptr;
+ OMPLoopBasedDirective::doForAllLoopsBodies(
+ Data->getRawStmt(), /*TryImperfectlyNestedLoops=*/true,
+ NumAssociatedLoops,
+ [&Body](unsigned, Stmt *, Stmt *BodyStmt) { Body = BodyStmt; });
return Body;
}
void OMPLoopDirective::setCounters(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
+ assert(A.size() == getLoopsNumber() &&
"Number of loop counters is not the same as the collapsed number");
llvm::copy(A, getCounters().begin());
}
void OMPLoopDirective::setPrivateCounters(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() && "Number of loop private counters "
- "is not the same as the collapsed "
- "number");
+ assert(A.size() == getLoopsNumber() && "Number of loop private counters "
+ "is not the same as the collapsed "
+ "number");
llvm::copy(A, getPrivateCounters().begin());
}
void OMPLoopDirective::setInits(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
+ assert(A.size() == getLoopsNumber() &&
"Number of counter inits is not the same as the collapsed number");
llvm::copy(A, getInits().begin());
}
void OMPLoopDirective::setUpdates(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
+ assert(A.size() == getLoopsNumber() &&
"Number of counter updates is not the same as the collapsed number");
llvm::copy(A, getUpdates().begin());
}
void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
+ assert(A.size() == getLoopsNumber() &&
"Number of counter finals is not the same as the collapsed number");
llvm::copy(A, getFinals().begin());
}
void OMPLoopDirective::setDependentCounters(ArrayRef<Expr *> A) {
assert(
- A.size() == getCollapsedNumber() &&
+ A.size() == getLoopsNumber() &&
"Number of dependent counters is not the same as the collapsed number");
llvm::copy(A, getDependentCounters().begin());
}
void OMPLoopDirective::setDependentInits(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
+ assert(A.size() == getLoopsNumber() &&
"Number of dependent inits is not the same as the collapsed number");
llvm::copy(A, getDependentInits().begin());
}
void OMPLoopDirective::setFinalsConditions(ArrayRef<Expr *> A) {
- assert(A.size() == getCollapsedNumber() &&
+ assert(A.size() == getLoopsNumber() &&
"Number of finals conditions is not the same as the collapsed number");
llvm::copy(A, getFinalsConditions().begin());
}
@@ -291,6 +353,46 @@
numLoopChildren(CollapsedNum, OMPD_for) + 1, CollapsedNum);
}
+OMPTileDirective *
+OMPTileDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
+ unsigned NumLoops, Stmt *AssociatedStmt,
+ Stmt *TransformedStmt, Stmt *PreInits) {
+ OMPTileDirective *Dir = createDirective<OMPTileDirective>(
+ C, Clauses, AssociatedStmt, TransformedStmtOffset + 1, StartLoc, EndLoc,
+ NumLoops);
+ Dir->setTransformedStmt(TransformedStmt);
+ Dir->setPreInits(PreInits);
+ return Dir;
+}
+
+OMPTileDirective *OMPTileDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned NumLoops) {
+ return createEmptyDirective<OMPTileDirective>(
+ C, NumClauses, /*HasAssociatedStmt=*/true, TransformedStmtOffset + 1,
+ SourceLocation(), SourceLocation(), NumLoops);
+}
+
+OMPUnrollDirective *
+OMPUnrollDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, Stmt *TransformedStmt,
+ Stmt *PreInits) {
+ auto *Dir = createDirective<OMPUnrollDirective>(
+ C, Clauses, AssociatedStmt, TransformedStmtOffset + 1, StartLoc, EndLoc);
+ Dir->setTransformedStmt(TransformedStmt);
+ Dir->setPreInits(PreInits);
+ return Dir;
+}
+
+OMPUnrollDirective *OMPUnrollDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses) {
+ return createEmptyDirective<OMPUnrollDirective>(
+ C, NumClauses, /*HasAssociatedStmt=*/true, TransformedStmtOffset + 1,
+ SourceLocation(), SourceLocation());
+}
+
OMPForSimdDirective *
OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
@@ -1880,3 +1982,53 @@
numLoopChildren(CollapsedNum, OMPD_target_teams_distribute_simd),
CollapsedNum);
}
+
+OMPInteropDirective *
+OMPInteropDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses) {
+ return createDirective<OMPInteropDirective>(
+ C, Clauses, /*AssociatedStmt=*/nullptr, /*NumChildren=*/0, StartLoc,
+ EndLoc);
+}
+
+OMPInteropDirective *OMPInteropDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ return createEmptyDirective<OMPInteropDirective>(C, NumClauses);
+}
+
+OMPDispatchDirective *OMPDispatchDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ SourceLocation TargetCallLoc) {
+ auto *Dir = createDirective<OMPDispatchDirective>(
+ C, Clauses, AssociatedStmt, /*NumChildren=*/0, StartLoc, EndLoc);
+ Dir->setTargetCallLoc(TargetCallLoc);
+ return Dir;
+}
+
+OMPDispatchDirective *OMPDispatchDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ return createEmptyDirective<OMPDispatchDirective>(C, NumClauses,
+ /*HasAssociatedStmt=*/true,
+ /*NumChildren=*/0);
+}
+
+OMPMaskedDirective *OMPMaskedDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ return createDirective<OMPMaskedDirective>(C, Clauses, AssociatedStmt,
+ /*NumChildren=*/0, StartLoc,
+ EndLoc);
+}
+
+OMPMaskedDirective *OMPMaskedDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ return createEmptyDirective<OMPMaskedDirective>(C, NumClauses,
+ /*HasAssociatedStmt=*/true);
+}
diff --git a/src/llvm-project/clang/lib/AST/StmtPrinter.cpp b/src/llvm-project/clang/lib/AST/StmtPrinter.cpp
index 55a7211..45b1517 100644
--- a/src/llvm-project/clang/lib/AST/StmtPrinter.cpp
+++ b/src/llvm-project/clang/lib/AST/StmtPrinter.cpp
@@ -47,11 +47,11 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <string>
@@ -636,6 +636,10 @@
// OpenMP directives printing methods
//===----------------------------------------------------------------------===//
+void StmtPrinter::VisitOMPCanonicalLoop(OMPCanonicalLoop *Node) {
+ PrintStmt(Node->getLoopStmt());
+}
+
void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S,
bool ForceNoStmt) {
OMPClausePrinter Printer(OS, Policy);
@@ -660,6 +664,16 @@
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPTileDirective(OMPTileDirective *Node) {
+ Indent() << "#pragma omp tile";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPUnrollDirective(OMPUnrollDirective *Node) {
+ Indent() << "#pragma omp unroll";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) {
Indent() << "#pragma omp for";
PrintOMPExecutableDirective(Node);
@@ -953,6 +967,21 @@
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPInteropDirective(OMPInteropDirective *Node) {
+ Indent() << "#pragma omp interop";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPDispatchDirective(OMPDispatchDirective *Node) {
+ Indent() << "#pragma omp dispatch";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPMaskedDirective(OMPMaskedDirective *Node) {
+ Indent() << "#pragma omp masked";
+ PrintOMPExecutableDirective(Node);
+}
+
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
@@ -979,8 +1008,13 @@
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getNameInfo();
- if (Node->hasExplicitTemplateArgs())
- printTemplateArgumentList(OS, Node->template_arguments(), Policy);
+ if (Node->hasExplicitTemplateArgs()) {
+ const TemplateParameterList *TPL = nullptr;
+ if (!Node->hadMultipleCandidates())
+ if (auto *TD = dyn_cast<TemplateDecl>(Node->getDecl()))
+ TPL = TD->getTemplateParameters();
+ printTemplateArgumentList(OS, Node->template_arguments(), Policy, TPL);
+ }
}
void StmtPrinter::VisitDependentScopeDeclRefExpr(
@@ -1053,70 +1087,19 @@
OS << "]";
}
+void StmtPrinter::VisitSYCLUniqueStableNameExpr(
+ SYCLUniqueStableNameExpr *Node) {
+ OS << "__builtin_sycl_unique_stable_name(";
+ Node->getTypeSourceInfo()->getType().print(OS, Policy);
+ OS << ")";
+}
+
void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
OS << PredefinedExpr::getIdentKindName(Node->getIdentKind());
}
void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
- unsigned value = Node->getValue();
-
- switch (Node->getKind()) {
- case CharacterLiteral::Ascii: break; // no prefix.
- case CharacterLiteral::Wide: OS << 'L'; break;
- case CharacterLiteral::UTF8: OS << "u8"; break;
- case CharacterLiteral::UTF16: OS << 'u'; break;
- case CharacterLiteral::UTF32: OS << 'U'; break;
- }
-
- switch (value) {
- case '\\':
- OS << "'\\\\'";
- break;
- case '\'':
- OS << "'\\''";
- break;
- case '\a':
- // TODO: K&R: the meaning of '\\a' is different in traditional C
- OS << "'\\a'";
- break;
- case '\b':
- OS << "'\\b'";
- break;
- // Nonstandard escape sequence.
- /*case '\e':
- OS << "'\\e'";
- break;*/
- case '\f':
- OS << "'\\f'";
- break;
- case '\n':
- OS << "'\\n'";
- break;
- case '\r':
- OS << "'\\r'";
- break;
- case '\t':
- OS << "'\\t'";
- break;
- case '\v':
- OS << "'\\v'";
- break;
- default:
- // A character literal might be sign-extended, which
- // would result in an invalid \U escape sequence.
- // FIXME: multicharacter literals such as '\xFF\xFF\xFF\xFF'
- // are not correctly handled.
- if ((value & ~0xFFu) == ~0xFFu && Node->getKind() == CharacterLiteral::Ascii)
- value &= 0xFFu;
- if (value < 256 && isPrintable((unsigned char)value))
- OS << "'" << (char)value << "'";
- else if (value < 256)
- OS << "'\\x" << llvm::format("%02x", value) << "'";
- else if (value <= 0xFFFF)
- OS << "'\\u" << llvm::format("%04x", value) << "'";
- else
- OS << "'\\U" << llvm::format("%08x", value) << "'";
- }
+ CharacterLiteral::print(Node->getValue(), Node->getKind(), OS);
}
/// Prints the given expression using the original source text. Returns true on
@@ -1140,7 +1123,7 @@
if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
return;
bool isSigned = Node->getType()->isSignedIntegerType();
- OS << Node->getValue().toString(10, isSigned);
+ OS << toString(Node->getValue(), 10, isSigned);
// Emit suffixes. Integer literals are always a builtin integer type.
switch (Node->getType()->castAs<BuiltinType>()->getKind()) {
@@ -1156,6 +1139,10 @@
case BuiltinType::ULong: OS << "UL"; break;
case BuiltinType::LongLong: OS << "LL"; break;
case BuiltinType::ULongLong: OS << "ULL"; break;
+ case BuiltinType::Int128:
+ break; // no suffix.
+ case BuiltinType::UInt128:
+ break; // no suffix.
}
}
@@ -1438,8 +1425,16 @@
if (Node->hasTemplateKeyword())
OS << "template ";
OS << Node->getMemberNameInfo();
+ const TemplateParameterList *TPL = nullptr;
+ if (auto *FD = dyn_cast<FunctionDecl>(Node->getMemberDecl())) {
+ if (!Node->hadMultipleCandidates())
+ if (auto *FTD = FD->getPrimaryTemplate())
+ TPL = FTD->getTemplateParameters();
+ } else if (auto *VTSD =
+ dyn_cast<VarTemplateSpecializationDecl>(Node->getMemberDecl()))
+ TPL = VTSD->getSpecializedTemplate()->getTemplateParameters();
if (Node->hasExplicitTemplateArgs())
- printTemplateArgumentList(OS, Node->template_arguments(), Policy);
+ printTemplateArgumentList(OS, Node->template_arguments(), Policy, TPL);
}
void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) {
@@ -1853,8 +1848,12 @@
assert(Args);
if (Args->size() != 1) {
+ const TemplateParameterList *TPL = nullptr;
+ if (!DRE->hadMultipleCandidates())
+ if (const auto *TD = dyn_cast<TemplateDecl>(DRE->getDecl()))
+ TPL = TD->getTemplateParameters();
OS << "operator\"\"" << Node->getUDSuffix()->getName();
- printTemplateArgumentList(OS, Args->asArray(), Policy);
+ printTemplateArgumentList(OS, Args->asArray(), Policy, TPL);
OS << "()";
return;
}
@@ -1869,7 +1868,7 @@
case UserDefinedLiteral::LOK_Integer: {
// Print integer literal without suffix.
const auto *Int = cast<IntegerLiteral>(Node->getCookedLiteral());
- OS << Int->getValue().toString(10, /*isSigned*/false);
+ OS << toString(Int->getValue(), 10, /*isSigned*/false);
break;
}
case UserDefinedLiteral::LOK_Floating: {
@@ -2304,7 +2303,8 @@
OS << "template ";
OS << E->getFoundDecl()->getName();
printTemplateArgumentList(OS, E->getTemplateArgsAsWritten()->arguments(),
- Policy);
+ Policy,
+ E->getNamedConcept()->getTemplateParameters());
}
void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) {
diff --git a/src/llvm-project/clang/lib/AST/StmtProfile.cpp b/src/llvm-project/clang/lib/AST/StmtProfile.cpp
index de9de6f..ed000c2 100644
--- a/src/llvm-project/clang/lib/AST/StmtProfile.cpp
+++ b/src/llvm-project/clang/lib/AST/StmtProfile.cpp
@@ -462,6 +462,19 @@
Profiler->VisitStmt(C->getSimdlen());
}
+void OMPClauseProfiler::VisitOMPSizesClause(const OMPSizesClause *C) {
+ for (auto E : C->getSizesRefs())
+ if (E)
+ Profiler->VisitExpr(E);
+}
+
+void OMPClauseProfiler::VisitOMPFullClause(const OMPFullClause *C) {}
+
+void OMPClauseProfiler::VisitOMPPartialClause(const OMPPartialClause *C) {
+ if (const Expr *Factor = C->getFactor())
+ Profiler->VisitExpr(Factor);
+}
+
void OMPClauseProfiler::VisitOMPAllocatorClause(const OMPAllocatorClause *C) {
if (C->getAllocator())
Profiler->VisitStmt(C->getAllocator());
@@ -477,6 +490,18 @@
Profiler->VisitStmt(Evt);
}
+void OMPClauseProfiler::VisitOMPNovariantsClause(const OMPNovariantsClause *C) {
+ VistOMPClauseWithPreInit(C);
+ if (C->getCondition())
+ Profiler->VisitStmt(C->getCondition());
+}
+
+void OMPClauseProfiler::VisitOMPNocontextClause(const OMPNocontextClause *C) {
+ VistOMPClauseWithPreInit(C);
+ if (C->getCondition())
+ Profiler->VisitStmt(C->getCondition());
+}
+
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { }
@@ -537,7 +562,25 @@
void OMPClauseProfiler::VisitOMPNogroupClause(const OMPNogroupClause *) {}
-void OMPClauseProfiler::VisitOMPDestroyClause(const OMPDestroyClause *) {}
+void OMPClauseProfiler::VisitOMPInitClause(const OMPInitClause *C) {
+ VisitOMPClauseList(C);
+}
+
+void OMPClauseProfiler::VisitOMPUseClause(const OMPUseClause *C) {
+ if (C->getInteropVar())
+ Profiler->VisitStmt(C->getInteropVar());
+}
+
+void OMPClauseProfiler::VisitOMPDestroyClause(const OMPDestroyClause *C) {
+ if (C->getInteropVar())
+ Profiler->VisitStmt(C->getInteropVar());
+}
+
+void OMPClauseProfiler::VisitOMPFilterClause(const OMPFilterClause *C) {
+ VistOMPClauseWithPreInit(C);
+ if (C->getThreadID())
+ Profiler->VisitStmt(C->getThreadID());
+}
template<typename T>
void OMPClauseProfiler::VisitOMPClauseList(T *Node) {
@@ -848,10 +891,18 @@
P.Visit(*I);
}
-void StmtProfiler::VisitOMPLoopDirective(const OMPLoopDirective *S) {
+void StmtProfiler::VisitOMPCanonicalLoop(const OMPCanonicalLoop *L) {
+ VisitStmt(L);
+}
+
+void StmtProfiler::VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPLoopDirective(const OMPLoopDirective *S) {
+ VisitOMPLoopBasedDirective(S);
+}
+
void StmtProfiler::VisitOMPParallelDirective(const OMPParallelDirective *S) {
VisitOMPExecutableDirective(S);
}
@@ -860,6 +911,14 @@
VisitOMPLoopDirective(S);
}
+void StmtProfiler::VisitOMPTileDirective(const OMPTileDirective *S) {
+ VisitOMPLoopBasedDirective(S);
+}
+
+void StmtProfiler::VisitOMPUnrollDirective(const OMPUnrollDirective *S) {
+ VisitOMPLoopBasedDirective(S);
+}
+
void StmtProfiler::VisitOMPForDirective(const OMPForDirective *S) {
VisitOMPLoopDirective(S);
}
@@ -1110,6 +1169,18 @@
VisitOMPLoopDirective(S);
}
+void StmtProfiler::VisitOMPInteropDirective(const OMPInteropDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPDispatchDirective(const OMPDispatchDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPMaskedDirective(const OMPMaskedDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
@@ -1130,6 +1201,12 @@
}
}
+void StmtProfiler::VisitSYCLUniqueStableNameExpr(
+ const SYCLUniqueStableNameExpr *S) {
+ VisitExpr(S);
+ VisitType(S->getTypeSourceInfo()->getType());
+}
+
void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
VisitExpr(S);
ID.AddInteger(S->getIdentKind());
diff --git a/src/llvm-project/clang/lib/AST/TemplateBase.cpp b/src/llvm-project/clang/lib/AST/TemplateBase.cpp
index baf62bd..f44230d 100644
--- a/src/llvm-project/clang/lib/AST/TemplateBase.cpp
+++ b/src/llvm-project/clang/lib/AST/TemplateBase.cpp
@@ -31,6 +31,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
@@ -50,8 +51,11 @@
/// \param Out the raw_ostream instance to use for printing.
///
/// \param Policy the printing policy for EnumConstantDecl printing.
-static void printIntegral(const TemplateArgument &TemplArg,
- raw_ostream &Out, const PrintingPolicy& Policy) {
+///
+/// \param IncludeType If set, ensure that the type of the expression printed
+/// matches the type of the template argument.
+static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out,
+ const PrintingPolicy &Policy, bool IncludeType) {
const Type *T = TemplArg.getIntegralType().getTypePtr();
const llvm::APSInt &Val = TemplArg.getAsIntegral();
@@ -68,16 +72,86 @@
}
}
- if (T->isBooleanType() && !Policy.MSVCFormatting) {
- Out << (Val.getBoolValue() ? "true" : "false");
+ if (Policy.MSVCFormatting)
+ IncludeType = false;
+
+ if (T->isBooleanType()) {
+ if (!Policy.MSVCFormatting)
+ Out << (Val.getBoolValue() ? "true" : "false");
+ else
+ Out << Val;
} else if (T->isCharType()) {
- const char Ch = Val.getZExtValue();
- Out << ((Ch == '\'') ? "'\\" : "'");
- Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
- Out << "'";
- } else {
+ if (IncludeType) {
+ if (T->isSpecificBuiltinType(BuiltinType::SChar))
+ Out << "(signed char)";
+ else if (T->isSpecificBuiltinType(BuiltinType::UChar))
+ Out << "(unsigned char)";
+ }
+ CharacterLiteral::print(Val.getZExtValue(), CharacterLiteral::Ascii, Out);
+ } else if (T->isAnyCharacterType() && !Policy.MSVCFormatting) {
+ CharacterLiteral::CharacterKind Kind;
+ if (T->isWideCharType())
+ Kind = CharacterLiteral::Wide;
+ else if (T->isChar8Type())
+ Kind = CharacterLiteral::UTF8;
+ else if (T->isChar16Type())
+ Kind = CharacterLiteral::UTF16;
+ else if (T->isChar32Type())
+ Kind = CharacterLiteral::UTF32;
+ else
+ Kind = CharacterLiteral::Ascii;
+ CharacterLiteral::print(Val.getExtValue(), Kind, Out);
+ } else if (IncludeType) {
+ if (const auto *BT = T->getAs<BuiltinType>()) {
+ switch (BT->getKind()) {
+ case BuiltinType::ULongLong:
+ Out << Val << "ULL";
+ break;
+ case BuiltinType::LongLong:
+ Out << Val << "LL";
+ break;
+ case BuiltinType::ULong:
+ Out << Val << "UL";
+ break;
+ case BuiltinType::Long:
+ Out << Val << "L";
+ break;
+ case BuiltinType::UInt:
+ Out << Val << "U";
+ break;
+ case BuiltinType::Int:
+ Out << Val;
+ break;
+ default:
+ Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
+ << Val;
+ break;
+ }
+ } else
+ Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
+ << Val;
+ } else
Out << Val;
+}
+
+static unsigned getArrayDepth(QualType type) {
+ unsigned count = 0;
+ while (const auto *arrayType = type->getAsArrayTypeUnsafe()) {
+ count++;
+ type = arrayType->getElementType();
}
+ return count;
+}
+
+static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) {
+ // Generally, if the parameter type is a pointer, we must be taking the
+ // address of something and need a &. However, if the argument is an array,
+ // this could be implicit via array-to-pointer decay.
+ if (!paramType->isPointerType())
+ return paramType->isMemberPointerType();
+ if (argType->isArrayType())
+ return getArrayDepth(argType) == getArrayDepth(paramType->getPointeeType());
+ return true;
}
//===----------------------------------------------------------------------===//
@@ -340,8 +414,9 @@
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-void TemplateArgument::print(const PrintingPolicy &Policy,
- raw_ostream &Out) const {
+void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
+ bool IncludeType) const {
+
switch (getKind()) {
case Null:
Out << "(no value)";
@@ -355,21 +430,24 @@
}
case Declaration: {
+ // FIXME: Include the type if it's not obvious from the context.
NamedDecl *ND = getAsDecl();
if (getParamTypeForDecl()->isRecordType()) {
if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
- // FIXME: Include the type if it's not obvious from the context.
TPO->printAsInit(Out);
break;
}
}
- if (!getParamTypeForDecl()->isReferenceType())
- Out << '&';
+ if (auto *VD = dyn_cast<ValueDecl>(ND)) {
+ if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType()))
+ Out << "&";
+ }
ND->printQualifiedName(Out);
break;
}
case NullPtr:
+ // FIXME: Include the type if it's not obvious from the context.
Out << "nullptr";
break;
@@ -383,7 +461,7 @@
break;
case Integral:
- printIntegral(*this, Out, Policy);
+ printIntegral(*this, Out, Policy, IncludeType);
break;
case Expression:
@@ -399,7 +477,7 @@
else
Out << ", ";
- P.print(Policy, Out);
+ P.print(Policy, Out, IncludeType);
}
Out << ">";
break;
@@ -410,7 +488,7 @@
LangOptions LO; // FIXME! see also TemplateName::dump().
LO.CPlusPlus = true;
LO.Bool = true;
- print(PrintingPolicy(LO), Out);
+ print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
}
LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }
@@ -477,7 +555,7 @@
return DB << "nullptr";
case TemplateArgument::Integral:
- return DB << Arg.getAsIntegral().toString(10);
+ return DB << toString(Arg.getAsIntegral(), 10);
case TemplateArgument::Template:
return DB << Arg.getAsTemplate();
@@ -505,7 +583,7 @@
LangOptions LangOpts;
LangOpts.CPlusPlus = true;
PrintingPolicy Policy(LangOpts);
- Arg.print(Policy, OS);
+ Arg.print(Policy, OS, /*IncludeType*/ true);
return DB << OS.str();
}
}
diff --git a/src/llvm-project/clang/lib/AST/TextNodeDumper.cpp b/src/llvm-project/clang/lib/AST/TextNodeDumper.cpp
index e313275..33f914f 100644
--- a/src/llvm-project/clang/lib/AST/TextNodeDumper.cpp
+++ b/src/llvm-project/clang/lib/AST/TextNodeDumper.cpp
@@ -21,6 +21,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TypeTraits.h"
+#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <utility>
@@ -144,7 +145,7 @@
{
ColorScope Color(OS, ShowColors, ValueKindColor);
switch (E->getValueKind()) {
- case VK_RValue:
+ case VK_PRValue:
break;
case VK_LValue:
OS << " lvalue";
@@ -355,6 +356,46 @@
OS << " selected";
}
+void TextNodeDumper::Visit(const concepts::Requirement *R) {
+ if (!R) {
+ ColorScope Color(OS, ShowColors, NullColor);
+ OS << "<<<NULL>>> Requirement";
+ return;
+ }
+
+ {
+ ColorScope Color(OS, ShowColors, StmtColor);
+ switch (R->getKind()) {
+ case concepts::Requirement::RK_Type:
+ OS << "TypeRequirement";
+ break;
+ case concepts::Requirement::RK_Simple:
+ OS << "SimpleRequirement";
+ break;
+ case concepts::Requirement::RK_Compound:
+ OS << "CompoundRequirement";
+ break;
+ case concepts::Requirement::RK_Nested:
+ OS << "NestedRequirement";
+ break;
+ }
+ }
+
+ dumpPointer(R);
+
+ if (auto *ER = dyn_cast<concepts::ExprRequirement>(R)) {
+ if (ER->hasNoexceptRequirement())
+ OS << " noexcept";
+ }
+
+ if (R->isDependent())
+ OS << " dependent";
+ else
+ OS << (R->isSatisfied() ? " satisfied" : " unsatisfied");
+ if (R->containsUnexpandedParameterPack())
+ OS << " contains_unexpanded_pack";
+}
+
static double GetApproxValue(const llvm::APFloat &F) {
llvm::APFloat V = F;
bool ignored;
@@ -923,6 +964,8 @@
void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
OS << " '" << Node->getName() << "'";
+ if (Node->isSideEntry())
+ OS << " side_entry";
}
void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) {
@@ -1016,6 +1059,11 @@
OS << " isFreeIvar";
}
+void TextNodeDumper::VisitSYCLUniqueStableNameExpr(
+ const SYCLUniqueStableNameExpr *Node) {
+ dumpType(Node->getTypeSourceInfo()->getType());
+}
+
void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind());
}
@@ -1028,7 +1076,7 @@
void TextNodeDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
bool isSigned = Node->getType()->isSignedIntegerType();
ColorScope Color(OS, ShowColors, ValueColor);
- OS << " " << Node->getValue().toString(10, isSigned);
+ OS << " " << toString(Node->getValue(), 10, isSigned);
}
void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
@@ -1358,6 +1406,12 @@
dumpBareDeclRef(Node->getFoundDecl());
}
+void TextNodeDumper::VisitRequiresExpr(
+ const RequiresExpr *Node) {
+ if (!Node->isValueDependent())
+ OS << (Node->isSatisfied() ? " satisfied" : " unsatisfied");
+}
+
void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
if (T->isSpelledAsLValue())
OS << " written as lvalue reference";
@@ -2051,6 +2105,11 @@
OS << D->getDeclName();
}
+void TextNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *D) {
+ OS << ' ';
+ dumpBareDeclRef(D->getEnumDecl());
+}
+
void TextNodeDumper::VisitUnresolvedUsingTypenameDecl(
const UnresolvedUsingTypenameDecl *D) {
OS << ' ';
diff --git a/src/llvm-project/clang/lib/AST/Type.cpp b/src/llvm-project/clang/lib/AST/Type.cpp
index 034e175..4a2fc52 100644
--- a/src/llvm-project/clang/lib/AST/Type.cpp
+++ b/src/llvm-project/clang/lib/AST/Type.cpp
@@ -1801,6 +1801,9 @@
}
// Only these types can contain the desired 'auto' type.
+ Type *VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
+ return Visit(T->getReplacementType());
+ }
Type *VisitElaboratedType(const ElaboratedType *T) {
return Visit(T->getNamedType());
@@ -2086,8 +2089,9 @@
bool Type::hasUnsignedIntegerRepresentation() const {
if (const auto *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerOrEnumerationType();
- else
- return isUnsignedIntegerOrEnumerationType();
+ if (const auto *VT = dyn_cast<MatrixType>(CanonicalType))
+ return VT->getElementType()->isUnsignedIntegerOrEnumerationType();
+ return isUnsignedIntegerOrEnumerationType();
}
bool Type::isFloatingType() const {
@@ -2228,10 +2232,11 @@
return !Rec->isCompleteDefinition();
}
case ConstantArray:
+ case VariableArray:
// An array is incomplete if its element type is incomplete
// (C++ [dcl.array]p1).
- // We don't handle variable arrays (they're not allowed in C++) or
- // dependent-sized arrays (dependent types are never treated as incomplete).
+ // We don't handle dependent-sized arrays (dependent types are never treated
+ // as incomplete).
return cast<ArrayType>(CanonicalType)->getElementType()
->isIncompleteType(Def);
case IncompleteArray:
@@ -2279,6 +2284,8 @@
// SVE Types
#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
#include "clang/Basic/AArch64SVEACLETypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
return true;
default:
return false;
@@ -3088,6 +3095,10 @@
case Id: \
return #Name;
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) \
+ case Id: \
+ return Name;
+#include "clang/Basic/RISCVVTypes.def"
}
llvm_unreachable("Invalid builtin type.");
@@ -3134,6 +3145,7 @@
case CC_SpirFunction: return "spir_function";
case CC_OpenCLKernel: return "opencl_kernel";
case CC_Swift: return "swiftcall";
+ case CC_SwiftAsync: return "swiftasynccall";
case CC_PreserveMost: return "preserve_most";
case CC_PreserveAll: return "preserve_all";
}
@@ -3550,6 +3562,7 @@
case attr::ThisCall:
case attr::RegCall:
case attr::SwiftCall:
+ case attr::SwiftAsyncCall:
case attr::VectorCall:
case attr::AArch64VectorPcs:
case attr::Pascal:
@@ -4110,6 +4123,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
case BuiltinType::BuiltinFn:
case BuiltinType::NullPtr:
case BuiltinType::IncompleteMatrixIdx:
@@ -4387,8 +4402,8 @@
if (TypeConstraintConcept) {
TemplateArgument *ArgBuffer = getArgBuffer();
for (const TemplateArgument &Arg : TypeConstraintArgs) {
- addDependence(toTypeDependence(
- Arg.getDependence() & TemplateArgumentDependence::UnexpandedPack));
+ addDependence(
+ toSyntacticDependence(toTypeDependence(Arg.getDependence())));
new (ArgBuffer++) TemplateArgument(Arg);
}
diff --git a/src/llvm-project/clang/lib/AST/TypeLoc.cpp b/src/llvm-project/clang/lib/AST/TypeLoc.cpp
index 222b1ab..16d953b 100644
--- a/src/llvm-project/clang/lib/AST/TypeLoc.cpp
+++ b/src/llvm-project/clang/lib/AST/TypeLoc.cpp
@@ -406,6 +406,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
case BuiltinType::BuiltinFn:
case BuiltinType::IncompleteMatrixIdx:
case BuiltinType::OMPArraySection:
diff --git a/src/llvm-project/clang/lib/AST/TypePrinter.cpp b/src/llvm-project/clang/lib/AST/TypePrinter.cpp
index 25d7874..5de22f7 100644
--- a/src/llvm-project/clang/lib/AST/TypePrinter.cpp
+++ b/src/llvm-project/clang/lib/AST/TypePrinter.cpp
@@ -846,6 +846,8 @@
llvm_unreachable("asking for spelling of ordinary parameter ABI");
case ParameterABI::SwiftContext:
return "swift_context";
+ case ParameterABI::SwiftAsyncContext:
+ return "swift_async_context";
case ParameterABI::SwiftErrorResult:
return "swift_error_result";
case ParameterABI::SwiftIndirectResult:
@@ -974,6 +976,9 @@
case CC_Swift:
OS << " __attribute__((swiftcall))";
break;
+ case CC_SwiftAsync:
+ OS << "__attribute__((swiftasynccall))";
+ break;
case CC_PreserveMost:
OS << " __attribute__((preserve_most))";
break;
@@ -1125,7 +1130,9 @@
printBefore(T->getDeducedType(), OS);
} else {
if (T->isConstrained()) {
- OS << T->getTypeConstraintConcept()->getName();
+ // FIXME: Track a TypeConstraint as type sugar, so that we can print the
+ // type as it was written.
+ T->getTypeConstraintConcept()->getDeclName().print(OS, Policy);
auto Args = T->getTypeConstraintArguments();
if (!Args.empty())
printTemplateArgumentList(
@@ -1235,8 +1242,7 @@
// Only suppress an inline namespace if the name has the same lookup
// results in the enclosing namespace.
if (Policy.SuppressInlineNamespace && NS->isInline() && NameInScope &&
- DC->getParent()->lookup(NameInScope).size() ==
- DC->lookup(NameInScope).size())
+ NS->isRedundantInlineQualifierFor(NameInScope))
return AppendScope(DC->getParent(), OS, NameInScope);
AppendScope(DC->getParent(), OS, NS->getDeclName());
@@ -1304,8 +1310,10 @@
if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
OS << "lambda";
HasKindDecoration = true;
- } else {
+ } else if ((isa<RecordDecl>(D) && cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {
OS << "anonymous";
+ } else {
+ OS << "unnamed";
}
if (Policy.AnonymousTagLocations) {
@@ -1444,15 +1452,14 @@
T->getTemplateName().print(OS, Policy);
}
- const TemplateParameterList *TPL = TD ? TD->getTemplateParameters() : nullptr;
- printTemplateArgumentList(OS, T->template_arguments(), Policy, TPL);
+ printTemplateArgumentList(OS, T->template_arguments(), Policy);
spaceBeforePlaceHolder(OS);
}
void TypePrinter::printTemplateSpecializationBefore(
const TemplateSpecializationType *T,
raw_ostream &OS) {
- printTemplateId(T, OS, false);
+ printTemplateId(T, OS, Policy.FullyQualifiedName);
}
void TypePrinter::printTemplateSpecializationAfter(
@@ -1702,6 +1709,7 @@
case attr::StdCall: OS << "stdcall"; break;
case attr::ThisCall: OS << "thiscall"; break;
case attr::SwiftCall: OS << "swiftcall"; break;
+ case attr::SwiftAsyncCall: OS << "swiftasynccall"; break;
case attr::VectorCall: OS << "vectorcall"; break;
case attr::Pascal: OS << "pascal"; break;
case attr::MSABI: OS << "ms_abi"; break;
@@ -1842,16 +1850,17 @@
}
static void printArgument(const TemplateArgument &A, const PrintingPolicy &PP,
- llvm::raw_ostream &OS) {
- A.print(PP, OS);
+ llvm::raw_ostream &OS, bool IncludeType) {
+ A.print(PP, OS, IncludeType);
}
static void printArgument(const TemplateArgumentLoc &A,
- const PrintingPolicy &PP, llvm::raw_ostream &OS) {
+ const PrintingPolicy &PP, llvm::raw_ostream &OS,
+ bool IncludeType) {
const TemplateArgument::ArgKind &Kind = A.getArgument().getKind();
if (Kind == TemplateArgument::ArgKind::Type)
return A.getTypeSourceInfo()->getType().print(OS, PP);
- return A.getArgument().print(PP, OS);
+ return A.getArgument().print(PP, OS, IncludeType);
}
static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
@@ -1988,13 +1997,14 @@
return false;
}
-template<typename TA>
+template <typename TA>
static void printTo(raw_ostream &OS, ArrayRef<TA> Args,
const PrintingPolicy &Policy, bool SkipBrackets,
- const TemplateParameterList *TPL) {
+ const TemplateParameterList *TPL, bool IsPack,
+ unsigned ParmIndex) {
// Drop trailing template arguments that match default arguments.
if (TPL && Policy.SuppressDefaultTemplateArgs &&
- !Policy.PrintCanonicalTypes && !Args.empty() &&
+ !Policy.PrintCanonicalTypes && !Args.empty() && !IsPack &&
Args.size() <= TPL->size()) {
ASTContext &Ctx = TPL->getParam(0)->getASTContext();
llvm::SmallVector<TemplateArgument, 8> OrigArgs;
@@ -2021,12 +2031,15 @@
if (Argument.getKind() == TemplateArgument::Pack) {
if (Argument.pack_size() && !FirstArg)
OS << Comma;
- printTo(ArgOS, Argument.getPackAsArray(), Policy, true, nullptr);
+ printTo(ArgOS, Argument.getPackAsArray(), Policy, true, TPL,
+ /*IsPack*/ true, ParmIndex);
} else {
if (!FirstArg)
OS << Comma;
// Tries to print the argument with location info if exists.
- printArgument(Arg, Policy, ArgOS);
+ printArgument(
+ Arg, Policy, ArgOS,
+ TemplateParameterList::shouldIncludeTypeForArgument(TPL, ParmIndex));
}
StringRef ArgString = ArgOS.str();
@@ -2043,6 +2056,10 @@
NeedSpace = Policy.SplitTemplateClosers && !ArgString.empty() &&
ArgString.back() == '>';
FirstArg = false;
+
+ // Use same template parameter for all elements of Pack
+ if (!IsPack)
+ ParmIndex++;
}
if (NeedSpace)
@@ -2063,14 +2080,14 @@
ArrayRef<TemplateArgument> Args,
const PrintingPolicy &Policy,
const TemplateParameterList *TPL) {
- printTo(OS, Args, Policy, false, TPL);
+ printTo(OS, Args, Policy, false, TPL, /*isPack*/ false, /*parmIndex*/ 0);
}
void clang::printTemplateArgumentList(raw_ostream &OS,
ArrayRef<TemplateArgumentLoc> Args,
const PrintingPolicy &Policy,
const TemplateParameterList *TPL) {
- printTo(OS, Args, Policy, false, TPL);
+ printTo(OS, Args, Policy, false, TPL, /*isPack*/ false, /*parmIndex*/ 0);
}
std::string Qualifiers::getAsString() const {
@@ -2110,18 +2127,23 @@
case LangAS::Default:
return "";
case LangAS::opencl_global:
+ case LangAS::sycl_global:
return "__global";
case LangAS::opencl_local:
+ case LangAS::sycl_local:
return "__local";
case LangAS::opencl_private:
+ case LangAS::sycl_private:
return "__private";
case LangAS::opencl_constant:
return "__constant";
case LangAS::opencl_generic:
return "__generic";
case LangAS::opencl_global_device:
+ case LangAS::sycl_global_device:
return "__global_device";
case LangAS::opencl_global_host:
+ case LangAS::sycl_global_host:
return "__global_host";
case LangAS::cuda_device:
return "__device__";
diff --git a/src/llvm-project/clang/lib/AST/VTableBuilder.cpp b/src/llvm-project/clang/lib/AST/VTableBuilder.cpp
index f5865ce..38d6fc2 100644
--- a/src/llvm-project/clang/lib/AST/VTableBuilder.cpp
+++ b/src/llvm-project/clang/lib/AST/VTableBuilder.cpp
@@ -487,7 +487,7 @@
bool VCallOffsetMap::MethodsCanShareVCallOffset(const CXXMethodDecl *LHS,
const CXXMethodDecl *RHS) {
assert(VTableContextBase::hasVtableSlot(LHS) && "LHS must be virtual!");
- assert(VTableContextBase::hasVtableSlot(RHS) && "LHS must be virtual!");
+ assert(VTableContextBase::hasVtableSlot(RHS) && "RHS must be virtual!");
// A destructor can share a vcall offset with another destructor.
if (isa<CXXDestructorDecl>(LHS))
diff --git a/src/llvm-project/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/src/llvm-project/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 69957a9..5d6cea5 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/src/llvm-project/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -1036,6 +1036,7 @@
Callback(Callback) {}
void visitMatch(const BoundNodes& BoundNodesView) override {
+ TraversalKindScope RAII(*Context, Callback->getCheckTraversalKind());
Callback->run(MatchFinder::MatchResult(BoundNodesView, Context));
}
@@ -1216,6 +1217,8 @@
ScopedChildren = true;
if (FD->isTemplateInstantiation())
ScopedTraversal = true;
+ } else if (isa<BindingDecl>(DeclNode)) {
+ ScopedChildren = true;
}
ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
@@ -1333,7 +1336,13 @@
void MatchFinder::addMatcher(const DeclarationMatcher &NodeMatch,
MatchCallback *Action) {
- Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
+ llvm::Optional<TraversalKind> TK;
+ if (Action)
+ TK = Action->getCheckTraversalKind();
+ if (TK)
+ Matchers.DeclOrStmt.emplace_back(traverse(*TK, NodeMatch), Action);
+ else
+ Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.insert(Action);
}
@@ -1345,7 +1354,13 @@
void MatchFinder::addMatcher(const StatementMatcher &NodeMatch,
MatchCallback *Action) {
- Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
+ llvm::Optional<TraversalKind> TK;
+ if (Action)
+ TK = Action->getCheckTraversalKind();
+ if (TK)
+ Matchers.DeclOrStmt.emplace_back(traverse(*TK, NodeMatch), Action);
+ else
+ Matchers.DeclOrStmt.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.insert(Action);
}
@@ -1434,5 +1449,10 @@
StringRef MatchFinder::MatchCallback::getID() const { return "<unknown>"; }
+llvm::Optional<TraversalKind>
+MatchFinder::MatchCallback::getCheckTraversalKind() const {
+ return llvm::None;
+}
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/src/llvm-project/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/src/llvm-project/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 705f1cd..169ce3b 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/src/llvm-project/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -733,6 +733,7 @@
typeAliasTemplateDecl;
const internal::VariadicAllOfMatcher<Decl> decl;
const internal::VariadicDynCastAllOfMatcher<Decl, DecompositionDecl> decompositionDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, BindingDecl> bindingDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
linkageSpecDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
@@ -755,6 +756,7 @@
const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
accessSpecDecl;
+const internal::VariadicAllOfMatcher<CXXBaseSpecifier> cxxBaseSpecifier;
const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
const internal::VariadicAllOfMatcher<TemplateArgumentLoc> templateArgumentLoc;
@@ -839,6 +841,7 @@
const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr>
substNonTypeTemplateParmExpr;
const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
+const internal::VariadicDynCastAllOfMatcher<Decl, UsingEnumDecl> usingEnumDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl>
usingDirectiveDecl;
const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr>
@@ -882,6 +885,7 @@
const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CoreturnStmt> coreturnStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
@@ -914,6 +918,12 @@
const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr>
cxxNullPtrLiteralExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, ChooseExpr> chooseExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CoawaitExpr>
+ coawaitExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, DependentCoawaitExpr>
+ dependentCoawaitExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CoyieldExpr>
+ coyieldExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr;
const internal::VariadicDynCastAllOfMatcher<Stmt, GenericSelectionExpr>
genericSelectionExpr;
@@ -924,6 +934,7 @@
const internal::MapAnyOfMatcher<BinaryOperator, CXXOperatorCallExpr,
CXXRewrittenBinaryOperator>
binaryOperation;
+const internal::MapAnyOfMatcher<CallExpr, CXXConstructExpr> invocation;
const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> unaryOperator;
const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator>
conditionalOperator;
diff --git a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
index 88c2279..ba2f49e 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
+++ b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Diagnostics.cpp
@@ -100,6 +100,10 @@
return "Value not found: $0";
case Diagnostics::ET_RegistryUnknownEnumWithReplace:
return "Unknown value '$1' for arg $0; did you mean '$2'";
+ case Diagnostics::ET_RegistryNonNodeMatcher:
+ return "Matcher not a node matcher: $0";
+ case Diagnostics::ET_RegistryMatcherNoWithSupport:
+ return "Matcher does not support with call.";
case Diagnostics::ET_ParserStringError:
return "Error parsing string token: <$0>";
@@ -123,6 +127,10 @@
return "Error parsing numeric literal: <$0>";
case Diagnostics::ET_ParserOverloadedType:
return "Input value has unresolved overloaded type: $0";
+ case Diagnostics::ET_ParserMalformedChainedExpr:
+ return "Period not followed by valid chained call.";
+ case Diagnostics::ET_ParserFailedToBuildMatcher:
+ return "Failed to build matcher: $0.";
case Diagnostics::ET_None:
return "<N/A>";
diff --git a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp
index f6fdbe8..40db70e 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp
+++ b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.cpp
@@ -20,7 +20,7 @@
++MaxEditDistance;
llvm::StringRef Res;
for (const llvm::StringRef &Item : Allowed) {
- if (Item.equals_lower(Search)) {
+ if (Item.equals_insensitive(Search)) {
assert(!Item.equals(Search) && "This should be handled earlier on.");
MaxEditDistance = 1;
Res = Item;
@@ -40,7 +40,7 @@
auto NoPrefix = Item;
if (!NoPrefix.consume_front(DropPrefix))
continue;
- if (NoPrefix.equals_lower(Search)) {
+ if (NoPrefix.equals_insensitive(Search)) {
if (NoPrefix.equals(Search))
return Item.str();
MaxEditDistance = 1;
diff --git a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.h b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.h
index 690b521..783fb20 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -93,7 +93,7 @@
}
static ArgKind getKind() {
- return ArgKind(ASTNodeKind::getFromNodeKind<T>());
+ return ArgKind::MakeMatcherArg(ASTNodeKind::getFromNodeKind<T>());
}
static llvm::Optional<std::string> getBestGuess(const VariantValue &) {
@@ -309,6 +309,16 @@
ArrayRef<ParserValue> Args,
Diagnostics *Error) const = 0;
+ virtual ASTNodeKind nodeMatcherType() const { return ASTNodeKind(); }
+
+ virtual bool isBuilderMatcher() const { return false; }
+
+ virtual std::unique_ptr<MatcherDescriptor>
+ buildMatcherCtor(SourceRange NameRange, ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ return {};
+ }
+
/// Returns whether the matcher is variadic. Variadic matchers can take any
/// number of arguments, but they must be of the same type.
virtual bool isVariadic() const = 0;
@@ -343,7 +353,8 @@
ASTNodeKind Kind, unsigned *Specificity,
ASTNodeKind *LeastDerivedKind) {
for (const ASTNodeKind &NodeKind : RetKinds) {
- if (ArgKind(NodeKind).isConvertibleTo(Kind, Specificity)) {
+ if (ArgKind::MakeMatcherArg(NodeKind).isConvertibleTo(
+ ArgKind::MakeMatcherArg(Kind), Specificity)) {
if (LeastDerivedKind)
*LeastDerivedKind = NodeKind;
return true;
@@ -481,9 +492,11 @@
VariantMatcher
variadicMatcherDescriptor(StringRef MatcherName, SourceRange NameRange,
ArrayRef<ParserValue> Args, Diagnostics *Error) {
- ArgT **InnerArgs = new ArgT *[Args.size()]();
+ SmallVector<ArgT *, 8> InnerArgsPtr;
+ InnerArgsPtr.resize_for_overwrite(Args.size());
+ SmallVector<ArgT, 8> InnerArgs;
+ InnerArgs.reserve(Args.size());
- bool HasError = false;
for (size_t i = 0, e = Args.size(); i != e; ++i) {
using ArgTraits = ArgTypeTraits<ArgT>;
@@ -492,8 +505,7 @@
if (!ArgTraits::hasCorrectType(Value)) {
Error->addError(Arg.Range, Error->ET_RegistryWrongArgType)
<< (i + 1) << ArgTraits::getKind().asString() << Value.getTypeAsString();
- HasError = true;
- break;
+ return {};
}
if (!ArgTraits::hasCorrectValue(Value)) {
if (llvm::Optional<std::string> BestGuess =
@@ -510,24 +522,12 @@
<< (i + 1) << ArgTraits::getKind().asString()
<< Value.getTypeAsString();
}
- HasError = true;
- break;
+ return {};
}
-
- InnerArgs[i] = new ArgT(ArgTraits::get(Value));
+ InnerArgs.set_size(i + 1);
+ InnerArgsPtr[i] = new (&InnerArgs[i]) ArgT(ArgTraits::get(Value));
}
-
- VariantMatcher Out;
- if (!HasError) {
- Out = outvalueToVariantMatcher(Func(llvm::makeArrayRef(InnerArgs,
- Args.size())));
- }
-
- for (size_t i = 0, e = Args.size(); i != e; ++i) {
- delete InnerArgs[i];
- }
- delete[] InnerArgs;
- return Out;
+ return outvalueToVariantMatcher(Func(InnerArgsPtr));
}
/// Matcher descriptor for variadic functions.
@@ -575,6 +575,8 @@
LeastDerivedKind);
}
+ ASTNodeKind nodeMatcherType() const override { return RetKinds[0]; }
+
private:
const RunFunc Func;
const std::string MatcherName;
@@ -610,6 +612,8 @@
}
}
+ ASTNodeKind nodeMatcherType() const override { return DerivedKind; }
+
private:
const ASTNodeKind DerivedKind;
};
@@ -904,7 +908,7 @@
void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo,
std::vector<ArgKind> &Kinds) const override {
- Kinds.push_back(ThisKind);
+ Kinds.push_back(ArgKind::MakeMatcherArg(ThisKind));
}
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity,
@@ -976,7 +980,7 @@
void getArgKinds(ASTNodeKind ThisKind, unsigned,
std::vector<ArgKind> &Kinds) const override {
- Kinds.push_back(ThisKind);
+ Kinds.push_back(ArgKind::MakeMatcherArg(ThisKind));
}
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity,
@@ -989,6 +993,62 @@
}
};
+class MapAnyOfBuilderDescriptor : public MatcherDescriptor {
+public:
+ VariantMatcher create(SourceRange, ArrayRef<ParserValue>,
+ Diagnostics *) const override {
+ return {};
+ }
+
+ bool isBuilderMatcher() const override { return true; }
+
+ std::unique_ptr<MatcherDescriptor>
+ buildMatcherCtor(SourceRange, ArrayRef<ParserValue> Args,
+ Diagnostics *) const override {
+
+ std::vector<ASTNodeKind> NodeKinds;
+ for (auto Arg : Args) {
+ if (!Arg.Value.isNodeKind())
+ return {};
+ NodeKinds.push_back(Arg.Value.getNodeKind());
+ }
+
+ if (NodeKinds.empty())
+ return {};
+
+ ASTNodeKind CladeNodeKind = NodeKinds.front().getCladeKind();
+
+ for (auto NK : NodeKinds)
+ {
+ if (!NK.getCladeKind().isSame(CladeNodeKind))
+ return {};
+ }
+
+ return std::make_unique<MapAnyOfMatcherDescriptor>(CladeNodeKind,
+ NodeKinds);
+ }
+
+ bool isVariadic() const override { return true; }
+
+ unsigned getNumArgs() const override { return 0; }
+
+ void getArgKinds(ASTNodeKind ThisKind, unsigned,
+ std::vector<ArgKind> &ArgKinds) const override {
+ ArgKinds.push_back(ArgKind::MakeNodeArg(ThisKind));
+ return;
+ }
+ bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity = nullptr,
+ ASTNodeKind *LeastDerivedKind = nullptr) const override {
+ if (Specificity)
+ *Specificity = 1;
+ if (LeastDerivedKind)
+ *LeastDerivedKind = Kind;
+ return true;
+ }
+
+ bool isPolymorphic() const override { return false; }
+};
+
/// Helper functions to select the appropriate marshaller functions.
/// They detect the number of arguments, arguments types and return type.
diff --git a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Parser.cpp
index a003754..c6a77bb 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -52,6 +52,7 @@
/// Some known identifiers.
static const char* const ID_Bind;
+ static const char *const ID_With;
TokenInfo() = default;
@@ -62,6 +63,7 @@
};
const char* const Parser::TokenInfo::ID_Bind = "bind";
+const char *const Parser::TokenInfo::ID_With = "with";
/// Simple tokenizer for the parser.
class Parser::CodeTokenizer {
@@ -366,6 +368,29 @@
}
std::string BindID;
+ Tokenizer->consumeNextToken();
+ TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
+ if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
+ addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
+ return false;
+ }
+
+ if (ChainCallToken.Kind != TokenInfo::TK_Ident ||
+ (ChainCallToken.Text != TokenInfo::ID_Bind &&
+ ChainCallToken.Text != TokenInfo::ID_With)) {
+ Error->addError(ChainCallToken.Range,
+ Error->ET_ParserMalformedChainedExpr);
+ return false;
+ }
+ if (ChainCallToken.Text == TokenInfo::ID_With) {
+
+ Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
+ NameToken.Text, NameToken.Range);
+
+ Error->addError(ChainCallToken.Range,
+ Error->ET_RegistryMatcherNoWithSupport);
+ return false;
+ }
if (!parseBindID(BindID))
return false;
@@ -405,31 +430,28 @@
Tokenizer->SkipNewlines();
- // Parse as a matcher expression.
- return parseMatcherExpressionImpl(NameToken, Value);
-}
-
-bool Parser::parseBindID(std::string &BindID) {
- // Parse .bind("foo")
- assert(Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period);
- Tokenizer->consumeNextToken(); // consume the period.
- const TokenInfo BindToken = Tokenizer->consumeNextToken();
- if (BindToken.Kind == TokenInfo::TK_CodeCompletion) {
- addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1));
+ assert(NameToken.Kind == TokenInfo::TK_Ident);
+ TokenInfo OpenToken = Tokenizer->consumeNextToken();
+ if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
+ Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
+ << OpenToken.Text;
return false;
}
+ llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
+
+ // Parse as a matcher expression.
+ return parseMatcherExpressionImpl(NameToken, OpenToken, Ctor, Value);
+}
+
+bool Parser::parseBindID(std::string &BindID) {
+ // Parse the parenthesized argument to .bind("foo")
const TokenInfo OpenToken = Tokenizer->consumeNextToken();
const TokenInfo IDToken = Tokenizer->consumeNextTokenIgnoreNewlines();
const TokenInfo CloseToken = Tokenizer->consumeNextTokenIgnoreNewlines();
// TODO: We could use different error codes for each/some to be more
// explicit about the syntax error.
- if (BindToken.Kind != TokenInfo::TK_Ident ||
- BindToken.Text != TokenInfo::ID_Bind) {
- Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
- return false;
- }
if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
return false;
@@ -446,28 +468,177 @@
return true;
}
+bool Parser::parseMatcherBuilder(MatcherCtor Ctor, const TokenInfo &NameToken,
+ const TokenInfo &OpenToken,
+ VariantValue *Value) {
+ std::vector<ParserValue> Args;
+ TokenInfo EndToken;
+
+ Tokenizer->SkipNewlines();
+
+ {
+ ScopedContextEntry SCE(this, Ctor);
+
+ while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
+ if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
+ // End of args.
+ EndToken = Tokenizer->consumeNextToken();
+ break;
+ }
+ if (!Args.empty()) {
+ // We must find a , token to continue.
+ TokenInfo CommaToken = Tokenizer->consumeNextToken();
+ if (CommaToken.Kind != TokenInfo::TK_Comma) {
+ Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
+ << CommaToken.Text;
+ return false;
+ }
+ }
+
+ Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
+ NameToken.Text, NameToken.Range,
+ Args.size() + 1);
+ ParserValue ArgValue;
+ Tokenizer->SkipNewlines();
+
+ if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_CodeCompletion) {
+ addExpressionCompletions();
+ return false;
+ }
+
+ TokenInfo NodeMatcherToken = Tokenizer->consumeNextToken();
+
+ if (NodeMatcherToken.Kind != TokenInfo::TK_Ident) {
+ Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher)
+ << NameToken.Text;
+ return false;
+ }
+
+ ArgValue.Text = NodeMatcherToken.Text;
+ ArgValue.Range = NodeMatcherToken.Range;
+
+ llvm::Optional<MatcherCtor> MappedMatcher =
+ S->lookupMatcherCtor(ArgValue.Text);
+
+ if (!MappedMatcher) {
+ Error->addError(NodeMatcherToken.Range,
+ Error->ET_RegistryMatcherNotFound)
+ << NodeMatcherToken.Text;
+ return false;
+ }
+
+ ASTNodeKind NK = S->nodeMatcherType(*MappedMatcher);
+
+ if (NK.isNone()) {
+ Error->addError(NodeMatcherToken.Range,
+ Error->ET_RegistryNonNodeMatcher)
+ << NodeMatcherToken.Text;
+ return false;
+ }
+
+ ArgValue.Value = NK;
+
+ Tokenizer->SkipNewlines();
+ Args.push_back(ArgValue);
+
+ SCE.nextArg();
+ }
+ }
+
+ if (EndToken.Kind == TokenInfo::TK_Eof) {
+ Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
+ return false;
+ }
+
+ internal::MatcherDescriptorPtr BuiltCtor =
+ S->buildMatcherCtor(Ctor, NameToken.Range, Args, Error);
+
+ if (!BuiltCtor.get()) {
+ Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher)
+ << NameToken.Text;
+ return false;
+ }
+
+ std::string BindID;
+ if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
+ Tokenizer->consumeNextToken();
+ TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
+ if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
+ addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
+ addCompletion(ChainCallToken, MatcherCompletion("with(", "with", 1));
+ return false;
+ }
+ if (ChainCallToken.Kind != TokenInfo::TK_Ident ||
+ (ChainCallToken.Text != TokenInfo::ID_Bind &&
+ ChainCallToken.Text != TokenInfo::ID_With)) {
+ Error->addError(ChainCallToken.Range,
+ Error->ET_ParserMalformedChainedExpr);
+ return false;
+ }
+ if (ChainCallToken.Text == TokenInfo::ID_Bind) {
+ if (!parseBindID(BindID))
+ return false;
+ Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
+ NameToken.Text, NameToken.Range);
+ SourceRange MatcherRange = NameToken.Range;
+ MatcherRange.End = ChainCallToken.Range.End;
+ VariantMatcher Result = S->actOnMatcherExpression(
+ BuiltCtor.get(), MatcherRange, BindID, {}, Error);
+ if (Result.isNull())
+ return false;
+
+ *Value = Result;
+ return true;
+ } else if (ChainCallToken.Text == TokenInfo::ID_With) {
+ Tokenizer->SkipNewlines();
+
+ if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
+ StringRef ErrTxt = Tokenizer->nextTokenKind() == TokenInfo::TK_Eof
+ ? StringRef("EOF")
+ : Tokenizer->peekNextToken().Text;
+ Error->addError(Tokenizer->peekNextToken().Range,
+ Error->ET_ParserNoOpenParen)
+ << ErrTxt;
+ return false;
+ }
+
+ TokenInfo WithOpenToken = Tokenizer->consumeNextToken();
+
+ return parseMatcherExpressionImpl(NameToken, WithOpenToken,
+ BuiltCtor.get(), Value);
+ }
+ }
+
+ Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
+ NameToken.Text, NameToken.Range);
+ SourceRange MatcherRange = NameToken.Range;
+ MatcherRange.End = EndToken.Range.End;
+ VariantMatcher Result = S->actOnMatcherExpression(
+ BuiltCtor.get(), MatcherRange, BindID, {}, Error);
+ if (Result.isNull())
+ return false;
+
+ *Value = Result;
+ return true;
+}
+
/// Parse and validate a matcher expression.
/// \return \c true on success, in which case \c Value has the matcher parsed.
/// If the input is malformed, or some argument has an error, it
/// returns \c false.
bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
+ const TokenInfo &OpenToken,
+ llvm::Optional<MatcherCtor> Ctor,
VariantValue *Value) {
- assert(NameToken.Kind == TokenInfo::TK_Ident);
- const TokenInfo OpenToken = Tokenizer->consumeNextToken();
- if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
- Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
- << OpenToken.Text;
- return false;
- }
-
- llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
-
if (!Ctor) {
Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
<< NameToken.Text;
// Do not return here. We need to continue to give completion suggestions.
}
+ if (Ctor && *Ctor && S->isBuilderMatcher(*Ctor))
+ return parseMatcherBuilder(*Ctor, NameToken, OpenToken, Value);
+
std::vector<ParserValue> Args;
TokenInfo EndToken;
@@ -516,6 +687,32 @@
std::string BindID;
if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
+ Tokenizer->consumeNextToken();
+ TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
+ if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
+ addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
+ return false;
+ }
+
+ if (ChainCallToken.Kind != TokenInfo::TK_Ident) {
+ Error->addError(ChainCallToken.Range,
+ Error->ET_ParserMalformedChainedExpr);
+ return false;
+ }
+ if (ChainCallToken.Text == TokenInfo::ID_With) {
+
+ Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
+ NameToken.Text, NameToken.Range);
+
+ Error->addError(ChainCallToken.Range,
+ Error->ET_RegistryMatcherNoWithSupport);
+ return false;
+ }
+ if (ChainCallToken.Text != TokenInfo::ID_Bind) {
+ Error->addError(ChainCallToken.Range,
+ Error->ET_ParserMalformedChainedExpr);
+ return false;
+ }
if (!parseBindID(BindID))
return false;
}
@@ -657,6 +854,21 @@
return Registry::getMatcherCompletions(AcceptedTypes);
}
+bool Parser::RegistrySema::isBuilderMatcher(MatcherCtor Ctor) const {
+ return Registry::isBuilderMatcher(Ctor);
+}
+
+ASTNodeKind Parser::RegistrySema::nodeMatcherType(MatcherCtor Ctor) const {
+ return Registry::nodeMatcherType(Ctor);
+}
+
+internal::MatcherDescriptorPtr
+Parser::RegistrySema::buildMatcherCtor(MatcherCtor Ctor, SourceRange NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) const {
+ return Registry::buildMatcherCtor(Ctor, NameRange, Args, Error);
+}
+
bool Parser::parseExpression(StringRef &Code, Sema *S,
const NamedValueMap *NamedValues,
VariantValue *Value, Diagnostics *Error) {
diff --git a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 00a7c74..0048f11 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -102,6 +102,9 @@
// Other:
// equalsNode
+ registerMatcher("mapAnyOf",
+ std::make_unique<internal::MapAnyOfBuilderDescriptor>());
+
REGISTER_OVERLOADED_2(callee);
REGISTER_OVERLOADED_2(hasAnyCapture);
REGISTER_OVERLOADED_2(hasPrefix);
@@ -144,6 +147,7 @@
REGISTER_MATCHER(binaryConditionalOperator);
REGISTER_MATCHER(binaryOperator);
REGISTER_MATCHER(binaryOperation);
+ REGISTER_MATCHER(bindingDecl);
REGISTER_MATCHER(blockDecl);
REGISTER_MATCHER(blockExpr);
REGISTER_MATCHER(blockPointerType);
@@ -162,12 +166,16 @@
REGISTER_MATCHER(complexType);
REGISTER_MATCHER(compoundLiteralExpr);
REGISTER_MATCHER(compoundStmt);
+ REGISTER_MATCHER(coawaitExpr);
REGISTER_MATCHER(conditionalOperator);
REGISTER_MATCHER(constantArrayType);
REGISTER_MATCHER(constantExpr);
REGISTER_MATCHER(containsDeclaration);
REGISTER_MATCHER(continueStmt);
+ REGISTER_MATCHER(coreturnStmt);
+ REGISTER_MATCHER(coyieldExpr);
REGISTER_MATCHER(cudaKernelCallExpr);
+ REGISTER_MATCHER(cxxBaseSpecifier);
REGISTER_MATCHER(cxxBindTemporaryExpr);
REGISTER_MATCHER(cxxBoolLiteral);
REGISTER_MATCHER(cxxCatchStmt);
@@ -210,6 +218,7 @@
REGISTER_MATCHER(decltypeType);
REGISTER_MATCHER(deducedTemplateSpecializationType);
REGISTER_MATCHER(defaultStmt);
+ REGISTER_MATCHER(dependentCoawaitExpr);
REGISTER_MATCHER(dependentSizedArrayType);
REGISTER_MATCHER(designatedInitExpr);
REGISTER_MATCHER(designatorCountIs);
@@ -225,7 +234,10 @@
REGISTER_MATCHER(expr);
REGISTER_MATCHER(exprWithCleanups);
REGISTER_MATCHER(fieldDecl);
+ REGISTER_MATCHER(fixedPointLiteral);
REGISTER_MATCHER(floatLiteral);
+ REGISTER_MATCHER(forCallable);
+ REGISTER_MATCHER(forDecomposition);
REGISTER_MATCHER(forEach);
REGISTER_MATCHER(forEachArgumentWithParam);
REGISTER_MATCHER(forEachArgumentWithParamType);
@@ -248,6 +260,8 @@
REGISTER_MATCHER(hasAncestor);
REGISTER_MATCHER(hasAnyArgument);
REGISTER_MATCHER(hasAnyBase);
+ REGISTER_MATCHER(hasAnyBinding);
+ REGISTER_MATCHER(hasAnyBody);
REGISTER_MATCHER(hasAnyClause);
REGISTER_MATCHER(hasAnyConstructorInitializer);
REGISTER_MATCHER(hasAnyDeclaration);
@@ -266,6 +280,7 @@
REGISTER_MATCHER(hasAttr);
REGISTER_MATCHER(hasAutomaticStorageDuration);
REGISTER_MATCHER(hasBase);
+ REGISTER_MATCHER(hasBinding);
REGISTER_MATCHER(hasBitWidth);
REGISTER_MATCHER(hasBody);
REGISTER_MATCHER(hasCanonicalType);
@@ -358,6 +373,7 @@
REGISTER_MATCHER(injectedClassNameType);
REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
+ REGISTER_MATCHER(invocation);
REGISTER_MATCHER(isAllowedToContainClauseKind);
REGISTER_MATCHER(isAnonymous);
REGISTER_MATCHER(isAnyCharacter);
@@ -518,6 +534,7 @@
REGISTER_MATCHER(tagType);
REGISTER_MATCHER(templateArgument);
REGISTER_MATCHER(templateArgumentCountIs);
+ REGISTER_MATCHER(templateArgumentLoc);
REGISTER_MATCHER(templateName);
REGISTER_MATCHER(templateSpecializationType);
REGISTER_MATCHER(templateTemplateParmDecl);
@@ -544,6 +561,7 @@
REGISTER_MATCHER(userDefinedLiteral);
REGISTER_MATCHER(usesADL);
REGISTER_MATCHER(usingDecl);
+ REGISTER_MATCHER(usingEnumDecl);
REGISTER_MATCHER(usingDirectiveDecl);
REGISTER_MATCHER(valueDecl);
REGISTER_MATCHER(varDecl);
@@ -557,6 +575,26 @@
static llvm::ManagedStatic<RegistryMaps> RegistryData;
+ASTNodeKind Registry::nodeMatcherType(MatcherCtor Ctor) {
+ return Ctor->nodeMatcherType();
+}
+
+internal::MatcherDescriptorPtr::MatcherDescriptorPtr(MatcherDescriptor *Ptr)
+ : Ptr(Ptr) {}
+
+internal::MatcherDescriptorPtr::~MatcherDescriptorPtr() { delete Ptr; }
+
+bool Registry::isBuilderMatcher(MatcherCtor Ctor) {
+ return Ctor->isBuilderMatcher();
+}
+
+internal::MatcherDescriptorPtr
+Registry::buildMatcherCtor(MatcherCtor Ctor, SourceRange NameRange,
+ ArrayRef<ParserValue> Args, Diagnostics *Error) {
+ return internal::MatcherDescriptorPtr(
+ Ctor->buildMatcherCtor(NameRange, Args, Error).release());
+}
+
// static
llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) {
auto it = RegistryData->constructors().find(MatcherName);
@@ -594,7 +632,10 @@
// Starting with the above seed of acceptable top-level matcher types, compute
// the acceptable type set for the argument indicated by each context element.
- std::set<ArgKind> TypeSet(std::begin(InitialTypes), std::end(InitialTypes));
+ std::set<ArgKind> TypeSet;
+ for (auto IT : InitialTypes) {
+ TypeSet.insert(ArgKind::MakeMatcherArg(IT));
+ }
for (const auto &CtxEntry : Context) {
MatcherCtor Ctor = CtxEntry.first;
unsigned ArgNumber = CtxEntry.second;
@@ -625,20 +666,40 @@
bool IsPolymorphic = Matcher.isPolymorphic();
std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
unsigned MaxSpecificity = 0;
+ bool NodeArgs = false;
for (const ArgKind& Kind : AcceptedTypes) {
- if (Kind.getArgKind() != Kind.AK_Matcher)
+ if (Kind.getArgKind() != Kind.AK_Matcher &&
+ Kind.getArgKind() != Kind.AK_Node) {
continue;
- unsigned Specificity;
- ASTNodeKind LeastDerivedKind;
- if (Matcher.isConvertibleTo(Kind.getMatcherKind(), &Specificity,
- &LeastDerivedKind)) {
- if (MaxSpecificity < Specificity)
- MaxSpecificity = Specificity;
- RetKinds.insert(LeastDerivedKind);
- for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
- Matcher.getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
- if (IsPolymorphic)
- break;
+ }
+
+ if (Kind.getArgKind() == Kind.AK_Node) {
+ NodeArgs = true;
+ unsigned Specificity;
+ ASTNodeKind LeastDerivedKind;
+ if (Matcher.isConvertibleTo(Kind.getNodeKind(), &Specificity,
+ &LeastDerivedKind)) {
+ if (MaxSpecificity < Specificity)
+ MaxSpecificity = Specificity;
+ RetKinds.insert(LeastDerivedKind);
+ for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
+ Matcher.getArgKinds(Kind.getNodeKind(), Arg, ArgsKinds[Arg]);
+ if (IsPolymorphic)
+ break;
+ }
+ } else {
+ unsigned Specificity;
+ ASTNodeKind LeastDerivedKind;
+ if (Matcher.isConvertibleTo(Kind.getMatcherKind(), &Specificity,
+ &LeastDerivedKind)) {
+ if (MaxSpecificity < Specificity)
+ MaxSpecificity = Specificity;
+ RetKinds.insert(LeastDerivedKind);
+ for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
+ Matcher.getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
+ if (IsPolymorphic)
+ break;
+ }
}
}
@@ -646,42 +707,49 @@
std::string Decl;
llvm::raw_string_ostream OS(Decl);
- if (IsPolymorphic) {
- OS << "Matcher<T> " << Name << "(Matcher<T>";
- } else {
- OS << "Matcher<" << RetKinds << "> " << Name << "(";
- for (const std::vector<ArgKind> &Arg : ArgsKinds) {
- if (&Arg != &ArgsKinds[0])
- OS << ", ";
+ std::string TypedText = std::string(Name);
- bool FirstArgKind = true;
- std::set<ASTNodeKind> MatcherKinds;
- // Two steps. First all non-matchers, then matchers only.
- for (const ArgKind &AK : Arg) {
- if (AK.getArgKind() == ArgKind::AK_Matcher) {
- MatcherKinds.insert(AK.getMatcherKind());
- } else {
+ if (NodeArgs) {
+ OS << Name;
+ } else {
+
+ if (IsPolymorphic) {
+ OS << "Matcher<T> " << Name << "(Matcher<T>";
+ } else {
+ OS << "Matcher<" << RetKinds << "> " << Name << "(";
+ for (const std::vector<ArgKind> &Arg : ArgsKinds) {
+ if (&Arg != &ArgsKinds[0])
+ OS << ", ";
+
+ bool FirstArgKind = true;
+ std::set<ASTNodeKind> MatcherKinds;
+ // Two steps. First all non-matchers, then matchers only.
+ for (const ArgKind &AK : Arg) {
+ if (AK.getArgKind() == ArgKind::AK_Matcher) {
+ MatcherKinds.insert(AK.getMatcherKind());
+ } else {
+ if (!FirstArgKind)
+ OS << "|";
+ FirstArgKind = false;
+ OS << AK.asString();
+ }
+ }
+ if (!MatcherKinds.empty()) {
if (!FirstArgKind) OS << "|";
- FirstArgKind = false;
- OS << AK.asString();
+ OS << "Matcher<" << MatcherKinds << ">";
}
}
- if (!MatcherKinds.empty()) {
- if (!FirstArgKind) OS << "|";
- OS << "Matcher<" << MatcherKinds << ">";
- }
}
- }
- if (Matcher.isVariadic())
- OS << "...";
- OS << ")";
+ if (Matcher.isVariadic())
+ OS << "...";
+ OS << ")";
- std::string TypedText = std::string(Name);
- TypedText += "(";
- if (ArgsKinds.empty())
- TypedText += ")";
- else if (ArgsKinds[0][0].getArgKind() == ArgKind::AK_String)
- TypedText += "\"";
+ TypedText += "(";
+ if (ArgsKinds.empty())
+ TypedText += ")";
+ else if (ArgsKinds[0][0].getArgKind() == ArgKind::AK_String)
+ TypedText += "\"";
+ }
Completions.emplace_back(TypedText, OS.str(), MaxSpecificity);
}
diff --git a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
index d1ecb1e..813eb15 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
+++ b/src/llvm-project/clang/lib/ASTMatchers/Dynamic/VariantValue.cpp
@@ -22,7 +22,9 @@
std::string ArgKind::asString() const {
switch (getArgKind()) {
case AK_Matcher:
- return (Twine("Matcher<") + MatcherKind.asStringRef() + ">").str();
+ return (Twine("Matcher<") + NodeKind.asStringRef() + ">").str();
+ case AK_Node:
+ return NodeKind.asStringRef().str();
case AK_Boolean:
return "boolean";
case AK_Double:
@@ -38,13 +40,13 @@
bool ArgKind::isConvertibleTo(ArgKind To, unsigned *Specificity) const {
if (K != To.K)
return false;
- if (K != AK_Matcher) {
+ if (K != AK_Matcher && K != AK_Node) {
if (Specificity)
*Specificity = 1;
return true;
}
unsigned Distance;
- if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance))
+ if (!NodeKind.isBaseOf(To.NodeKind, &Distance))
return false;
if (Specificity)
@@ -107,8 +109,8 @@
}
bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity) const override {
- return ArgKind(Matcher.getSupportedKind())
- .isConvertibleTo(Kind, Specificity);
+ return ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
+ .isConvertibleTo(ArgKind::MakeMatcherArg(Kind), Specificity);
}
private:
@@ -167,8 +169,9 @@
unsigned MaxSpecificity = 0;
for (const DynTypedMatcher &Matcher : Matchers) {
unsigned ThisSpecificity;
- if (ArgKind(Matcher.getSupportedKind())
- .isConvertibleTo(Kind, &ThisSpecificity)) {
+ if (ArgKind::MakeMatcherArg(Matcher.getSupportedKind())
+ .isConvertibleTo(ArgKind::MakeMatcherArg(Kind),
+ &ThisSpecificity)) {
MaxSpecificity = std::max(MaxSpecificity, ThisSpecificity);
}
}
@@ -442,6 +445,11 @@
*Specificity = 1;
return true;
+ case ArgKind::AK_Node:
+ if (!isNodeKind())
+ return false;
+ return getMatcher().isConvertibleTo(Kind.getNodeKind(), Specificity);
+
case ArgKind::AK_Matcher:
if (!isMatcher())
return false;
diff --git a/src/llvm-project/clang/lib/ASTMatchers/GtestMatchers.cpp b/src/llvm-project/clang/lib/ASTMatchers/GtestMatchers.cpp
index 0e587c0..6e4c12f 100644
--- a/src/llvm-project/clang/lib/ASTMatchers/GtestMatchers.cpp
+++ b/src/llvm-project/clang/lib/ASTMatchers/GtestMatchers.cpp
@@ -5,76 +5,109 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+//
+// This file implements several matchers for popular gtest macros. In general,
+// AST matchers cannot match calls to macros. However, we can simulate such
+// matches if the macro definition has identifiable elements that themselves can
+// be matched. In that case, we can match on those elements and then check that
+// the match occurs within an expansion of the desired macro. The more uncommon
+// the identified elements, the more efficient this process will be.
+//
+//===----------------------------------------------------------------------===//
#include "clang/ASTMatchers/GtestMatchers.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/Timer.h"
-#include <deque>
-#include <memory>
-#include <set>
+#include "llvm/ADT/StringRef.h"
namespace clang {
namespace ast_matchers {
+namespace {
+
+enum class MacroType {
+ Expect,
+ Assert,
+ On,
+};
+
+} // namespace
static DeclarationMatcher getComparisonDecl(GtestCmp Cmp) {
switch (Cmp) {
- case GtestCmp::Eq:
- return cxxMethodDecl(hasName("Compare"),
- ofClass(cxxRecordDecl(isSameOrDerivedFrom(
- hasName("::testing::internal::EqHelper")))));
- case GtestCmp::Ne:
- return functionDecl(hasName("::testing::internal::CmpHelperNE"));
- case GtestCmp::Ge:
- return functionDecl(hasName("::testing::internal::CmpHelperGE"));
- case GtestCmp::Gt:
- return functionDecl(hasName("::testing::internal::CmpHelperGT"));
- case GtestCmp::Le:
- return functionDecl(hasName("::testing::internal::CmpHelperLE"));
- case GtestCmp::Lt:
- return functionDecl(hasName("::testing::internal::CmpHelperLT"));
+ case GtestCmp::Eq:
+ return cxxMethodDecl(hasName("Compare"),
+ ofClass(cxxRecordDecl(isSameOrDerivedFrom(
+ hasName("::testing::internal::EqHelper")))));
+ case GtestCmp::Ne:
+ return functionDecl(hasName("::testing::internal::CmpHelperNE"));
+ case GtestCmp::Ge:
+ return functionDecl(hasName("::testing::internal::CmpHelperGE"));
+ case GtestCmp::Gt:
+ return functionDecl(hasName("::testing::internal::CmpHelperGT"));
+ case GtestCmp::Le:
+ return functionDecl(hasName("::testing::internal::CmpHelperLE"));
+ case GtestCmp::Lt:
+ return functionDecl(hasName("::testing::internal::CmpHelperLT"));
}
llvm_unreachable("Unhandled GtestCmp enum");
}
-static llvm::StringRef getAssertMacro(GtestCmp Cmp) {
+static llvm::StringRef getMacroTypeName(MacroType Macro) {
+ switch (Macro) {
+ case MacroType::Expect:
+ return "EXPECT";
+ case MacroType::Assert:
+ return "ASSERT";
+ case MacroType::On:
+ return "ON";
+ }
+ llvm_unreachable("Unhandled MacroType enum");
+}
+
+static llvm::StringRef getComparisonTypeName(GtestCmp Cmp) {
switch (Cmp) {
- case GtestCmp::Eq:
- return "ASSERT_EQ";
- case GtestCmp::Ne:
- return "ASSERT_NE";
- case GtestCmp::Ge:
- return "ASSERT_GE";
- case GtestCmp::Gt:
- return "ASSERT_GT";
- case GtestCmp::Le:
- return "ASSERT_LE";
- case GtestCmp::Lt:
- return "ASSERT_LT";
+ case GtestCmp::Eq:
+ return "EQ";
+ case GtestCmp::Ne:
+ return "NE";
+ case GtestCmp::Ge:
+ return "GE";
+ case GtestCmp::Gt:
+ return "GT";
+ case GtestCmp::Le:
+ return "LE";
+ case GtestCmp::Lt:
+ return "LT";
}
llvm_unreachable("Unhandled GtestCmp enum");
}
-static llvm::StringRef getExpectMacro(GtestCmp Cmp) {
- switch (Cmp) {
- case GtestCmp::Eq:
- return "EXPECT_EQ";
- case GtestCmp::Ne:
- return "EXPECT_NE";
- case GtestCmp::Ge:
- return "EXPECT_GE";
- case GtestCmp::Gt:
- return "EXPECT_GT";
- case GtestCmp::Le:
- return "EXPECT_LE";
- case GtestCmp::Lt:
- return "EXPECT_LT";
+static std::string getMacroName(MacroType Macro, GtestCmp Cmp) {
+ return (getMacroTypeName(Macro) + "_" + getComparisonTypeName(Cmp)).str();
+}
+
+static std::string getMacroName(MacroType Macro, llvm::StringRef Operation) {
+ return (getMacroTypeName(Macro) + "_" + Operation).str();
+}
+
+// Under the hood, ON_CALL is expanded to a call to `InternalDefaultActionSetAt`
+// to set a default action spec to the underlying function mocker, while
+// EXPECT_CALL is expanded to a call to `InternalExpectedAt` to set a new
+// expectation spec.
+static llvm::StringRef getSpecSetterName(MacroType Macro) {
+ switch (Macro) {
+ case MacroType::On:
+ return "InternalDefaultActionSetAt";
+ case MacroType::Expect:
+ return "InternalExpectedAt";
+ default:
+ llvm_unreachable("Unhandled MacroType enum");
}
- llvm_unreachable("Unhandled GtestCmp enum");
+ llvm_unreachable("Unhandled MacroType enum");
}
// In general, AST matchers cannot match calls to macros. However, we can
@@ -86,18 +119,115 @@
//
// We use this approach to implement the derived matchers gtestAssert and
// gtestExpect.
+static internal::BindableMatcher<Stmt>
+gtestComparisonInternal(MacroType Macro, GtestCmp Cmp, StatementMatcher Left,
+ StatementMatcher Right) {
+ return callExpr(isExpandedFromMacro(getMacroName(Macro, Cmp)),
+ callee(getComparisonDecl(Cmp)), hasArgument(2, Left),
+ hasArgument(3, Right));
+}
+
+static internal::BindableMatcher<Stmt>
+gtestThatInternal(MacroType Macro, StatementMatcher Actual,
+ StatementMatcher Matcher) {
+ return cxxOperatorCallExpr(
+ isExpandedFromMacro(getMacroName(Macro, "THAT")),
+ hasOverloadedOperatorName("()"), hasArgument(2, Actual),
+ hasArgument(
+ 0, expr(hasType(classTemplateSpecializationDecl(hasName(
+ "::testing::internal::PredicateFormatterFromMatcher"))),
+ ignoringImplicit(
+ callExpr(callee(functionDecl(hasName(
+ "::testing::internal::"
+ "MakePredicateFormatterFromMatcher"))),
+ hasArgument(0, ignoringImplicit(Matcher)))))));
+}
+
+static internal::BindableMatcher<Stmt>
+gtestCallInternal(MacroType Macro, StatementMatcher MockCall, MockArgs Args) {
+ // A ON_CALL or EXPECT_CALL macro expands to different AST structures
+ // depending on whether the mock method has arguments or not.
+ switch (Args) {
+ // For example,
+ // `ON_CALL(mock, TwoParamMethod)` is expanded to
+ // `mock.gmock_TwoArgsMethod(WithoutMatchers(),
+ // nullptr).InternalDefaultActionSetAt(...)`.
+ // EXPECT_CALL is the same except
+ // that it calls `InternalExpectedAt` instead of `InternalDefaultActionSetAt`
+ // in the end.
+ case MockArgs::None:
+ return cxxMemberCallExpr(
+ isExpandedFromMacro(getMacroName(Macro, "CALL")),
+ callee(functionDecl(hasName(getSpecSetterName(Macro)))),
+ onImplicitObjectArgument(ignoringImplicit(MockCall)));
+ // For example,
+ // `ON_CALL(mock, TwoParamMethod(m1, m2))` is expanded to
+ // `mock.gmock_TwoParamMethod(m1,m2)(WithoutMatchers(),
+ // nullptr).InternalDefaultActionSetAt(...)`.
+ // EXPECT_CALL is the same except that it calls `InternalExpectedAt` instead
+ // of `InternalDefaultActionSetAt` in the end.
+ case MockArgs::Some:
+ return cxxMemberCallExpr(
+ isExpandedFromMacro(getMacroName(Macro, "CALL")),
+ callee(functionDecl(hasName(getSpecSetterName(Macro)))),
+ onImplicitObjectArgument(ignoringImplicit(cxxOperatorCallExpr(
+ hasOverloadedOperatorName("()"), argumentCountIs(3),
+ hasArgument(0, ignoringImplicit(MockCall))))));
+ }
+ llvm_unreachable("Unhandled MockArgs enum");
+}
+
+static internal::BindableMatcher<Stmt>
+gtestCallInternal(MacroType Macro, StatementMatcher MockObject,
+ llvm::StringRef MockMethodName, MockArgs Args) {
+ return gtestCallInternal(
+ Macro,
+ cxxMemberCallExpr(
+ onImplicitObjectArgument(MockObject),
+ callee(functionDecl(hasName(("gmock_" + MockMethodName).str())))),
+ Args);
+}
+
internal::BindableMatcher<Stmt> gtestAssert(GtestCmp Cmp, StatementMatcher Left,
StatementMatcher Right) {
- return callExpr(callee(getComparisonDecl(Cmp)),
- isExpandedFromMacro(getAssertMacro(Cmp).str()),
- hasArgument(2, Left), hasArgument(3, Right));
+ return gtestComparisonInternal(MacroType::Assert, Cmp, Left, Right);
}
internal::BindableMatcher<Stmt> gtestExpect(GtestCmp Cmp, StatementMatcher Left,
StatementMatcher Right) {
- return callExpr(callee(getComparisonDecl(Cmp)),
- isExpandedFromMacro(getExpectMacro(Cmp).str()),
- hasArgument(2, Left), hasArgument(3, Right));
+ return gtestComparisonInternal(MacroType::Expect, Cmp, Left, Right);
+}
+
+internal::BindableMatcher<Stmt> gtestAssertThat(StatementMatcher Actual,
+ StatementMatcher Matcher) {
+ return gtestThatInternal(MacroType::Assert, Actual, Matcher);
+}
+
+internal::BindableMatcher<Stmt> gtestExpectThat(StatementMatcher Actual,
+ StatementMatcher Matcher) {
+ return gtestThatInternal(MacroType::Expect, Actual, Matcher);
+}
+
+internal::BindableMatcher<Stmt> gtestOnCall(StatementMatcher MockObject,
+ llvm::StringRef MockMethodName,
+ MockArgs Args) {
+ return gtestCallInternal(MacroType::On, MockObject, MockMethodName, Args);
+}
+
+internal::BindableMatcher<Stmt> gtestOnCall(StatementMatcher MockCall,
+ MockArgs Args) {
+ return gtestCallInternal(MacroType::On, MockCall, Args);
+}
+
+internal::BindableMatcher<Stmt> gtestExpectCall(StatementMatcher MockObject,
+ llvm::StringRef MockMethodName,
+ MockArgs Args) {
+ return gtestCallInternal(MacroType::Expect, MockObject, MockMethodName, Args);
+}
+
+internal::BindableMatcher<Stmt> gtestExpectCall(StatementMatcher MockCall,
+ MockArgs Args) {
+ return gtestCallInternal(MacroType::Expect, MockCall, Args);
}
} // end namespace ast_matchers
diff --git a/src/llvm-project/clang/lib/Analysis/AnalysisDeclContext.cpp b/src/llvm-project/clang/lib/Analysis/AnalysisDeclContext.cpp
index 783de64..d8466ac 100644
--- a/src/llvm-project/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/src/llvm-project/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -337,6 +337,59 @@
return ND->isStdNamespace();
}
+std::string AnalysisDeclContext::getFunctionName(const Decl *D) {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ const ASTContext &Ctx = D->getASTContext();
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ OS << FD->getQualifiedNameAsString();
+
+ // In C++, there are overloads.
+
+ if (Ctx.getLangOpts().CPlusPlus) {
+ OS << '(';
+ for (const auto &P : FD->parameters()) {
+ if (P != *FD->param_begin())
+ OS << ", ";
+ OS << P->getType().getAsString();
+ }
+ OS << ')';
+ }
+
+ } else if (isa<BlockDecl>(D)) {
+ PresumedLoc Loc = Ctx.getSourceManager().getPresumedLoc(D->getLocation());
+
+ if (Loc.isValid()) {
+ OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
+ << ')';
+ }
+
+ } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
+
+ // FIXME: copy-pasted from CGDebugInfo.cpp.
+ OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
+ const DeclContext *DC = OMD->getDeclContext();
+ if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
+ if (OC->IsClassExtension()) {
+ OS << OC->getClassInterface()->getName();
+ } else {
+ OS << OC->getIdentifier()->getNameStart() << '('
+ << OC->getIdentifier()->getNameStart() << ')';
+ }
+ } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
+ OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
+ }
+ OS << ' ' << OMD->getSelector().getAsString() << ']';
+ }
+
+ return OS.str();
+}
+
LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
assert(
ADCMgr &&
@@ -456,7 +509,7 @@
Out << "\t#" << Frame << ' ';
++Frame;
if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
- Out << "Calling " << D->getQualifiedNameAsString();
+ Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
else
Out << "Calling anonymous code";
if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
diff --git a/src/llvm-project/clang/lib/Analysis/BodyFarm.cpp b/src/llvm-project/clang/lib/Analysis/BodyFarm.cpp
index 603da67..e357bfb 100644
--- a/src/llvm-project/clang/lib/Analysis/BodyFarm.cpp
+++ b/src/llvm-project/clang/lib/Analysis/BodyFarm.cpp
@@ -116,7 +116,7 @@
QualType Ty) {
return BinaryOperator::Create(
C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), BO_Assign, Ty,
- VK_RValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
+ VK_PRValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
}
BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
@@ -125,7 +125,7 @@
BinaryOperator::isComparisonOp(Op));
return BinaryOperator::Create(
C, const_cast<Expr *>(LHS), const_cast<Expr *>(RHS), Op,
- C.getLogicalOperationType(), VK_RValue, OK_Ordinary, SourceLocation(),
+ C.getLogicalOperationType(), VK_PRValue, OK_Ordinary, SourceLocation(),
FPOptionsOverride());
}
@@ -169,7 +169,7 @@
/* CastKind=*/CK,
/* Expr=*/const_cast<Expr *>(Arg),
/* CXXCastPath=*/nullptr,
- /* ExprValueKind=*/VK_RValue,
+ /* ExprValueKind=*/VK_PRValue,
/* FPFeatures */ FPOptionsOverride());
}
@@ -264,7 +264,7 @@
llvm_unreachable("Unexpected state");
}
- return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue,
+ return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_PRValue,
SourceLocation(), FPOptionsOverride());
}
@@ -291,7 +291,7 @@
/*AstContext=*/C, OO_Call, callOperatorDeclRef,
/*Args=*/CallArgs,
/*QualType=*/C.VoidTy,
- /*ExprValueType=*/VK_RValue,
+ /*ExprValueType=*/VK_PRValue,
/*SourceLocation=*/SourceLocation(),
/*FPFeatures=*/FPOptionsOverride());
}
@@ -451,7 +451,7 @@
CK_IntegralToBoolean),
/* opc=*/UO_LNot,
/* QualType=*/C.IntTy,
- /* ExprValueKind=*/VK_RValue,
+ /* ExprValueKind=*/VK_PRValue,
/* ExprObjectKind=*/OK_Ordinary, SourceLocation(),
/* CanOverflow*/ false, FPOptionsOverride());
@@ -513,13 +513,13 @@
/*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
/*Args=*/None,
/*QualType=*/C.VoidTy,
- /*ExprValueType=*/VK_RValue,
+ /*ExprValueType=*/VK_PRValue,
/*SourceLocation=*/SourceLocation(), FPOptionsOverride());
// (2) Create the assignment to the predicate.
Expr *DoneValue =
UnaryOperator::Create(C, M.makeIntegerLiteral(0, C.LongTy), UO_Not,
- C.LongTy, VK_RValue, OK_Ordinary, SourceLocation(),
+ C.LongTy, VK_PRValue, OK_Ordinary, SourceLocation(),
/*CanOverflow*/ false, FPOptionsOverride());
BinaryOperator *B =
@@ -580,7 +580,7 @@
ASTMaker M(C);
DeclRefExpr *DR = M.makeDeclRefExpr(PV);
ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
- CallExpr *CE = CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue,
+ CallExpr *CE = CallExpr::Create(C, ICE, None, C.VoidTy, VK_PRValue,
SourceLocation(), FPOptionsOverride());
return CE;
}
@@ -742,8 +742,9 @@
static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
const ObjCMethodDecl *MD) {
- // First, find the backing ivar.
+ // First, find the backing ivar.
const ObjCIvarDecl *IVar = nullptr;
+ const ObjCPropertyDecl *Prop = nullptr;
// Property accessor stubs sometimes do not correspond to any property decl
// in the current interface (but in a superclass). They still have a
@@ -751,54 +752,57 @@
if (MD->isSynthesizedAccessorStub()) {
const ObjCInterfaceDecl *IntD = MD->getClassInterface();
const ObjCImplementationDecl *ImpD = IntD->getImplementation();
- for (const auto *PI: ImpD->property_impls()) {
- if (const ObjCPropertyDecl *P = PI->getPropertyDecl()) {
- if (P->getGetterName() == MD->getSelector())
- IVar = P->getPropertyIvarDecl();
+ for (const auto *PI : ImpD->property_impls()) {
+ if (const ObjCPropertyDecl *Candidate = PI->getPropertyDecl()) {
+ if (Candidate->getGetterName() == MD->getSelector()) {
+ Prop = Candidate;
+ IVar = Prop->getPropertyIvarDecl();
+ }
}
}
}
if (!IVar) {
- const ObjCPropertyDecl *Prop = MD->findPropertyDecl();
+ Prop = MD->findPropertyDecl();
IVar = findBackingIvar(Prop);
- if (!IVar)
- return nullptr;
+ }
- // Ignore weak variables, which have special behavior.
- if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
- return nullptr;
+ if (!IVar || !Prop)
+ return nullptr;
- // Look to see if Sema has synthesized a body for us. This happens in
- // Objective-C++ because the return value may be a C++ class type with a
- // non-trivial copy constructor. We can only do this if we can find the
- // @synthesize for this property, though (or if we know it's been auto-
- // synthesized).
- const ObjCImplementationDecl *ImplDecl =
+ // Ignore weak variables, which have special behavior.
+ if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)
+ return nullptr;
+
+ // Look to see if Sema has synthesized a body for us. This happens in
+ // Objective-C++ because the return value may be a C++ class type with a
+ // non-trivial copy constructor. We can only do this if we can find the
+ // @synthesize for this property, though (or if we know it's been auto-
+ // synthesized).
+ const ObjCImplementationDecl *ImplDecl =
IVar->getContainingInterface()->getImplementation();
- if (ImplDecl) {
- for (const auto *I : ImplDecl->property_impls()) {
- if (I->getPropertyDecl() != Prop)
- continue;
+ if (ImplDecl) {
+ for (const auto *I : ImplDecl->property_impls()) {
+ if (I->getPropertyDecl() != Prop)
+ continue;
- if (I->getGetterCXXConstructor()) {
- ASTMaker M(Ctx);
- return M.makeReturn(I->getGetterCXXConstructor());
- }
+ if (I->getGetterCXXConstructor()) {
+ ASTMaker M(Ctx);
+ return M.makeReturn(I->getGetterCXXConstructor());
}
}
-
- // Sanity check that the property is the same type as the ivar, or a
- // reference to it, and that it is either an object pointer or trivially
- // copyable.
- if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
- Prop->getType().getNonReferenceType()))
- return nullptr;
- if (!IVar->getType()->isObjCLifetimeType() &&
- !IVar->getType().isTriviallyCopyableType(Ctx))
- return nullptr;
}
+ // Sanity check that the property is the same type as the ivar, or a
+ // reference to it, and that it is either an object pointer or trivially
+ // copyable.
+ if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
+ Prop->getType().getNonReferenceType()))
+ return nullptr;
+ if (!IVar->getType()->isObjCLifetimeType() &&
+ !IVar->getType().isTriviallyCopyableType(Ctx))
+ return nullptr;
+
// Generate our body:
// return self->_ivar;
ASTMaker M(Ctx);
@@ -807,11 +811,8 @@
if (!selfVar)
return nullptr;
- Expr *loadedIVar =
- M.makeObjCIvarRef(
- M.makeLvalueToRvalue(
- M.makeDeclRefExpr(selfVar),
- selfVar->getType()),
+ Expr *loadedIVar = M.makeObjCIvarRef(
+ M.makeLvalueToRvalue(M.makeDeclRefExpr(selfVar), selfVar->getType()),
IVar);
if (!MD->getReturnType()->isReferenceType())
diff --git a/src/llvm-project/clang/lib/Analysis/CFG.cpp b/src/llvm-project/clang/lib/Analysis/CFG.cpp
index edc86c4..ba5eced 100644
--- a/src/llvm-project/clang/lib/Analysis/CFG.cpp
+++ b/src/llvm-project/clang/lib/Analysis/CFG.cpp
@@ -1456,6 +1456,13 @@
// TODO: Handle other cases. For now, fail to find construction contexts.
break;
}
+ case Stmt::ParenExprClass: {
+ // If expression is placed into parenthesis we should propagate the parent
+ // construction context to subexpressions.
+ auto *PE = cast<ParenExpr>(Child);
+ findConstructionContexts(Layer, PE->getSubExpr());
+ break;
+ }
default:
break;
}
@@ -4475,8 +4482,14 @@
// Add implicit scope and dtors for loop variable.
addLocalScopeAndDtors(S->getLoopVarStmt());
+ // If body is not a compound statement create implicit scope
+ // and add destructors.
+ if (!isa<CompoundStmt>(S->getBody()))
+ addLocalScopeAndDtors(S->getBody());
+
// Populate a new block to contain the loop body and loop variable.
addStmt(S->getBody());
+
if (badCFG)
return nullptr;
CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt());
diff --git a/src/llvm-project/clang/lib/Analysis/CMakeLists.txt b/src/llvm-project/clang/lib/Analysis/CMakeLists.txt
index ed626a6..00c8d67 100644
--- a/src/llvm-project/clang/lib/Analysis/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/Analysis/CMakeLists.txt
@@ -20,6 +20,7 @@
ExprMutationAnalyzer.cpp
IssueHash.cpp
LiveVariables.cpp
+ MacroExpansionContext.cpp
ObjCNoReturn.cpp
PathDiagnostic.cpp
PostOrderCFGView.cpp
diff --git a/src/llvm-project/clang/lib/Analysis/CalledOnceCheck.cpp b/src/llvm-project/clang/lib/Analysis/CalledOnceCheck.cpp
index 883629a..661f7b9 100644
--- a/src/llvm-project/clang/lib/Analysis/CalledOnceCheck.cpp
+++ b/src/llvm-project/clang/lib/Analysis/CalledOnceCheck.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/CalledOnceCheck.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
@@ -22,6 +23,7 @@
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/BitVector.h"
@@ -47,12 +49,29 @@
template <class T>
using CFGSizedVector = llvm::SmallVector<T, EXPECTED_NUMBER_OF_BASIC_BLOCKS>;
constexpr llvm::StringLiteral CONVENTIONAL_NAMES[] = {
- "completionHandler", "completion", "withCompletionHandler"};
+ "completionHandler", "completion", "withCompletionHandler",
+ "withCompletion", "completionBlock", "withCompletionBlock",
+ "replyTo", "reply", "withReplyTo"};
constexpr llvm::StringLiteral CONVENTIONAL_SUFFIXES[] = {
- "WithCompletionHandler", "WithCompletion"};
+ "WithCompletionHandler", "WithCompletion", "WithCompletionBlock",
+ "WithReplyTo", "WithReply"};
constexpr llvm::StringLiteral CONVENTIONAL_CONDITIONS[] = {
"error", "cancel", "shouldCall", "done", "OK", "success"};
+struct KnownCalledOnceParameter {
+ llvm::StringLiteral FunctionName;
+ unsigned ParamIndex;
+};
+constexpr KnownCalledOnceParameter KNOWN_CALLED_ONCE_PARAMETERS[] = {
+ {llvm::StringLiteral{"dispatch_async"}, 1},
+ {llvm::StringLiteral{"dispatch_async_and_wait"}, 1},
+ {llvm::StringLiteral{"dispatch_after"}, 2},
+ {llvm::StringLiteral{"dispatch_sync"}, 1},
+ {llvm::StringLiteral{"dispatch_once"}, 1},
+ {llvm::StringLiteral{"dispatch_barrier_async"}, 1},
+ {llvm::StringLiteral{"dispatch_barrier_async_and_wait"}, 1},
+ {llvm::StringLiteral{"dispatch_barrier_sync"}, 1}};
+
class ParameterStatus {
public:
// Status kind is basically the main part of parameter's status.
@@ -330,6 +349,29 @@
return Visit(OVE->getSourceExpr());
}
+ const DeclRefExpr *VisitCallExpr(const CallExpr *CE) {
+ if (!ShouldRetrieveFromComparisons)
+ return nullptr;
+
+ // We want to see through some of the boolean builtin functions
+ // that we are likely to see in conditions.
+ switch (CE->getBuiltinCallee()) {
+ case Builtin::BI__builtin_expect:
+ case Builtin::BI__builtin_expect_with_probability: {
+ assert(CE->getNumArgs() >= 2);
+
+ const DeclRefExpr *Candidate = Visit(CE->getArg(0));
+ return Candidate != nullptr ? Candidate : Visit(CE->getArg(1));
+ }
+
+ case Builtin::BI__builtin_unpredictable:
+ return Visit(CE->getArg(0));
+
+ default:
+ return nullptr;
+ }
+ }
+
const DeclRefExpr *VisitExpr(const Expr *E) {
// It is a fallback method that gets called whenever the actual type
// of the given expression is not covered.
@@ -436,7 +478,7 @@
return llvm::any_of(
CONVENTIONAL_CONDITIONS,
[ConditionName](const llvm::StringLiteral &Conventional) {
- return ConditionName.contains_lower(Conventional);
+ return ConditionName.contains_insensitive(Conventional);
});
});
}
@@ -770,8 +812,12 @@
}
}
- // Early exit if we don't have parameters for extra analysis.
- if (NotCalledOnEveryPath.none() && NotUsedOnEveryPath.none())
+ // Early exit if we don't have parameters for extra analysis...
+ if (NotCalledOnEveryPath.none() && NotUsedOnEveryPath.none() &&
+ // ... or if we've seen variables with cleanup functions.
+ // We can't reason that we've seen every path in this case,
+ // and thus abandon reporting any warnings that imply that.
+ !FunctionHasCleanupVars)
return;
// We are looking for a pair of blocks A, B so that the following is true:
@@ -840,16 +886,14 @@
// Let's check if any of the call arguments is a point of interest.
for (const auto &Argument : llvm::enumerate(Arguments)) {
if (auto Index = getIndexOfExpression(Argument.value())) {
- ParameterStatus &CurrentParamStatus = CurrentState.getStatusFor(*Index);
-
if (shouldBeCalledOnce(CallOrMessage, Argument.index())) {
// If the corresponding parameter is marked as 'called_once' we should
// consider it as a call.
processCallFor(*Index, CallOrMessage);
- } else if (CurrentParamStatus.getKind() == ParameterStatus::NotCalled) {
+ } else {
// Otherwise, we mark this parameter as escaped, which can be
// interpreted both as called or not called depending on the context.
- CurrentParamStatus = ParameterStatus::Escaped;
+ processEscapeFor(*Index);
}
// Otherwise, let's keep the state as it is.
}
@@ -883,6 +927,16 @@
}
}
+ /// Process escape of the parameter with the given index
+ void processEscapeFor(unsigned Index) {
+ ParameterStatus &CurrentParamStatus = CurrentState.getStatusFor(Index);
+
+ // Escape overrides whatever error we think happened.
+ if (CurrentParamStatus.isErrorStatus()) {
+ CurrentParamStatus = ParameterStatus::Escaped;
+ }
+ }
+
void findAndReportNotCalledBranches(const CFGBlock *Parent, unsigned Index,
bool IsEscape = false) {
for (const CFGBlock *Succ : Parent->succs()) {
@@ -894,9 +948,9 @@
"Block should have at least two successors at this point");
if (auto Clarification = NotCalledClarifier::clarify(Parent, Succ)) {
const ParmVarDecl *Parameter = getParameter(Index);
- Handler.handleNeverCalled(Parameter, Clarification->Location,
- Clarification->Reason, !IsEscape,
- !isExplicitlyMarked(Parameter));
+ Handler.handleNeverCalled(
+ Parameter, AC.getDecl(), Clarification->Location,
+ Clarification->Reason, !IsEscape, !isExplicitlyMarked(Parameter));
}
}
}
@@ -929,9 +983,9 @@
return false;
}
- QualType BlockType = Ty->getAs<BlockPointerType>()->getPointeeType();
+ QualType BlockType = Ty->castAs<BlockPointerType>()->getPointeeType();
// Completion handlers should have a block type with void return type.
- return BlockType->getAs<FunctionType>()->getReturnType()->isVoidType();
+ return BlockType->castAs<FunctionType>()->getReturnType()->isVoidType();
}
/// Return true if the only parameter of the function is conventional.
@@ -957,11 +1011,16 @@
return llvm::None;
}
+ /// Return true if the specified selector represents init method.
+ static bool isInitMethod(Selector MethodSelector) {
+ return MethodSelector.getMethodFamily() == OMF_init;
+ }
+
/// Return true if the specified selector piece matches conventions.
static bool isConventionalSelectorPiece(Selector MethodSelector,
unsigned PieceIndex,
QualType PieceType) {
- if (!isConventional(PieceType)) {
+ if (!isConventional(PieceType) || isInitMethod(MethodSelector)) {
return false;
}
@@ -970,13 +1029,15 @@
return hasConventionalSuffix(MethodSelector.getNameForSlot(0));
}
- return isConventional(MethodSelector.getNameForSlot(PieceIndex));
+ llvm::StringRef PieceName = MethodSelector.getNameForSlot(PieceIndex);
+ return isConventional(PieceName) || hasConventionalSuffix(PieceName);
}
bool shouldBeCalledOnce(const ParmVarDecl *Parameter) const {
return isExplicitlyMarked(Parameter) ||
(CheckConventionalParameters &&
- isConventional(Parameter->getName()) &&
+ (isConventional(Parameter->getName()) ||
+ hasConventionalSuffix(Parameter->getName())) &&
isConventional(Parameter->getType()));
}
@@ -1054,6 +1115,91 @@
return false;
}
+ // Return a call site where the block is called exactly once or null otherwise
+ const Expr *getBlockGuaraneedCallSite(const BlockExpr *Block) const {
+ ParentMap &PM = AC.getParentMap();
+
+ // We don't want to track the block through assignments and so on, instead
+ // we simply see how the block used and if it's used directly in a call,
+ // we decide based on call to what it is.
+ //
+ // In order to do this, we go up the parents of the block looking for
+ // a call or a message expressions. These might not be immediate parents
+ // of the actual block expression due to casts and parens, so we skip them.
+ for (const Stmt *Prev = Block, *Current = PM.getParent(Block);
+ Current != nullptr; Prev = Current, Current = PM.getParent(Current)) {
+ // Skip no-op (for our case) operations.
+ if (isa<CastExpr>(Current) || isa<ParenExpr>(Current))
+ continue;
+
+ // At this point, Prev represents our block as an immediate child of the
+ // call.
+ if (const auto *Call = dyn_cast<CallExpr>(Current)) {
+ // It might be the call of the Block itself...
+ if (Call->getCallee() == Prev)
+ return Call;
+
+ // ...or it can be an indirect call of the block.
+ return shouldBlockArgumentBeCalledOnce(Call, Prev) ? Call : nullptr;
+ }
+ if (const auto *Message = dyn_cast<ObjCMessageExpr>(Current)) {
+ return shouldBlockArgumentBeCalledOnce(Message, Prev) ? Message
+ : nullptr;
+ }
+
+ break;
+ }
+
+ return nullptr;
+ }
+
+ template <class CallLikeExpr>
+ bool shouldBlockArgumentBeCalledOnce(const CallLikeExpr *CallOrMessage,
+ const Stmt *BlockArgument) const {
+ // CallExpr::arguments does not interact nicely with llvm::enumerate.
+ llvm::ArrayRef<const Expr *> Arguments = llvm::makeArrayRef(
+ CallOrMessage->getArgs(), CallOrMessage->getNumArgs());
+
+ for (const auto &Argument : llvm::enumerate(Arguments)) {
+ if (Argument.value() == BlockArgument) {
+ return shouldBlockArgumentBeCalledOnce(CallOrMessage, Argument.index());
+ }
+ }
+
+ return false;
+ }
+
+ bool shouldBlockArgumentBeCalledOnce(const CallExpr *Call,
+ unsigned ParamIndex) const {
+ const FunctionDecl *Function = Call->getDirectCallee();
+ return shouldBlockArgumentBeCalledOnce(Function, ParamIndex) ||
+ shouldBeCalledOnce(Call, ParamIndex);
+ }
+
+ bool shouldBlockArgumentBeCalledOnce(const ObjCMessageExpr *Message,
+ unsigned ParamIndex) const {
+ // At the moment, we don't have any Obj-C methods we want to specifically
+ // check in here.
+ return shouldBeCalledOnce(Message, ParamIndex);
+ }
+
+ static bool shouldBlockArgumentBeCalledOnce(const FunctionDecl *Function,
+ unsigned ParamIndex) {
+ // There is a list of important API functions that while not following
+ // conventions nor being directly annotated, still guarantee that the
+ // callback parameter will be called exactly once.
+ //
+ // Here we check if this is the case.
+ return Function &&
+ llvm::any_of(KNOWN_CALLED_ONCE_PARAMETERS,
+ [Function, ParamIndex](
+ const KnownCalledOnceParameter &Reference) {
+ return Reference.FunctionName ==
+ Function->getName() &&
+ Reference.ParamIndex == ParamIndex;
+ });
+ }
+
/// Return true if the analyzed function is actually a default implementation
/// of the method that has to be overriden.
///
@@ -1336,11 +1482,7 @@
/// Check given parameter that was discovered to escape.
void checkEscapee(const ParmVarDecl &Parameter) {
if (auto Index = getIndex(Parameter)) {
- ParameterStatus &CurrentParamStatus = CurrentState.getStatusFor(*Index);
-
- if (CurrentParamStatus.getKind() == ParameterStatus::NotCalled) {
- CurrentParamStatus = ParameterStatus::Escaped;
- }
+ processEscapeFor(*Index);
}
}
@@ -1404,17 +1546,44 @@
}
void VisitBlockExpr(const BlockExpr *Block) {
+ // Block expressions are tricky. It is a very common practice to capture
+ // completion handlers by blocks and use them there.
+ // For this reason, it is important to analyze blocks and report warnings
+ // for completion handler misuse in blocks.
+ //
+ // However, it can be quite difficult to track how the block itself is being
+ // used. The full precise anlysis of that will be similar to alias analysis
+ // for completion handlers and can be too heavyweight for a compile-time
+ // diagnostic. Instead, we judge about the immediate use of the block.
+ //
+ // Here, we try to find a call expression where we know due to conventions,
+ // annotations, or other reasons that the block is called once and only
+ // once.
+ const Expr *CalledOnceCallSite = getBlockGuaraneedCallSite(Block);
+
+ // We need to report this information to the handler because in the
+ // situation when we know that the block is called exactly once, we can be
+ // stricter in terms of reported diagnostics.
+ if (CalledOnceCallSite) {
+ Handler.handleBlockThatIsGuaranteedToBeCalledOnce(Block->getBlockDecl());
+ } else {
+ Handler.handleBlockWithNoGuarantees(Block->getBlockDecl());
+ }
+
for (const auto &Capture : Block->getBlockDecl()->captures()) {
- // If a block captures a tracked parameter, it should be
- // considered escaped.
- // On one hand, blocks that do that should definitely call it on
- // every path. However, it is not guaranteed that the block
- // itself gets called whenever it gets created.
- //
- // Because we don't want to track blocks and whether they get called,
- // we consider such parameters simply escaped.
if (const auto *Param = dyn_cast<ParmVarDecl>(Capture.getVariable())) {
- checkEscapee(*Param);
+ if (auto Index = getIndex(*Param)) {
+ if (CalledOnceCallSite) {
+ // The call site of a block can be considered a call site of the
+ // captured parameter we track.
+ processCallFor(*Index, CalledOnceCallSite);
+ } else {
+ // We still should consider this block as an escape for parameter,
+ // if we don't know about its call site or the number of time it
+ // can be invoked.
+ processEscapeFor(*Index);
+ }
+ }
}
}
}
@@ -1441,6 +1610,10 @@
if (Var->getInit()) {
checkEscapee(Var->getInit());
}
+
+ if (Var->hasAttr<CleanupAttr>()) {
+ FunctionHasCleanupVars = true;
+ }
}
}
}
@@ -1509,6 +1682,13 @@
// around.
bool SuppressOnConventionalErrorPaths = false;
+ // The user can annotate variable declarations with cleanup functions, which
+ // essentially imposes a custom destructor logic on that variable.
+ // It is possible to use it, however, to call tracked parameters on all exits
+ // from the function. For this reason, we track the fact that the function
+ // actually has these.
+ bool FunctionHasCleanupVars = false;
+
State CurrentState;
ParamSizedVector<const ParmVarDecl *> TrackedParams;
CFGSizedVector<State> States;
diff --git a/src/llvm-project/clang/lib/Analysis/LiveVariables.cpp b/src/llvm-project/clang/lib/Analysis/LiveVariables.cpp
index 8cdc4cc..6c601c2 100644
--- a/src/llvm-project/clang/lib/Analysis/LiveVariables.cpp
+++ b/src/llvm-project/clang/lib/Analysis/LiveVariables.cpp
@@ -325,6 +325,11 @@
}
void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
+ if (LV.killAtAssign && B->getOpcode() == BO_Assign) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParens())) {
+ LV.inAssignment[DR] = 1;
+ }
+ }
if (B->isAssignmentOp()) {
if (!LV.killAtAssign)
return;
@@ -513,29 +518,8 @@
llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());
// FIXME: we should enqueue using post order.
- for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
- const CFGBlock *block = *it;
- worklist.enqueueBlock(block);
-
- // FIXME: Scan for DeclRefExprs using in the LHS of an assignment.
- // We need to do this because we lack context in the reverse analysis
- // to determine if a DeclRefExpr appears in such a context, and thus
- // doesn't constitute a "use".
- if (killAtAssign)
- for (CFGBlock::const_iterator bi = block->begin(), be = block->end();
- bi != be; ++bi) {
- if (Optional<CFGStmt> cs = bi->getAs<CFGStmt>()) {
- const Stmt* stmt = cs->getStmt();
- if (const auto *BO = dyn_cast<BinaryOperator>(stmt)) {
- if (BO->getOpcode() == BO_Assign) {
- if (const auto *DR =
- dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) {
- LV->inAssignment[DR] = 1;
- }
- }
- }
- }
- }
+ for (const CFGBlock *B : cfg->nodes()) {
+ worklist.enqueueBlock(B);
}
while (const CFGBlock *block = worklist.dequeue()) {
diff --git a/src/llvm-project/clang/lib/Analysis/MacroExpansionContext.cpp b/src/llvm-project/clang/lib/Analysis/MacroExpansionContext.cpp
new file mode 100644
index 0000000..2905106
--- /dev/null
+++ b/src/llvm-project/clang/lib/Analysis/MacroExpansionContext.cpp
@@ -0,0 +1,231 @@
+//===- MacroExpansionContext.cpp - Macro expansion information --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/MacroExpansionContext.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "macro-expansion-context"
+
+static void dumpTokenInto(const clang::Preprocessor &PP, clang::raw_ostream &OS,
+ clang::Token Tok);
+
+namespace clang {
+namespace detail {
+class MacroExpansionRangeRecorder : public PPCallbacks {
+ const Preprocessor &PP;
+ SourceManager &SM;
+ MacroExpansionContext::ExpansionRangeMap &ExpansionRanges;
+
+public:
+ explicit MacroExpansionRangeRecorder(
+ const Preprocessor &PP, SourceManager &SM,
+ MacroExpansionContext::ExpansionRangeMap &ExpansionRanges)
+ : PP(PP), SM(SM), ExpansionRanges(ExpansionRanges) {}
+
+ void MacroExpands(const Token &MacroName, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override {
+ // Ignore annotation tokens like: _Pragma("pack(push, 1)")
+ if (MacroName.getIdentifierInfo()->getName() == "_Pragma")
+ return;
+
+ SourceLocation MacroNameBegin = SM.getExpansionLoc(MacroName.getLocation());
+ assert(MacroNameBegin == SM.getExpansionLoc(Range.getBegin()));
+
+ const SourceLocation ExpansionEnd = [Range, &SM = SM, &MacroName] {
+ // If the range is empty, use the length of the macro.
+ if (Range.getBegin() == Range.getEnd())
+ return SM.getExpansionLoc(
+ MacroName.getLocation().getLocWithOffset(MacroName.getLength()));
+
+ // Include the last character.
+ return SM.getExpansionLoc(Range.getEnd()).getLocWithOffset(1);
+ }();
+
+ (void)PP;
+ LLVM_DEBUG(llvm::dbgs() << "MacroExpands event: '";
+ dumpTokenInto(PP, llvm::dbgs(), MacroName);
+ llvm::dbgs()
+ << "' with length " << MacroName.getLength() << " at ";
+ MacroNameBegin.print(llvm::dbgs(), SM);
+ llvm::dbgs() << ", expansion end at ";
+ ExpansionEnd.print(llvm::dbgs(), SM); llvm::dbgs() << '\n';);
+
+ // If the expansion range is empty, use the identifier of the macro as a
+ // range.
+ MacroExpansionContext::ExpansionRangeMap::iterator It;
+ bool Inserted;
+ std::tie(It, Inserted) =
+ ExpansionRanges.try_emplace(MacroNameBegin, ExpansionEnd);
+ if (Inserted) {
+ LLVM_DEBUG(llvm::dbgs() << "maps ";
+ It->getFirst().print(llvm::dbgs(), SM); llvm::dbgs() << " to ";
+ It->getSecond().print(llvm::dbgs(), SM);
+ llvm::dbgs() << '\n';);
+ } else {
+ if (SM.isBeforeInTranslationUnit(It->getSecond(), ExpansionEnd)) {
+ It->getSecond() = ExpansionEnd;
+ LLVM_DEBUG(
+ llvm::dbgs() << "remaps "; It->getFirst().print(llvm::dbgs(), SM);
+ llvm::dbgs() << " to "; It->getSecond().print(llvm::dbgs(), SM);
+ llvm::dbgs() << '\n';);
+ }
+ }
+ }
+};
+} // namespace detail
+} // namespace clang
+
+using namespace clang;
+
+MacroExpansionContext::MacroExpansionContext(const LangOptions &LangOpts)
+ : LangOpts(LangOpts) {}
+
+void MacroExpansionContext::registerForPreprocessor(Preprocessor &NewPP) {
+ PP = &NewPP;
+ SM = &NewPP.getSourceManager();
+
+ // Make sure that the Preprocessor does not outlive the MacroExpansionContext.
+ PP->addPPCallbacks(std::make_unique<detail::MacroExpansionRangeRecorder>(
+ *PP, *SM, ExpansionRanges));
+ // Same applies here.
+ PP->setTokenWatcher([this](const Token &Tok) { onTokenLexed(Tok); });
+}
+
+Optional<StringRef>
+MacroExpansionContext::getExpandedText(SourceLocation MacroExpansionLoc) const {
+ if (MacroExpansionLoc.isMacroID())
+ return llvm::None;
+
+ // If there was no macro expansion at that location, return None.
+ if (ExpansionRanges.find_as(MacroExpansionLoc) == ExpansionRanges.end())
+ return llvm::None;
+
+ // There was macro expansion, but resulted in no tokens, return empty string.
+ const auto It = ExpandedTokens.find_as(MacroExpansionLoc);
+ if (It == ExpandedTokens.end())
+ return StringRef{""};
+
+ // Otherwise we have the actual token sequence as string.
+ return It->getSecond().str();
+}
+
+Optional<StringRef>
+MacroExpansionContext::getOriginalText(SourceLocation MacroExpansionLoc) const {
+ if (MacroExpansionLoc.isMacroID())
+ return llvm::None;
+
+ const auto It = ExpansionRanges.find_as(MacroExpansionLoc);
+ if (It == ExpansionRanges.end())
+ return llvm::None;
+
+ assert(It->getFirst() != It->getSecond() &&
+ "Every macro expansion must cover a non-empty range.");
+
+ return Lexer::getSourceText(
+ CharSourceRange::getCharRange(It->getFirst(), It->getSecond()), *SM,
+ LangOpts);
+}
+
+void MacroExpansionContext::dumpExpansionRanges() const {
+ dumpExpansionRangesToStream(llvm::dbgs());
+}
+void MacroExpansionContext::dumpExpandedTexts() const {
+ dumpExpandedTextsToStream(llvm::dbgs());
+}
+
+void MacroExpansionContext::dumpExpansionRangesToStream(raw_ostream &OS) const {
+ std::vector<std::pair<SourceLocation, SourceLocation>> LocalExpansionRanges;
+ LocalExpansionRanges.reserve(ExpansionRanges.size());
+ for (const auto &Record : ExpansionRanges)
+ LocalExpansionRanges.emplace_back(
+ std::make_pair(Record.getFirst(), Record.getSecond()));
+ llvm::sort(LocalExpansionRanges);
+
+ OS << "\n=============== ExpansionRanges ===============\n";
+ for (const auto &Record : LocalExpansionRanges) {
+ OS << "> ";
+ Record.first.print(OS, *SM);
+ OS << ", ";
+ Record.second.print(OS, *SM);
+ OS << '\n';
+ }
+}
+
+void MacroExpansionContext::dumpExpandedTextsToStream(raw_ostream &OS) const {
+ std::vector<std::pair<SourceLocation, MacroExpansionText>>
+ LocalExpandedTokens;
+ LocalExpandedTokens.reserve(ExpandedTokens.size());
+ for (const auto &Record : ExpandedTokens)
+ LocalExpandedTokens.emplace_back(
+ std::make_pair(Record.getFirst(), Record.getSecond()));
+ llvm::sort(LocalExpandedTokens);
+
+ OS << "\n=============== ExpandedTokens ===============\n";
+ for (const auto &Record : LocalExpandedTokens) {
+ OS << "> ";
+ Record.first.print(OS, *SM);
+ OS << " -> '" << Record.second << "'\n";
+ }
+}
+
+static void dumpTokenInto(const Preprocessor &PP, raw_ostream &OS, Token Tok) {
+ assert(Tok.isNot(tok::raw_identifier));
+
+ // Ignore annotation tokens like: _Pragma("pack(push, 1)")
+ if (Tok.isAnnotation())
+ return;
+
+ if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
+ // FIXME: For now, we don't respect whitespaces between macro expanded
+ // tokens. We just emit a space after every identifier to produce a valid
+ // code for `int a ;` like expansions.
+ // ^-^-- Space after the 'int' and 'a' identifiers.
+ OS << II->getName() << ' ';
+ } else if (Tok.isLiteral() && !Tok.needsCleaning() && Tok.getLiteralData()) {
+ OS << StringRef(Tok.getLiteralData(), Tok.getLength());
+ } else {
+ char Tmp[256];
+ if (Tok.getLength() < sizeof(Tmp)) {
+ const char *TokPtr = Tmp;
+ // FIXME: Might use a different overload for cleaner callsite.
+ unsigned Len = PP.getSpelling(Tok, TokPtr);
+ OS.write(TokPtr, Len);
+ } else {
+ OS << "<too long token>";
+ }
+ }
+}
+
+void MacroExpansionContext::onTokenLexed(const Token &Tok) {
+ SourceLocation SLoc = Tok.getLocation();
+ if (SLoc.isFileID())
+ return;
+
+ LLVM_DEBUG(llvm::dbgs() << "lexed macro expansion token '";
+ dumpTokenInto(*PP, llvm::dbgs(), Tok); llvm::dbgs() << "' at ";
+ SLoc.print(llvm::dbgs(), *SM); llvm::dbgs() << '\n';);
+
+ // Remove spelling location.
+ SourceLocation CurrExpansionLoc = SM->getExpansionLoc(SLoc);
+
+ MacroExpansionText TokenAsString;
+ llvm::raw_svector_ostream OS(TokenAsString);
+
+ // FIXME: Prepend newlines and space to produce the exact same output as the
+ // preprocessor would for this token.
+
+ dumpTokenInto(*PP, OS, Tok);
+
+ ExpansionMap::iterator It;
+ bool Inserted;
+ std::tie(It, Inserted) =
+ ExpandedTokens.try_emplace(CurrExpansionLoc, std::move(TokenAsString));
+ if (!Inserted)
+ It->getSecond().append(TokenAsString);
+}
+
diff --git a/src/llvm-project/clang/lib/Analysis/PathDiagnostic.cpp b/src/llvm-project/clang/lib/Analysis/PathDiagnostic.cpp
index b42f47f..ee8185c 100644
--- a/src/llvm-project/clang/lib/Analysis/PathDiagnostic.cpp
+++ b/src/llvm-project/clang/lib/Analysis/PathDiagnostic.cpp
@@ -898,7 +898,7 @@
if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
} else {
- TArg.print(PrintingPolicy(LO), Out);
+ TArg.print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
}
}
diff --git a/src/llvm-project/clang/lib/Analysis/RetainSummaryManager.cpp b/src/llvm-project/clang/lib/Analysis/RetainSummaryManager.cpp
index 9f45a8e..7ed1e40 100644
--- a/src/llvm-project/clang/lib/Analysis/RetainSummaryManager.cpp
+++ b/src/llvm-project/clang/lib/Analysis/RetainSummaryManager.cpp
@@ -145,16 +145,20 @@
return !(match(SubclassM, *D, D->getASTContext()).empty());
}
-static bool isOSObjectSubclass(const Decl *D) {
- // OSSymbols are particular OSObjects that are allocated globally
- // and therefore aren't really refcounted, so we ignore them.
- return D && isSubclass(D, "OSMetaClassBase") && !isSubclass(D, "OSSymbol");
+static bool isExactClass(const Decl *D, StringRef ClassName) {
+ using namespace ast_matchers;
+ DeclarationMatcher sameClassM =
+ cxxRecordDecl(hasName(std::string(ClassName)));
+ return !(match(sameClassM, *D, D->getASTContext()).empty());
}
-static bool isOSObjectDynamicCast(StringRef S) {
- return S == "safeMetaCast";
+static bool isOSObjectSubclass(const Decl *D) {
+ return D && isSubclass(D, "OSMetaClassBase") &&
+ !isExactClass(D, "OSMetaClass");
}
+static bool isOSObjectDynamicCast(StringRef S) { return S == "safeMetaCast"; }
+
static bool isOSObjectRequiredCast(StringRef S) {
return S == "requiredMetaCast";
}
@@ -185,20 +189,22 @@
}
static bool isRetain(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("retain") || FName.endswith_lower("retain");
+ return FName.startswith_insensitive("retain") ||
+ FName.endswith_insensitive("retain");
}
static bool isRelease(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("release") || FName.endswith_lower("release");
+ return FName.startswith_insensitive("release") ||
+ FName.endswith_insensitive("release");
}
static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
- return FName.startswith_lower("autorelease") ||
- FName.endswith_lower("autorelease");
+ return FName.startswith_insensitive("autorelease") ||
+ FName.endswith_insensitive("autorelease");
}
static bool isMakeCollectable(StringRef FName) {
- return FName.contains_lower("MakeCollectable");
+ return FName.contains_insensitive("MakeCollectable");
}
/// A function is OSObject related if it is declared on a subclass
@@ -883,8 +889,8 @@
return None;
}
-/// \return Whether the chain of typedefs starting from {@code QT}
-/// has a typedef with a given name {@code Name}.
+/// \return Whether the chain of typedefs starting from @c QT
+/// has a typedef with a given name @c Name.
static bool hasTypedefNamed(QualType QT,
StringRef Name) {
while (auto *T = dyn_cast<TypedefType>(QT)) {
@@ -1096,7 +1102,7 @@
if (S.isKeywordSelector()) {
for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
StringRef Slot = S.getNameForSlot(i);
- if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
+ if (Slot.substr(Slot.size() - 8).equals_insensitive("delegate")) {
if (ResultEff == ObjCInitRetE)
ResultEff = RetEffect::MakeNoRetHard();
else
diff --git a/src/llvm-project/clang/lib/Analysis/ThreadSafety.cpp b/src/llvm-project/clang/lib/Analysis/ThreadSafety.cpp
index 21583e9..5b2c882 100644
--- a/src/llvm-project/clang/lib/Analysis/ThreadSafety.cpp
+++ b/src/llvm-project/clang/lib/Analysis/ThreadSafety.cpp
@@ -105,32 +105,37 @@
///
/// FIXME: this analysis does not currently support re-entrant locking.
class FactEntry : public CapabilityExpr {
+public:
+ /// Where a fact comes from.
+ enum SourceKind {
+ Acquired, ///< The fact has been directly acquired.
+ Asserted, ///< The fact has been asserted to be held.
+ Declared, ///< The fact is assumed to be held by callers.
+ Managed, ///< The fact has been acquired through a scoped capability.
+ };
+
private:
/// Exclusive or shared.
- LockKind LKind;
+ LockKind LKind : 8;
+
+ // How it was acquired.
+ SourceKind Source : 8;
/// Where it was acquired.
SourceLocation AcquireLoc;
- /// True if the lock was asserted.
- bool Asserted;
-
- /// True if the lock was declared.
- bool Declared;
-
public:
FactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
- bool Asrt, bool Declrd = false)
- : CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Asserted(Asrt),
- Declared(Declrd) {}
+ SourceKind Src)
+ : CapabilityExpr(CE), LKind(LK), Source(Src), AcquireLoc(Loc) {}
virtual ~FactEntry() = default;
LockKind kind() const { return LKind; }
SourceLocation loc() const { return AcquireLoc; }
- bool asserted() const { return Asserted; }
- bool declared() const { return Declared; }
- void setDeclared(bool D) { Declared = D; }
+ bool asserted() const { return Source == Asserted; }
+ bool declared() const { return Source == Declared; }
+ bool managed() const { return Source == Managed; }
virtual void
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
@@ -851,20 +856,16 @@
namespace {
class LockableFactEntry : public FactEntry {
-private:
- /// managed by ScopedLockable object
- bool Managed;
-
public:
LockableFactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
- bool Mng = false, bool Asrt = false)
- : FactEntry(CE, LK, Loc, Asrt), Managed(Mng) {}
+ SourceKind Src = Acquired)
+ : FactEntry(CE, LK, Loc, Src) {}
void
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
SourceLocation JoinLoc, LockErrorKind LEK,
ThreadSafetyHandler &Handler) const override {
- if (!Managed && !asserted() && !negative() && !isUniversal()) {
+ if (!asserted() && !negative() && !isUniversal()) {
Handler.handleMutexHeldEndOfScope("mutex", toString(), loc(), JoinLoc,
LEK);
}
@@ -903,7 +904,7 @@
public:
ScopedLockableFactEntry(const CapabilityExpr &CE, SourceLocation Loc)
- : FactEntry(CE, LK_Exclusive, Loc, false) {}
+ : FactEntry(CE, LK_Exclusive, Loc, Acquired) {}
void addLock(const CapabilityExpr &M) {
UnderlyingMutexes.emplace_back(M.sexpr(), UCK_Acquired);
@@ -983,7 +984,7 @@
} else {
FSet.removeLock(FactMan, !Cp);
FSet.addLock(FactMan,
- std::make_unique<LockableFactEntry>(Cp, kind, loc));
+ std::make_unique<LockableFactEntry>(Cp, kind, loc, Managed));
}
}
@@ -1049,15 +1050,15 @@
const CFGBlock* PredBlock,
const CFGBlock *CurrBlock);
- void intersectAndWarn(FactSet &FSet1, const FactSet &FSet2,
- SourceLocation JoinLoc,
- LockErrorKind LEK1, LockErrorKind LEK2,
- bool Modify=true);
+ bool join(const FactEntry &a, const FactEntry &b);
- void intersectAndWarn(FactSet &FSet1, const FactSet &FSet2,
- SourceLocation JoinLoc, LockErrorKind LEK1,
- bool Modify=true) {
- intersectAndWarn(FSet1, FSet2, JoinLoc, LEK1, LEK1, Modify);
+ void intersectAndWarn(FactSet &EntrySet, const FactSet &ExitSet,
+ SourceLocation JoinLoc, LockErrorKind EntryLEK,
+ LockErrorKind ExitLEK);
+
+ void intersectAndWarn(FactSet &EntrySet, const FactSet &ExitSet,
+ SourceLocation JoinLoc, LockErrorKind LEK) {
+ intersectAndWarn(EntrySet, ExitSet, JoinLoc, LEK, LEK);
}
void runAnalysis(AnalysisDeclContext &AC);
@@ -1854,10 +1855,11 @@
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
for (const auto &AssertLock : AssertLocks)
- Analyzer->addLock(FSet,
- std::make_unique<LockableFactEntry>(
- AssertLock, LK_Exclusive, Loc, false, true),
- ClassifyDiagnostic(A));
+ Analyzer->addLock(
+ FSet,
+ std::make_unique<LockableFactEntry>(AssertLock, LK_Exclusive, Loc,
+ FactEntry::Asserted),
+ ClassifyDiagnostic(A));
break;
}
case attr::AssertSharedLock: {
@@ -1866,10 +1868,11 @@
CapExprSet AssertLocks;
Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
for (const auto &AssertLock : AssertLocks)
- Analyzer->addLock(FSet,
- std::make_unique<LockableFactEntry>(
- AssertLock, LK_Shared, Loc, false, true),
- ClassifyDiagnostic(A));
+ Analyzer->addLock(
+ FSet,
+ std::make_unique<LockableFactEntry>(AssertLock, LK_Shared, Loc,
+ FactEntry::Asserted),
+ ClassifyDiagnostic(A));
break;
}
@@ -1882,7 +1885,7 @@
std::make_unique<LockableFactEntry>(
AssertLock,
A->isShared() ? LK_Shared : LK_Exclusive, Loc,
- false, true),
+ FactEntry::Asserted),
ClassifyDiagnostic(A));
break;
}
@@ -1943,14 +1946,16 @@
Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind);
// Add locks.
+ FactEntry::SourceKind Source =
+ isScopedVar ? FactEntry::Managed : FactEntry::Acquired;
for (const auto &M : ExclusiveLocksToAdd)
- Analyzer->addLock(FSet, std::make_unique<LockableFactEntry>(
- M, LK_Exclusive, Loc, isScopedVar),
- CapDiagKind);
+ Analyzer->addLock(
+ FSet, std::make_unique<LockableFactEntry>(M, LK_Exclusive, Loc, Source),
+ CapDiagKind);
for (const auto &M : SharedLocksToAdd)
- Analyzer->addLock(FSet, std::make_unique<LockableFactEntry>(
- M, LK_Shared, Loc, isScopedVar),
- CapDiagKind);
+ Analyzer->addLock(
+ FSet, std::make_unique<LockableFactEntry>(M, LK_Shared, Loc, Source),
+ CapDiagKind);
if (isScopedVar) {
// Add the managing object as a dummy mutex, mapped to the underlying mutex.
@@ -2051,15 +2056,11 @@
if (ME && MD) {
if (ME->isArrow()) {
- if (MD->isConst())
- checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
- else // FIXME -- should be AK_Written
- checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
+ // Should perhaps be AK_Written if !MD->isConst().
+ checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
} else {
- if (MD->isConst())
- checkAccess(CE->getImplicitObjectArgument(), AK_Read);
- else // FIXME -- should be AK_Written
- checkAccess(CE->getImplicitObjectArgument(), AK_Read);
+ // Should perhaps be AK_Written if !MD->isConst().
+ checkAccess(CE->getImplicitObjectArgument(), AK_Read);
}
}
@@ -2169,7 +2170,7 @@
if (!CtorD || !CtorD->hasAttrs())
continue;
handleCall(E, CtorD, VD);
- } else if (isa<CallExpr>(E) && E->isRValue()) {
+ } else if (isa<CallExpr>(E) && E->isPRValue()) {
// If the object is initialized by a function call that returns a
// scoped lockable by value, use the attributes on the copy or move
// constructor to figure out what effect that should have on the
@@ -2187,6 +2188,28 @@
}
}
+/// Given two facts merging on a join point, decide whether to warn and which
+/// one to keep.
+///
+/// \return false if we should keep \p A, true if we should keep \p B.
+bool ThreadSafetyAnalyzer::join(const FactEntry &A, const FactEntry &B) {
+ if (A.kind() != B.kind()) {
+ // For managed capabilities, the destructor should unlock in the right mode
+ // anyway. For asserted capabilities no unlocking is needed.
+ if ((A.managed() || A.asserted()) && (B.managed() || B.asserted())) {
+ // The shared capability subsumes the exclusive capability.
+ return B.kind() == LK_Shared;
+ } else {
+ Handler.handleExclusiveAndShared("mutex", B.toString(), B.loc(), A.loc());
+ // Take the exclusive capability to reduce further warnings.
+ return B.kind() == LK_Exclusive;
+ }
+ } else {
+ // The non-asserted capability is the one we want to track.
+ return A.asserted() && !B.asserted();
+ }
+}
+
/// Compute the intersection of two locksets and issue warnings for any
/// locks in the symmetric difference.
///
@@ -2196,55 +2219,44 @@
/// are the same. In the event of a difference, we use the intersection of these
/// two locksets at the start of D.
///
-/// \param FSet1 The first lockset.
-/// \param FSet2 The second lockset.
+/// \param EntrySet A lockset for entry into a (possibly new) block.
+/// \param ExitSet The lockset on exiting a preceding block.
/// \param JoinLoc The location of the join point for error reporting
-/// \param LEK1 The error message to report if a mutex is missing from LSet1
-/// \param LEK2 The error message to report if a mutex is missing from Lset2
-void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &FSet1,
- const FactSet &FSet2,
+/// \param EntryLEK The warning if a mutex is missing from \p EntrySet.
+/// \param ExitLEK The warning if a mutex is missing from \p ExitSet.
+void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &EntrySet,
+ const FactSet &ExitSet,
SourceLocation JoinLoc,
- LockErrorKind LEK1,
- LockErrorKind LEK2,
- bool Modify) {
- FactSet FSet1Orig = FSet1;
+ LockErrorKind EntryLEK,
+ LockErrorKind ExitLEK) {
+ FactSet EntrySetOrig = EntrySet;
- // Find locks in FSet2 that conflict or are not in FSet1, and warn.
- for (const auto &Fact : FSet2) {
- const FactEntry *LDat1 = nullptr;
- const FactEntry *LDat2 = &FactMan[Fact];
- FactSet::iterator Iter1 = FSet1.findLockIter(FactMan, *LDat2);
- if (Iter1 != FSet1.end()) LDat1 = &FactMan[*Iter1];
+ // Find locks in ExitSet that conflict or are not in EntrySet, and warn.
+ for (const auto &Fact : ExitSet) {
+ const FactEntry &ExitFact = FactMan[Fact];
- if (LDat1) {
- if (LDat1->kind() != LDat2->kind()) {
- Handler.handleExclusiveAndShared("mutex", LDat2->toString(),
- LDat2->loc(), LDat1->loc());
- if (Modify && LDat1->kind() != LK_Exclusive) {
- // Take the exclusive lock, which is the one in FSet2.
- *Iter1 = Fact;
- }
- }
- else if (Modify && LDat1->asserted() && !LDat2->asserted()) {
- // The non-asserted lock in FSet2 is the one we want to track.
- *Iter1 = Fact;
- }
- } else {
- LDat2->handleRemovalFromIntersection(FSet2, FactMan, JoinLoc, LEK1,
- Handler);
+ FactSet::iterator EntryIt = EntrySet.findLockIter(FactMan, ExitFact);
+ if (EntryIt != EntrySet.end()) {
+ if (join(FactMan[*EntryIt], ExitFact) &&
+ EntryLEK == LEK_LockedSomePredecessors)
+ *EntryIt = Fact;
+ } else if (!ExitFact.managed()) {
+ ExitFact.handleRemovalFromIntersection(ExitSet, FactMan, JoinLoc,
+ EntryLEK, Handler);
}
}
- // Find locks in FSet1 that are not in FSet2, and remove them.
- for (const auto &Fact : FSet1Orig) {
- const FactEntry *LDat1 = &FactMan[Fact];
- const FactEntry *LDat2 = FSet2.findLock(FactMan, *LDat1);
+ // Find locks in EntrySet that are not in ExitSet, and remove them.
+ for (const auto &Fact : EntrySetOrig) {
+ const FactEntry *EntryFact = &FactMan[Fact];
+ const FactEntry *ExitFact = ExitSet.findLock(FactMan, *EntryFact);
- if (!LDat2) {
- LDat1->handleRemovalFromIntersection(FSet1Orig, FactMan, JoinLoc, LEK2,
- Handler);
- if (Modify)
- FSet1.removeLock(FactMan, *LDat1);
+ if (!ExitFact) {
+ if (!EntryFact->managed() || ExitLEK == LEK_LockedSomeLoopIterations)
+ EntryFact->handleRemovalFromIntersection(EntrySetOrig, FactMan, JoinLoc,
+ ExitLEK, Handler);
+ if (ExitLEK == LEK_LockedSomePredecessors)
+ EntrySet.removeLock(FactMan, *EntryFact);
}
}
}
@@ -2368,13 +2380,13 @@
// FIXME -- Loc can be wrong here.
for (const auto &Mu : ExclusiveLocksToAdd) {
- auto Entry = std::make_unique<LockableFactEntry>(Mu, LK_Exclusive, Loc);
- Entry->setDeclared(true);
+ auto Entry = std::make_unique<LockableFactEntry>(Mu, LK_Exclusive, Loc,
+ FactEntry::Declared);
addLock(InitialLockset, std::move(Entry), CapDiagKind, true);
}
for (const auto &Mu : SharedLocksToAdd) {
- auto Entry = std::make_unique<LockableFactEntry>(Mu, LK_Shared, Loc);
- Entry->setDeclared(true);
+ auto Entry = std::make_unique<LockableFactEntry>(Mu, LK_Shared, Loc,
+ FactEntry::Declared);
addLock(InitialLockset, std::move(Entry), CapDiagKind, true);
}
}
@@ -2468,11 +2480,9 @@
PrevBlock, CurrBlock);
// Do not update EntrySet.
- intersectAndWarn(CurrBlockInfo->EntrySet, PrevLockset,
- PrevBlockInfo->ExitLoc,
- IsLoop ? LEK_LockedSomeLoopIterations
- : LEK_LockedSomePredecessors,
- false);
+ intersectAndWarn(
+ CurrBlockInfo->EntrySet, PrevLockset, PrevBlockInfo->ExitLoc,
+ IsLoop ? LEK_LockedSomeLoopIterations : LEK_LockedSomePredecessors);
}
}
@@ -2520,10 +2530,8 @@
CFGBlock *FirstLoopBlock = *SI;
CFGBlockInfo *PreLoop = &BlockInfo[FirstLoopBlock->getBlockID()];
CFGBlockInfo *LoopEnd = &BlockInfo[CurrBlockID];
- intersectAndWarn(LoopEnd->ExitSet, PreLoop->EntrySet,
- PreLoop->EntryLoc,
- LEK_LockedSomeLoopIterations,
- false);
+ intersectAndWarn(PreLoop->EntrySet, LoopEnd->ExitSet, PreLoop->EntryLoc,
+ LEK_LockedSomeLoopIterations);
}
}
@@ -2551,11 +2559,8 @@
ExpectedExitSet.removeLock(FactMan, Lock);
// FIXME: Should we call this function for all blocks which exit the function?
- intersectAndWarn(ExpectedExitSet, Final->ExitSet,
- Final->ExitLoc,
- LEK_LockedAtEndOfFunction,
- LEK_NotLockedAtEndOfFunction,
- false);
+ intersectAndWarn(ExpectedExitSet, Final->ExitSet, Final->ExitLoc,
+ LEK_LockedAtEndOfFunction, LEK_NotLockedAtEndOfFunction);
Handler.leaveFunction(CurrentFunction);
}
diff --git a/src/llvm-project/clang/lib/Analysis/ThreadSafetyCommon.cpp b/src/llvm-project/clang/lib/Analysis/ThreadSafetyCommon.cpp
index 0c5d185..e6b4a05 100644
--- a/src/llvm-project/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/src/llvm-project/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -26,6 +26,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include <algorithm>
@@ -40,7 +41,7 @@
std::string threadSafety::getSourceLiteralString(const Expr *CE) {
switch (CE->getStmtClass()) {
case Stmt::IntegerLiteralClass:
- return cast<IntegerLiteral>(CE)->getValue().toString(10, true);
+ return toString(cast<IntegerLiteral>(CE)->getValue(), 10, true);
case Stmt::StringLiteralClass: {
std::string ret("\"");
ret += cast<StringLiteral>(CE)->getString();
diff --git a/src/llvm-project/clang/lib/Basic/Attributes.cpp b/src/llvm-project/clang/lib/Basic/Attributes.cpp
index ff6dbf8..62eea9c 100644
--- a/src/llvm-project/clang/lib/Basic/Attributes.cpp
+++ b/src/llvm-project/clang/lib/Basic/Attributes.cpp
@@ -20,6 +20,14 @@
else if (ScopeName == "_Clang")
ScopeName = "clang";
+ // As a special case, look for the omp::sequence and omp::directive
+ // attributes. We support those, but not through the typical attribute
+ // machinery that goes through TableGen. We support this in all OpenMP modes
+ // so long as double square brackets are enabled.
+ if (LangOpts.OpenMP && LangOpts.DoubleSquareBracketAttributes &&
+ ScopeName == "omp")
+ return (Name == "directive" || Name == "sequence") ? 1 : 0;
+
#include "clang/Basic/AttrHasAttributeImpl.inc"
return 0;
diff --git a/src/llvm-project/clang/lib/Basic/Builtins.cpp b/src/llvm-project/clang/lib/Basic/Builtins.cpp
index 0cd89df..7118aa9 100644
--- a/src/llvm-project/clang/lib/Basic/Builtins.cpp
+++ b/src/llvm-project/clang/lib/Basic/Builtins.cpp
@@ -60,6 +60,8 @@
bool BuiltinsUnsupported =
(LangOpts.NoBuiltin || LangOpts.isNoBuiltinFunc(BuiltinInfo.Name)) &&
strchr(BuiltinInfo.Attributes, 'f');
+ bool CorBuiltinsUnsupported =
+ !LangOpts.Coroutines && (BuiltinInfo.Langs & COR_LANG);
bool MathBuiltinsUnsupported =
LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName &&
llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h");
@@ -75,12 +77,14 @@
bool OclCUnsupported = !LangOpts.OpenCL &&
(BuiltinInfo.Langs & ALL_OCLC_LANGUAGES);
bool OpenMPUnsupported = !LangOpts.OpenMP && BuiltinInfo.Langs == OMP_LANG;
+ bool CUDAUnsupported = !LangOpts.CUDA && BuiltinInfo.Langs == CUDA_LANG;
bool CPlusPlusUnsupported =
!LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG;
- return !BuiltinsUnsupported && !MathBuiltinsUnsupported && !OclCUnsupported &&
- !OclC1Unsupported && !OclC2Unsupported && !OpenMPUnsupported &&
- !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported &&
- !CPlusPlusUnsupported;
+ return !BuiltinsUnsupported && !CorBuiltinsUnsupported &&
+ !MathBuiltinsUnsupported && !OclCUnsupported && !OclC1Unsupported &&
+ !OclC2Unsupported && !OpenMPUnsupported && !GnuModeUnsupported &&
+ !MSModeUnsupported && !ObjCUnsupported && !CPlusPlusUnsupported &&
+ !CUDAUnsupported;
}
/// initializeBuiltins - Mark the identifiers for all the builtins with their
@@ -105,10 +109,6 @@
.setBuiltinID(i + Builtin::FirstTSBuiltin + TSRecords.size());
}
-void Builtin::Context::forgetBuiltin(unsigned ID, IdentifierTable &Table) {
- Table.get(getRecord(ID).Name).setBuiltinID(0);
-}
-
unsigned Builtin::Context::getRequiredVectorWidth(unsigned ID) const {
const char *WidthPos = ::strchr(getRecord(ID).Attributes, 'V');
if (!WidthPos)
diff --git a/src/llvm-project/clang/lib/Basic/CMakeLists.txt b/src/llvm-project/clang/lib/Basic/CMakeLists.txt
index e531948..c550e8c 100644
--- a/src/llvm-project/clang/lib/Basic/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/Basic/CMakeLists.txt
@@ -1,6 +1,4 @@
set(LLVM_LINK_COMPONENTS
- Core
- MC
Support
)
@@ -44,6 +42,7 @@
CharInfo.cpp
CodeGenOptions.cpp
Cuda.cpp
+ DarwinSDKInfo.cpp
Diagnostic.cpp
DiagnosticIDs.cpp
DiagnosticOptions.cpp
@@ -60,7 +59,7 @@
OpenMPKinds.cpp
OperatorPrecedence.cpp
ProfileList.cpp
- SanitizerBlacklist.cpp
+ NoSanitizeList.cpp
SanitizerSpecialCaseList.cpp
Sanitizers.cpp
SourceLocation.cpp
@@ -78,6 +77,7 @@
Targets/Hexagon.cpp
Targets/Lanai.cpp
Targets/Le64.cpp
+ Targets/M68k.cpp
Targets/MSP430.cpp
Targets/Mips.cpp
Targets/NVPTX.cpp
diff --git a/src/llvm-project/clang/lib/Basic/CodeGenOptions.cpp b/src/llvm-project/clang/lib/Basic/CodeGenOptions.cpp
index 4fc7a53..0c609cf 100644
--- a/src/llvm-project/clang/lib/Basic/CodeGenOptions.cpp
+++ b/src/llvm-project/clang/lib/Basic/CodeGenOptions.cpp
@@ -20,12 +20,4 @@
memcpy(CoverageVersion, "408*", 4);
}
-bool CodeGenOptions::isNoBuiltinFunc(const char *Name) const {
- StringRef FuncName(Name);
- for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i)
- if (FuncName.equals(NoBuiltinFuncs[i]))
- return true;
- return false;
-}
-
} // end namespace clang
diff --git a/src/llvm-project/clang/lib/Basic/Cuda.cpp b/src/llvm-project/clang/lib/Basic/Cuda.cpp
index 144113f..766135b 100644
--- a/src/llvm-project/clang/lib/Basic/Cuda.cpp
+++ b/src/llvm-project/clang/lib/Basic/Cuda.cpp
@@ -32,6 +32,10 @@
return "10.2";
case CudaVersion::CUDA_110:
return "11.0";
+ case CudaVersion::CUDA_111:
+ return "11.1";
+ case CudaVersion::CUDA_112:
+ return "11.2";
}
llvm_unreachable("invalid enum");
}
@@ -48,21 +52,25 @@
.Case("10.1", CudaVersion::CUDA_101)
.Case("10.2", CudaVersion::CUDA_102)
.Case("11.0", CudaVersion::CUDA_110)
+ .Case("11.1", CudaVersion::CUDA_111)
+ .Case("11.2", CudaVersion::CUDA_112)
.Default(CudaVersion::UNKNOWN);
}
+namespace {
struct CudaArchToStringMap {
CudaArch arch;
const char *arch_name;
const char *virtual_arch_name;
};
+} // namespace
#define SM2(sm, ca) \
{ CudaArch::SM_##sm, "sm_" #sm, ca }
#define SM(sm) SM2(sm, "compute_" #sm)
#define GFX(gpu) \
{ CudaArch::GFX##gpu, "gfx" #gpu, "compute_amdgcn" }
-CudaArchToStringMap arch_names[] = {
+static const CudaArchToStringMap arch_names[] = {
// clang-format off
{CudaArch::UNUSED, "", ""},
SM2(20, "compute_20"), SM2(21, "compute_20"), // Fermi
@@ -71,7 +79,7 @@
SM(60), SM(61), SM(62), // Pascal
SM(70), SM(72), // Volta
SM(75), // Turing
- SM(80), // Ampere
+ SM(80), SM(86), // Ampere
GFX(600), // gfx600
GFX(601), // gfx601
GFX(602), // gfx602
@@ -92,14 +100,18 @@
GFX(906), // gfx906
GFX(908), // gfx908
GFX(909), // gfx909
+ GFX(90a), // gfx90a
GFX(90c), // gfx90c
GFX(1010), // gfx1010
GFX(1011), // gfx1011
GFX(1012), // gfx1012
+ GFX(1013), // gfx1013
GFX(1030), // gfx1030
GFX(1031), // gfx1031
GFX(1032), // gfx1032
GFX(1033), // gfx1033
+ GFX(1034), // gfx1034
+ GFX(1035), // gfx1035
// clang-format on
};
#undef SM
@@ -164,6 +176,8 @@
return CudaVersion::CUDA_100;
case CudaArch::SM_80:
return CudaVersion::CUDA_110;
+ case CudaArch::SM_86:
+ return CudaVersion::CUDA_111;
default:
llvm_unreachable("invalid enum");
}
@@ -209,6 +223,10 @@
return CudaVersion::CUDA_102;
case 110:
return CudaVersion::CUDA_110;
+ case 111:
+ return CudaVersion::CUDA_111;
+ case 112:
+ return CudaVersion::CUDA_112;
default:
return CudaVersion::UNKNOWN;
}
diff --git a/src/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp b/src/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp
new file mode 100644
index 0000000..fe35f77
--- /dev/null
+++ b/src/llvm-project/clang/lib/Basic/DarwinSDKInfo.cpp
@@ -0,0 +1,131 @@
+//===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/DarwinSDKInfo.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang;
+
+Optional<VersionTuple> DarwinSDKInfo::RelatedTargetVersionMapping::map(
+ const VersionTuple &Key, const VersionTuple &MinimumValue,
+ Optional<VersionTuple> MaximumValue) const {
+ if (Key < MinimumKeyVersion)
+ return MinimumValue;
+ if (Key > MaximumKeyVersion)
+ return MaximumValue;
+ auto KV = Mapping.find(Key.normalize());
+ if (KV != Mapping.end())
+ return KV->getSecond();
+ // If no exact entry found, try just the major key version. Only do so when
+ // a minor version number is present, to avoid recursing indefinitely into
+ // the major-only check.
+ if (Key.getMinor())
+ return map(VersionTuple(Key.getMajor()), MinimumValue, MaximumValue);
+ // If this a major only key, return None for a missing entry.
+ return None;
+}
+
+Optional<DarwinSDKInfo::RelatedTargetVersionMapping>
+DarwinSDKInfo::RelatedTargetVersionMapping::parseJSON(
+ const llvm::json::Object &Obj, VersionTuple MaximumDeploymentTarget) {
+ VersionTuple Min = VersionTuple(std::numeric_limits<unsigned>::max());
+ VersionTuple Max = VersionTuple(0);
+ VersionTuple MinValue = Min;
+ llvm::DenseMap<VersionTuple, VersionTuple> Mapping;
+ for (const auto &KV : Obj) {
+ if (auto Val = KV.getSecond().getAsString()) {
+ llvm::VersionTuple KeyVersion;
+ llvm::VersionTuple ValueVersion;
+ if (KeyVersion.tryParse(KV.getFirst()) || ValueVersion.tryParse(*Val))
+ return None;
+ Mapping[KeyVersion.normalize()] = ValueVersion;
+ if (KeyVersion < Min)
+ Min = KeyVersion;
+ if (KeyVersion > Max)
+ Max = KeyVersion;
+ if (ValueVersion < MinValue)
+ MinValue = ValueVersion;
+ }
+ }
+ if (Mapping.empty())
+ return None;
+ return RelatedTargetVersionMapping(
+ Min, Max, MinValue, MaximumDeploymentTarget, std::move(Mapping));
+}
+
+static Optional<VersionTuple> getVersionKey(const llvm::json::Object &Obj,
+ StringRef Key) {
+ auto Value = Obj.getString(Key);
+ if (!Value)
+ return None;
+ VersionTuple Version;
+ if (Version.tryParse(*Value))
+ return None;
+ return Version;
+}
+
+Optional<DarwinSDKInfo>
+DarwinSDKInfo::parseDarwinSDKSettingsJSON(const llvm::json::Object *Obj) {
+ auto Version = getVersionKey(*Obj, "Version");
+ if (!Version)
+ return None;
+ auto MaximumDeploymentVersion =
+ getVersionKey(*Obj, "MaximumDeploymentTarget");
+ if (!MaximumDeploymentVersion)
+ return None;
+ llvm::DenseMap<OSEnvPair::StorageType, Optional<RelatedTargetVersionMapping>>
+ VersionMappings;
+ if (const auto *VM = Obj->getObject("VersionMap")) {
+ if (const auto *Mapping = VM->getObject("macOS_iOSMac")) {
+ auto VersionMap = RelatedTargetVersionMapping::parseJSON(
+ *Mapping, *MaximumDeploymentVersion);
+ if (!VersionMap)
+ return None;
+ VersionMappings[OSEnvPair::macOStoMacCatalystPair().Value] =
+ std::move(VersionMap);
+ }
+ if (const auto *Mapping = VM->getObject("iOSMac_macOS")) {
+ auto VersionMap = RelatedTargetVersionMapping::parseJSON(
+ *Mapping, *MaximumDeploymentVersion);
+ if (!VersionMap)
+ return None;
+ VersionMappings[OSEnvPair::macCatalystToMacOSPair().Value] =
+ std::move(VersionMap);
+ }
+ }
+
+ return DarwinSDKInfo(std::move(*Version),
+ std::move(*MaximumDeploymentVersion),
+ std::move(VersionMappings));
+}
+
+Expected<Optional<DarwinSDKInfo>>
+clang::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) {
+ llvm::SmallString<256> Filepath = SDKRootPath;
+ llvm::sys::path::append(Filepath, "SDKSettings.json");
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ VFS.getBufferForFile(Filepath);
+ if (!File) {
+ // If the file couldn't be read, assume it just doesn't exist.
+ return None;
+ }
+ Expected<llvm::json::Value> Result =
+ llvm::json::parse(File.get()->getBuffer());
+ if (!Result)
+ return Result.takeError();
+
+ if (const auto *Obj = Result->getAsObject()) {
+ if (auto SDKInfo = DarwinSDKInfo::parseDarwinSDKSettingsJSON(Obj))
+ return std::move(SDKInfo);
+ }
+ return llvm::make_error<llvm::StringError>("invalid SDKSettings.json",
+ llvm::inconvertibleErrorCode());
+}
diff --git a/src/llvm-project/clang/lib/Basic/DiagnosticIDs.cpp b/src/llvm-project/clang/lib/Basic/DiagnosticIDs.cpp
index 06a8e2e..c333076 100644
--- a/src/llvm-project/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/src/llvm-project/clang/lib/Basic/DiagnosticIDs.cpp
@@ -109,15 +109,15 @@
struct StaticDiagInfoRec {
uint16_t DiagID;
- unsigned DefaultSeverity : 3;
- unsigned Class : 3;
- unsigned SFINAE : 2;
- unsigned WarnNoWerror : 1;
- unsigned WarnShowInSystemHeader : 1;
- unsigned Deferrable : 1;
- unsigned Category : 6;
+ uint8_t DefaultSeverity : 3;
+ uint8_t Class : 3;
+ uint8_t SFINAE : 2;
+ uint8_t Category : 6;
+ uint8_t WarnNoWerror : 1;
+ uint8_t WarnShowInSystemHeader : 1;
- uint16_t OptionGroupIndex;
+ uint16_t OptionGroupIndex : 15;
+ uint16_t Deferrable : 1;
uint16_t DescriptionLen;
@@ -168,20 +168,20 @@
#undef STRINGIFY_NAME
const StaticDiagInfoRec StaticDiagInfo[] = {
+// clang-format off
#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \
{ \
diag::ENUM, \
DEFAULT_SEVERITY, \
CLASS, \
DiagnosticIDs::SFINAE, \
+ CATEGORY, \
NOWERROR, \
SHOWINSYSHEADER, \
- DEFERRABLE, \
- CATEGORY, \
GROUP, \
+ DEFERRABLE, \
STR_SIZE(DESC, uint16_t)},
-// clang-format off
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
@@ -194,7 +194,7 @@
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#include "clang/Basic/DiagnosticRefactoringKinds.inc"
- // clang-format on
+// clang-format on
#undef DIAG
};
diff --git a/src/llvm-project/clang/lib/Basic/FileManager.cpp b/src/llvm-project/clang/lib/Basic/FileManager.cpp
index 6e9d5d7..74cd2f2 100644
--- a/src/llvm-project/clang/lib/Basic/FileManager.cpp
+++ b/src/llvm-project/clang/lib/Basic/FileManager.cpp
@@ -128,7 +128,7 @@
// Stat("C:") does not recognize "C:" as a valid directory
std::string DirNameStr;
if (DirName.size() > 1 && DirName.back() == ':' &&
- DirName.equals_lower(llvm::sys::path::root_name(DirName))) {
+ DirName.equals_insensitive(llvm::sys::path::root_name(DirName))) {
DirNameStr = DirName.str() + '.';
DirName = DirNameStr;
}
@@ -384,9 +384,12 @@
// Now that all ancestors of Filename are in the cache, the
// following call is guaranteed to find the DirectoryEntry from the
- // cache.
- auto DirInfo = expectedToOptional(
- getDirectoryFromFile(*this, Filename, /*CacheFailure=*/true));
+ // cache. A virtual file can also have an empty filename, that could come
+ // from a source location preprocessor directive with an empty filename as
+ // an example, so we need to pretend it has a name to ensure a valid directory
+ // entry can be returned.
+ auto DirInfo = expectedToOptional(getDirectoryFromFile(
+ *this, Filename.empty() ? "." : Filename, /*CacheFailure=*/true));
assert(DirInfo &&
"The directory of a virtual file should already be in the cache.");
@@ -608,7 +611,7 @@
SmallString<4096> CanonicalNameBuf;
if (!FS->getRealPath(Dir->getName(), CanonicalNameBuf))
- CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
+ CanonicalName = CanonicalNameBuf.str().copy(CanonicalNameStorage);
CanonicalNames.insert({Dir, CanonicalName});
return CanonicalName;
@@ -624,7 +627,7 @@
SmallString<4096> CanonicalNameBuf;
if (!FS->getRealPath(File->getName(), CanonicalNameBuf))
- CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
+ CanonicalName = CanonicalNameBuf.str().copy(CanonicalNameStorage);
CanonicalNames.insert({File, CanonicalName});
return CanonicalName;
diff --git a/src/llvm-project/clang/lib/Basic/IdentifierTable.cpp b/src/llvm-project/clang/lib/Basic/IdentifierTable.cpp
index 51c6e02..d811aee 100644
--- a/src/llvm-project/clang/lib/Basic/IdentifierTable.cpp
+++ b/src/llvm-project/clang/lib/Basic/IdentifierTable.cpp
@@ -107,8 +107,9 @@
KEYCXX20 = 0x200000,
KEYOPENCLCXX = 0x400000,
KEYMSCOMPAT = 0x800000,
+ KEYSYCL = 0x1000000,
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
- KEYALL = (0xffffff & ~KEYNOMS18 &
+ KEYALL = (0x1ffffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
@@ -155,6 +156,8 @@
if (LangOpts.CPlusPlus && (Flags & KEYALLCXX)) return KS_Future;
if (LangOpts.CPlusPlus && !LangOpts.CPlusPlus20 && (Flags & CHAR8SUPPORT))
return KS_Future;
+ if (LangOpts.isSYCL() && (Flags & KEYSYCL))
+ return KS_Enabled;
return KS_Disabled;
}
@@ -227,6 +230,9 @@
if (LangOpts.DeclSpecKeyword)
AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
+ if (LangOpts.IEEE128)
+ AddKeyword("__ieee128", tok::kw___float128, KEYALL, LangOpts, *this);
+
// Add the 'import' contextual keyword.
get("import").setModulesImport(true);
}
@@ -270,6 +276,39 @@
return !isKeyword(LangOptsNoCPP);
}
+ReservedIdentifierStatus
+IdentifierInfo::isReserved(const LangOptions &LangOpts) const {
+ StringRef Name = getName();
+
+ // '_' is a reserved identifier, but its use is so common (e.g. to store
+ // ignored values) that we don't warn on it.
+ if (Name.size() <= 1)
+ return ReservedIdentifierStatus::NotReserved;
+
+ // [lex.name] p3
+ if (Name[0] == '_') {
+
+ // Each name that begins with an underscore followed by an uppercase letter
+ // or another underscore is reserved.
+ if (Name[1] == '_')
+ return ReservedIdentifierStatus::StartsWithDoubleUnderscore;
+
+ if ('A' <= Name[1] && Name[1] <= 'Z')
+ return ReservedIdentifierStatus::
+ StartsWithUnderscoreFollowedByCapitalLetter;
+
+ // This is a bit misleading: it actually means it's only reserved if we're
+ // at global scope because it starts with an underscore.
+ return ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope;
+ }
+
+ // Each name that contains a double underscore (__) is reserved.
+ if (LangOpts.CPlusPlus && Name.contains("__"))
+ return ReservedIdentifierStatus::ContainsDoubleUnderscore;
+
+ return ReservedIdentifierStatus::NotReserved;
+}
+
tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
// We use a perfect hash function here involving the length of the keyword,
// the first and third character. For preprocessor ID's there are no
@@ -305,9 +344,11 @@
CASE( 6, 'p', 'a', pragma);
CASE( 7, 'd', 'f', defined);
+ CASE( 7, 'e', 'i', elifdef);
CASE( 7, 'i', 'c', include);
CASE( 7, 'w', 'r', warning);
+ CASE( 8, 'e', 'i', elifndef);
CASE( 8, 'u', 'a', unassert);
CASE(12, 'i', 'c', include_next);
diff --git a/src/llvm-project/clang/lib/Basic/LangOptions.cpp b/src/llvm-project/clang/lib/Basic/LangOptions.cpp
index ed275ad..bebf317 100644
--- a/src/llvm-project/clang/lib/Basic/LangOptions.cpp
+++ b/src/llvm-project/clang/lib/Basic/LangOptions.cpp
@@ -11,6 +11,8 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Path.h"
using namespace clang;
@@ -28,7 +30,7 @@
#include "clang/Basic/LangOptions.def"
// These options do not affect AST generation.
- SanitizerBlacklistFiles.clear();
+ NoSanitizeFiles.clear();
XRayAlwaysInstrumentFiles.clear();
XRayNeverInstrumentFiles.clear();
@@ -48,6 +50,12 @@
return VersionTuple(Ver / 100, (Ver % 100) / 10);
}
+void LangOptions::remapPathPrefix(SmallString<256> &Path) const {
+ for (const auto &Entry : MacroPrefixMap)
+ if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
+ break;
+}
+
FPOptions FPOptions::defaultWithoutTrailingStorage(const LangOptions &LO) {
FPOptions result(LO);
return result;
diff --git a/src/llvm-project/clang/lib/Basic/Module.cpp b/src/llvm-project/clang/lib/Basic/Module.cpp
index 2dd53b0..b6cf162 100644
--- a/src/llvm-project/clang/lib/Basic/Module.cpp
+++ b/src/llvm-project/clang/lib/Basic/Module.cpp
@@ -245,12 +245,10 @@
Module::DirectoryName Module::getUmbrellaDir() const {
if (Header U = getUmbrellaHeader())
- return {"", U.Entry->getDir()};
+ return {"", "", U.Entry->getDir()};
- if (auto *ME = Umbrella.dyn_cast<const DirectoryEntryRef::MapEntry *>())
- return {UmbrellaAsWritten, DirectoryEntryRef(*ME)};
-
- return {"", None};
+ return {UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory,
+ Umbrella.dyn_cast<const DirectoryEntry *>()};
}
void Module::addTopHeader(const FileEntry *File) {
@@ -432,7 +430,7 @@
}
}
-void Module::print(raw_ostream &OS, unsigned Indent) const {
+void Module::print(raw_ostream &OS, unsigned Indent, bool Dump) const {
OS.indent(Indent);
if (IsFramework)
OS << "framework ";
@@ -538,7 +536,7 @@
// the module. Regular inferred submodules are OK, as we need to look at all
// those header files anyway.
if (!(*MI)->IsInferred || (*MI)->IsFramework)
- (*MI)->print(OS, Indent + 2);
+ (*MI)->print(OS, Indent + 2, Dump);
for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
OS.indent(Indent + 2);
@@ -562,6 +560,13 @@
OS << "\n";
}
+ if (Dump) {
+ for (Module *M : Imports) {
+ OS.indent(Indent + 2);
+ llvm::errs() << "import " << M->getFullModuleName() << "\n";
+ }
+ }
+
for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) {
OS.indent(Indent + 2);
OS << "use ";
@@ -622,7 +627,7 @@
}
LLVM_DUMP_METHOD void Module::dump() const {
- print(llvm::errs());
+ print(llvm::errs(), 0, true);
}
void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
diff --git a/src/llvm-project/clang/lib/Basic/NoSanitizeList.cpp b/src/llvm-project/clang/lib/Basic/NoSanitizeList.cpp
new file mode 100644
index 0000000..3efd613
--- /dev/null
+++ b/src/llvm-project/clang/lib/Basic/NoSanitizeList.cpp
@@ -0,0 +1,54 @@
+//===--- NoSanitizeList.cpp - Ignored list for sanitizers ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// User-provided ignore-list used to disable/alter instrumentation done in
+// sanitizers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/NoSanitizeList.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SanitizerSpecialCaseList.h"
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/SourceManager.h"
+
+using namespace clang;
+
+NoSanitizeList::NoSanitizeList(const std::vector<std::string> &NoSanitizePaths,
+ SourceManager &SM)
+ : SSCL(SanitizerSpecialCaseList::createOrDie(
+ NoSanitizePaths, SM.getFileManager().getVirtualFileSystem())),
+ SM(SM) {}
+
+NoSanitizeList::~NoSanitizeList() = default;
+
+bool NoSanitizeList::containsGlobal(SanitizerMask Mask, StringRef GlobalName,
+ StringRef Category) const {
+ return SSCL->inSection(Mask, "global", GlobalName, Category);
+}
+
+bool NoSanitizeList::containsType(SanitizerMask Mask, StringRef MangledTypeName,
+ StringRef Category) const {
+ return SSCL->inSection(Mask, "type", MangledTypeName, Category);
+}
+
+bool NoSanitizeList::containsFunction(SanitizerMask Mask,
+ StringRef FunctionName) const {
+ return SSCL->inSection(Mask, "fun", FunctionName);
+}
+
+bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
+ StringRef Category) const {
+ return SSCL->inSection(Mask, "src", FileName, Category);
+}
+
+bool NoSanitizeList::containsLocation(SanitizerMask Mask, SourceLocation Loc,
+ StringRef Category) const {
+ return Loc.isValid() &&
+ containsFile(Mask, SM.getFilename(SM.getFileLoc(Loc)), Category);
+}
diff --git a/src/llvm-project/clang/lib/Basic/OpenCLOptions.cpp b/src/llvm-project/clang/lib/Basic/OpenCLOptions.cpp
index 266acc5..b7408f3 100644
--- a/src/llvm-project/clang/lib/Basic/OpenCLOptions.cpp
+++ b/src/llvm-project/clang/lib/Basic/OpenCLOptions.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/OpenCLOptions.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetInfo.h"
namespace clang {
@@ -14,39 +16,47 @@
return OptMap.find(Ext) != OptMap.end();
}
+bool OpenCLOptions::isAvailableOption(llvm::StringRef Ext,
+ const LangOptions &LO) const {
+ if (!isKnown(Ext))
+ return false;
+
+ auto &OptInfo = OptMap.find(Ext)->getValue();
+ if (OptInfo.isCoreIn(LO) || OptInfo.isOptionalCoreIn(LO))
+ return isSupported(Ext, LO);
+
+ return isEnabled(Ext);
+}
+
bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
+ auto I = OptMap.find(Ext);
+ return I != OptMap.end() && I->getValue().Enabled;
+}
+
+bool OpenCLOptions::isWithPragma(llvm::StringRef Ext) const {
auto E = OptMap.find(Ext);
- return E != OptMap.end() && E->second.Enabled;
+ return E != OptMap.end() && E->second.WithPragma;
}
bool OpenCLOptions::isSupported(llvm::StringRef Ext,
const LangOptions &LO) const {
- auto E = OptMap.find(Ext);
- if (E == OptMap.end()) {
- return false;
- }
- auto I = OptMap.find(Ext)->getValue();
- return I.Supported && I.isAvailableIn(LO);
+ auto I = OptMap.find(Ext);
+ return I != OptMap.end() && I->getValue().Supported &&
+ I->getValue().isAvailableIn(LO);
}
bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext,
const LangOptions &LO) const {
- auto E = OptMap.find(Ext);
- if (E == OptMap.end()) {
- return false;
- }
- auto I = OptMap.find(Ext)->getValue();
- return I.Supported && I.isCoreIn(LO);
+ auto I = OptMap.find(Ext);
+ return I != OptMap.end() && I->getValue().Supported &&
+ I->getValue().isCoreIn(LO);
}
bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext,
const LangOptions &LO) const {
- auto E = OptMap.find(Ext);
- if (E == OptMap.end()) {
- return false;
- }
- auto I = OptMap.find(Ext)->getValue();
- return I.Supported && I.isOptionalCoreIn(LO);
+ auto I = OptMap.find(Ext);
+ return I != OptMap.end() && I->getValue().Supported &&
+ I->getValue().isOptionalCoreIn(LO);
}
bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
@@ -56,12 +66,9 @@
bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext,
const LangOptions &LO) const {
- auto E = OptMap.find(Ext);
- if (E == OptMap.end()) {
- return false;
- }
- auto I = OptMap.find(Ext)->getValue();
- return I.Supported && I.isAvailableIn(LO) &&
+ auto I = OptMap.find(Ext);
+ return I != OptMap.end() && I->getValue().Supported &&
+ I->getValue().isAvailableIn(LO) &&
!isSupportedCoreOrOptionalCore(Ext, LO);
}
@@ -69,6 +76,10 @@
OptMap[Ext].Enabled = V;
}
+void OpenCLOptions::acceptsPragma(llvm::StringRef Ext, bool V) {
+ OptMap[Ext].WithPragma = V;
+}
+
void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
assert(!Ext.empty() && "Extension is empty.");
assert(Ext[0] != '+' && Ext[0] != '-');
@@ -76,10 +87,8 @@
}
OpenCLOptions::OpenCLOptions() {
-#define OPENCL_GENERIC_EXTENSION(Ext, AvailVer, CoreVer, OptVer) \
- OptMap[#Ext].Avail = AvailVer; \
- OptMap[#Ext].Core = CoreVer; \
- OptMap[#Ext].Opt = OptVer;
+#define OPENCL_GENERIC_EXTENSION(Ext, ...) \
+ OptMap.insert_or_assign(#Ext, OpenCLOptionInfo{__VA_ARGS__});
#include "clang/Basic/OpenCLExtensions.def"
}
@@ -97,10 +106,46 @@
Opt.getValue().Enabled = false;
}
-void OpenCLOptions::enableSupportedCore(const LangOptions &LO) {
- for (auto &Opt : OptMap)
- if (isSupportedCoreOrOptionalCore(Opt.getKey(), LO))
- Opt.getValue().Enabled = true;
+bool OpenCLOptions::diagnoseUnsupportedFeatureDependencies(
+ const TargetInfo &TI, DiagnosticsEngine &Diags) {
+ // Feature pairs. First feature in a pair requires the second one to be
+ // supported.
+ static const llvm::StringMap<llvm::StringRef> DependentFeaturesMap = {
+ {"__opencl_c_read_write_images", "__opencl_c_images"},
+ {"__opencl_c_3d_image_writes", "__opencl_c_images"},
+ {"__opencl_c_pipes", "__opencl_c_generic_address_space"}};
+
+ auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
+
+ bool IsValid = true;
+ for (auto &FeaturePair : DependentFeaturesMap)
+ if (TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getKey()) &&
+ !TI.hasFeatureEnabled(OpenCLFeaturesMap, FeaturePair.getValue())) {
+ IsValid = false;
+ Diags.Report(diag::err_opencl_feature_requires)
+ << FeaturePair.getKey() << FeaturePair.getValue();
+ }
+ return IsValid;
+}
+
+bool OpenCLOptions::diagnoseFeatureExtensionDifferences(
+ const TargetInfo &TI, DiagnosticsEngine &Diags) {
+ // Extensions and equivalent feature pairs.
+ static const llvm::StringMap<llvm::StringRef> FeatureExtensionMap = {
+ {"cl_khr_fp64", "__opencl_c_fp64"},
+ {"cl_khr_3d_image_writes", "__opencl_c_3d_image_writes"}};
+
+ auto OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
+
+ bool IsValid = true;
+ for (auto &ExtAndFeat : FeatureExtensionMap)
+ if (TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getKey()) !=
+ TI.hasFeatureEnabled(OpenCLFeaturesMap, ExtAndFeat.getValue())) {
+ IsValid = false;
+ Diags.Report(diag::err_opencl_extension_and_feature_differs)
+ << ExtAndFeat.getKey() << ExtAndFeat.getValue();
+ }
+ return IsValid;
}
} // end namespace clang
diff --git a/src/llvm-project/clang/lib/Basic/OpenMPKinds.cpp b/src/llvm-project/clang/lib/Basic/OpenMPKinds.cpp
index 5c19d60..cfdba09 100644
--- a/src/llvm-project/clang/lib/Basic/OpenMPKinds.cpp
+++ b/src/llvm-project/clang/lib/Basic/OpenMPKinds.cpp
@@ -130,6 +130,7 @@
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
@@ -175,6 +176,8 @@
case OMPC_match:
case OMPC_nontemporal:
case OMPC_destroy:
+ case OMPC_novariants:
+ case OMPC_nocontext:
case OMPC_detach:
case OMPC_inclusive:
case OMPC_exclusive:
@@ -370,6 +373,7 @@
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
@@ -416,6 +420,8 @@
case OMPC_nontemporal:
case OMPC_destroy:
case OMPC_detach:
+ case OMPC_novariants:
+ case OMPC_nocontext:
case OMPC_inclusive:
case OMPC_exclusive:
case OMPC_uses_allocators:
@@ -446,7 +452,8 @@
DKind == OMPD_target_teams_distribute ||
DKind == OMPD_target_teams_distribute_parallel_for ||
DKind == OMPD_target_teams_distribute_parallel_for_simd ||
- DKind == OMPD_target_teams_distribute_simd;
+ DKind == OMPD_target_teams_distribute_simd || DKind == OMPD_tile ||
+ DKind == OMPD_unroll;
}
bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
@@ -573,6 +580,10 @@
Kind == OMPD_target_teams_distribute_parallel_for_simd;
}
+bool clang::isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_tile || DKind == OMPD_unroll;
+}
+
void clang::getOpenMPCaptureRegions(
SmallVectorImpl<OpenMPDirectiveKind> &CaptureRegions,
OpenMPDirectiveKind DKind) {
@@ -654,8 +665,13 @@
case OMPD_atomic:
case OMPD_target_data:
case OMPD_distribute_simd:
+ case OMPD_dispatch:
CaptureRegions.push_back(OMPD_unknown);
break;
+ case OMPD_tile:
+ case OMPD_unroll:
+ // loop transformations do not introduce captures.
+ break;
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
diff --git a/src/llvm-project/clang/lib/Basic/SanitizerBlacklist.cpp b/src/llvm-project/clang/lib/Basic/SanitizerBlacklist.cpp
deleted file mode 100644
index feb7cbd..0000000
--- a/src/llvm-project/clang/lib/Basic/SanitizerBlacklist.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//===--- SanitizerBlacklist.cpp - Blacklist for sanitizers ----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// User-provided blacklist used to disable/alter instrumentation done in
-// sanitizers.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Basic/SanitizerBlacklist.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/SanitizerSpecialCaseList.h"
-#include "clang/Basic/Sanitizers.h"
-#include "clang/Basic/SourceManager.h"
-
-using namespace clang;
-
-SanitizerBlacklist::SanitizerBlacklist(
- const std::vector<std::string> &BlacklistPaths, SourceManager &SM)
- : SSCL(SanitizerSpecialCaseList::createOrDie(
- BlacklistPaths, SM.getFileManager().getVirtualFileSystem())),
- SM(SM) {}
-
-SanitizerBlacklist::~SanitizerBlacklist() = default;
-
-bool SanitizerBlacklist::isBlacklistedGlobal(SanitizerMask Mask,
- StringRef GlobalName,
- StringRef Category) const {
- return SSCL->inSection(Mask, "global", GlobalName, Category);
-}
-
-bool SanitizerBlacklist::isBlacklistedType(SanitizerMask Mask,
- StringRef MangledTypeName,
- StringRef Category) const {
- return SSCL->inSection(Mask, "type", MangledTypeName, Category);
-}
-
-bool SanitizerBlacklist::isBlacklistedFunction(SanitizerMask Mask,
- StringRef FunctionName) const {
- return SSCL->inSection(Mask, "fun", FunctionName);
-}
-
-bool SanitizerBlacklist::isBlacklistedFile(SanitizerMask Mask,
- StringRef FileName,
- StringRef Category) const {
- return SSCL->inSection(Mask, "src", FileName, Category);
-}
-
-bool SanitizerBlacklist::isBlacklistedLocation(SanitizerMask Mask,
- SourceLocation Loc,
- StringRef Category) const {
- return Loc.isValid() &&
- isBlacklistedFile(Mask, SM.getFilename(SM.getFileLoc(Loc)), Category);
-}
-
diff --git a/src/llvm-project/clang/lib/Basic/Sanitizers.cpp b/src/llvm-project/clang/lib/Basic/Sanitizers.cpp
index f5f81b5..7d903c8 100644
--- a/src/llvm-project/clang/lib/Basic/Sanitizers.cpp
+++ b/src/llvm-project/clang/lib/Basic/Sanitizers.cpp
@@ -12,7 +12,9 @@
#include "clang/Basic/Sanitizers.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/MathExtras.h"
using namespace clang;
@@ -34,6 +36,14 @@
return ParsedKind;
}
+void clang::serializeSanitizerSet(SanitizerSet Set,
+ SmallVectorImpl<StringRef> &Values) {
+#define SANITIZER(NAME, ID) \
+ if (Set.has(SanitizerKind::ID)) \
+ Values.push_back(NAME);
+#include "clang/Basic/Sanitizers.def"
+}
+
SanitizerMask clang::expandSanitizerGroups(SanitizerMask Kinds) {
#define SANITIZER(NAME, ID)
#define SANITIZER_GROUP(NAME, ID, ALIAS) \
@@ -48,7 +58,58 @@
}
namespace clang {
+unsigned SanitizerMask::countPopulation() const {
+ unsigned total = 0;
+ for (const auto &Val : maskLoToHigh)
+ total += llvm::countPopulation(Val);
+ return total;
+}
+
llvm::hash_code hash_value(const clang::SanitizerMask &Arg) {
return Arg.hash_value();
}
+
+StringRef AsanDtorKindToString(llvm::AsanDtorKind kind) {
+ switch (kind) {
+ case llvm::AsanDtorKind::None:
+ return "none";
+ case llvm::AsanDtorKind::Global:
+ return "global";
+ case llvm::AsanDtorKind::Invalid:
+ return "invalid";
+ }
+ return "invalid";
+}
+
+llvm::AsanDtorKind AsanDtorKindFromString(StringRef kindStr) {
+ return llvm::StringSwitch<llvm::AsanDtorKind>(kindStr)
+ .Case("none", llvm::AsanDtorKind::None)
+ .Case("global", llvm::AsanDtorKind::Global)
+ .Default(llvm::AsanDtorKind::Invalid);
+}
+
+StringRef AsanDetectStackUseAfterReturnModeToString(
+ llvm::AsanDetectStackUseAfterReturnMode mode) {
+ switch (mode) {
+ case llvm::AsanDetectStackUseAfterReturnMode::Always:
+ return "always";
+ case llvm::AsanDetectStackUseAfterReturnMode::Runtime:
+ return "runtime";
+ case llvm::AsanDetectStackUseAfterReturnMode::Never:
+ return "never";
+ case llvm::AsanDetectStackUseAfterReturnMode::Invalid:
+ return "invalid";
+ }
+ return "invalid";
+}
+
+llvm::AsanDetectStackUseAfterReturnMode
+AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr) {
+ return llvm::StringSwitch<llvm::AsanDetectStackUseAfterReturnMode>(modeStr)
+ .Case("always", llvm::AsanDetectStackUseAfterReturnMode::Always)
+ .Case("runtime", llvm::AsanDetectStackUseAfterReturnMode::Runtime)
+ .Case("never", llvm::AsanDetectStackUseAfterReturnMode::Never)
+ .Default(llvm::AsanDetectStackUseAfterReturnMode::Invalid);
+}
+
} // namespace clang
diff --git a/src/llvm-project/clang/lib/Basic/SourceLocation.cpp b/src/llvm-project/clang/lib/Basic/SourceLocation.cpp
index 6f64120..6986fcd 100644
--- a/src/llvm-project/clang/lib/Basic/SourceLocation.cpp
+++ b/src/llvm-project/clang/lib/Basic/SourceLocation.cpp
@@ -51,7 +51,7 @@
"used in unions");
unsigned SourceLocation::getHashValue() const {
- return llvm::DenseMapInfo<unsigned>::getHashValue(ID);
+ return llvm::DenseMapInfo<UIntTy>::getHashValue(ID);
}
void llvm::FoldingSetTrait<SourceLocation>::Profile(
diff --git a/src/llvm-project/clang/lib/Basic/SourceManager.cpp b/src/llvm-project/clang/lib/Basic/SourceManager.cpp
index c0b2283..8cba379 100644
--- a/src/llvm-project/clang/lib/Basic/SourceManager.cpp
+++ b/src/llvm-project/clang/lib/Basic/SourceManager.cpp
@@ -26,6 +26,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Capacity.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MathExtras.h"
@@ -449,9 +450,9 @@
return LoadedSLocEntryTable[Index];
}
-std::pair<int, unsigned>
+std::pair<int, SourceLocation::UIntTy>
SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
- unsigned TotalSize) {
+ SourceLocation::UIntTy TotalSize) {
assert(ExternalSLocEntries && "Don't have an external sloc source");
// Make sure we're not about to run out of source locations.
if (CurrentLoadedOffset - TotalSize < NextLocalOffset)
@@ -531,7 +532,8 @@
FileID SourceManager::createFileID(const FileEntry *SourceFile,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID, unsigned LoadedOffset) {
+ int LoadedID,
+ SourceLocation::UIntTy LoadedOffset) {
return createFileID(SourceFile->getLastRef(), IncludePos, FileCharacter,
LoadedID, LoadedOffset);
}
@@ -539,7 +541,8 @@
FileID SourceManager::createFileID(FileEntryRef SourceFile,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID, unsigned LoadedOffset) {
+ int LoadedID,
+ SourceLocation::UIntTy LoadedOffset) {
SrcMgr::ContentCache &IR = getOrCreateContentCache(SourceFile,
isSystem(FileCharacter));
@@ -558,7 +561,8 @@
/// MemoryBuffer, so only pass a MemoryBuffer to this once.
FileID SourceManager::createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID, unsigned LoadedOffset,
+ int LoadedID,
+ SourceLocation::UIntTy LoadedOffset,
SourceLocation IncludeLoc) {
StringRef Name = Buffer->getBufferIdentifier();
return createFileIDImpl(createMemBufferContentCache(std::move(Buffer)), Name,
@@ -571,7 +575,8 @@
/// outlive the SourceManager.
FileID SourceManager::createFileID(const llvm::MemoryBufferRef &Buffer,
SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID, unsigned LoadedOffset,
+ int LoadedID,
+ SourceLocation::UIntTy LoadedOffset,
SourceLocation IncludeLoc) {
return createFileID(llvm::MemoryBuffer::getMemBuffer(Buffer), FileCharacter,
LoadedID, LoadedOffset, IncludeLoc);
@@ -593,7 +598,8 @@
FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
- int LoadedID, unsigned LoadedOffset) {
+ int LoadedID,
+ SourceLocation::UIntTy LoadedOffset) {
if (LoadedID < 0) {
assert(LoadedID != -1 && "Loading sentinel FileID");
unsigned Index = unsigned(-LoadedID) - 2;
@@ -632,14 +638,11 @@
return createExpansionLocImpl(Info, TokLength);
}
-SourceLocation
-SourceManager::createExpansionLoc(SourceLocation SpellingLoc,
- SourceLocation ExpansionLocStart,
- SourceLocation ExpansionLocEnd,
- unsigned TokLength,
- bool ExpansionIsTokenRange,
- int LoadedID,
- unsigned LoadedOffset) {
+SourceLocation SourceManager::createExpansionLoc(
+ SourceLocation SpellingLoc, SourceLocation ExpansionLocStart,
+ SourceLocation ExpansionLocEnd, unsigned TokLength,
+ bool ExpansionIsTokenRange, int LoadedID,
+ SourceLocation::UIntTy LoadedOffset) {
ExpansionInfo Info = ExpansionInfo::create(
SpellingLoc, ExpansionLocStart, ExpansionLocEnd, ExpansionIsTokenRange);
return createExpansionLocImpl(Info, TokLength, LoadedID, LoadedOffset);
@@ -657,9 +660,8 @@
SourceLocation
SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
- unsigned TokLength,
- int LoadedID,
- unsigned LoadedOffset) {
+ unsigned TokLength, int LoadedID,
+ SourceLocation::UIntTy LoadedOffset) {
if (LoadedID < 0) {
assert(LoadedID != -1 && "Loading sentinel FileID");
unsigned Index = unsigned(-LoadedID) - 2;
@@ -761,7 +763,7 @@
/// This is the cache-miss path of getFileID. Not as hot as that function, but
/// still very important. It is responsible for finding the entry in the
/// SLocEntry tables that contains the specified location.
-FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
+FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const {
if (!SLocOffset)
return FileID::get(0);
@@ -776,7 +778,7 @@
///
/// This function knows that the SourceLocation is in a local buffer, not a
/// loaded one.
-FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const {
+FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
assert(SLocOffset < NextLocalOffset && "Bad function choice");
// After the first and second level caches, I see two common sorts of
@@ -827,7 +829,8 @@
NumProbes = 0;
while (true) {
unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
- unsigned MidOffset = getLocalSLocEntry(MiddleIndex).getOffset();
+ SourceLocation::UIntTy MidOffset =
+ getLocalSLocEntry(MiddleIndex).getOffset();
++NumProbes;
@@ -858,7 +861,7 @@
///
/// This function knows that the SourceLocation is in a loaded buffer, not a
/// local one.
-FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const {
+FileID SourceManager::getFileIDLoaded(SourceLocation::UIntTy SLocOffset) const {
// Sanity checking, otherwise a bug may lead to hanging in release build.
if (SLocOffset < CurrentLoadedOffset) {
assert(0 && "Invalid SLocOffset or bad function choice");
@@ -1252,12 +1255,22 @@
return PLoc.getColumn();
}
-#ifdef __SSE2__
-#include <emmintrin.h>
-#endif
+// Check if mutli-byte word x has bytes between m and n, included. This may also
+// catch bytes equal to n + 1.
+// The returned value holds a 0x80 at each byte position that holds a match.
+// see http://graphics.stanford.edu/~seander/bithacks.html#HasBetweenInWord
+template <class T>
+static constexpr inline T likelyhasbetween(T x, unsigned char m,
+ unsigned char n) {
+ return ((x - ~static_cast<T>(0) / 255 * (n + 1)) & ~x &
+ ((x & ~static_cast<T>(0) / 255 * 127) +
+ (~static_cast<T>(0) / 255 * (127 - (m - 1))))) &
+ ~static_cast<T>(0) / 255 * 128;
+}
LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer,
llvm::BumpPtrAllocator &Alloc) {
+
// Find the file offsets of all of the *physical* source lines. This does
// not look at trigraphs, escaped newlines, or anything else tricky.
SmallVector<unsigned, 256> LineOffsets;
@@ -1268,7 +1281,43 @@
const unsigned char *Buf = (const unsigned char *)Buffer.getBufferStart();
const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd();
const std::size_t BufLen = End - Buf;
+
unsigned I = 0;
+ uint64_t Word;
+
+ // scan sizeof(Word) bytes at a time for new lines.
+ // This is much faster than scanning each byte independently.
+ if (BufLen > sizeof(Word)) {
+ do {
+ Word = llvm::support::endian::read64(Buf + I, llvm::support::little);
+ // no new line => jump over sizeof(Word) bytes.
+ auto Mask = likelyhasbetween(Word, '\n', '\r');
+ if (!Mask) {
+ I += sizeof(Word);
+ continue;
+ }
+
+ // At that point, Mask contains 0x80 set at each byte that holds a value
+ // in [\n, \r + 1 [
+
+ // Scan for the next newline - it's very likely there's one.
+ unsigned N =
+ llvm::countTrailingZeros(Mask) - 7; // -7 because 0x80 is the marker
+ Word >>= N;
+ I += N / 8 + 1;
+ unsigned char Byte = Word;
+ if (Byte == '\n') {
+ LineOffsets.push_back(I);
+ } else if (Byte == '\r') {
+ // If this is \r\n, skip both characters.
+ if (Buf[I] == '\n')
+ ++I;
+ LineOffsets.push_back(I);
+ }
+ } while (I < BufLen - sizeof(Word) - 1);
+ }
+
+ // Handle tail using a regular check.
while (I < BufLen) {
if (Buf[I] == '\n') {
LineOffsets.push_back(I + 1);
@@ -1572,7 +1621,7 @@
return 0;
int ID = FID.ID;
- unsigned NextOffset;
+ SourceLocation::UIntTy NextOffset;
if ((ID > 0 && unsigned(ID+1) == local_sloc_entry_size()))
NextOffset = getNextLocalOffset();
else if (ID+1 == -1)
@@ -1780,8 +1829,8 @@
SourceLocation ExpansionLoc,
unsigned ExpansionLength) const {
if (!SpellLoc.isFileID()) {
- unsigned SpellBeginOffs = SpellLoc.getOffset();
- unsigned SpellEndOffs = SpellBeginOffs + ExpansionLength;
+ SourceLocation::UIntTy SpellBeginOffs = SpellLoc.getOffset();
+ SourceLocation::UIntTy SpellEndOffs = SpellBeginOffs + ExpansionLength;
// The spelling range for this macro argument expansion can span multiple
// consecutive FileID entries. Go through each entry contained in the
@@ -1793,9 +1842,9 @@
std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc);
while (true) {
const SLocEntry &Entry = getSLocEntry(SpellFID);
- unsigned SpellFIDBeginOffs = Entry.getOffset();
+ SourceLocation::UIntTy SpellFIDBeginOffs = Entry.getOffset();
unsigned SpellFIDSize = getFileIDSize(SpellFID);
- unsigned SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
+ SourceLocation::UIntTy SpellFIDEndOffs = SpellFIDBeginOffs + SpellFIDSize;
const ExpansionInfo &Info = Entry.getExpansion();
if (Info.isMacroArgExpansion()) {
unsigned CurrSpellLength;
@@ -1887,7 +1936,7 @@
--I;
- unsigned MacroArgBeginOffs = I->first;
+ SourceLocation::UIntTy MacroArgBeginOffs = I->first;
SourceLocation MacroArgExpandedLoc = I->second;
if (MacroArgExpandedLoc.isValid())
return MacroArgExpandedLoc.getLocWithOffset(Offset - MacroArgBeginOffs);
@@ -2107,7 +2156,7 @@
llvm::raw_ostream &out = llvm::errs();
auto DumpSLocEntry = [&](int ID, const SrcMgr::SLocEntry &Entry,
- llvm::Optional<unsigned> NextStart) {
+ llvm::Optional<SourceLocation::UIntTy> NextStart) {
out << "SLocEntry <FileID " << ID << "> " << (Entry.isFile() ? "file" : "expansion")
<< " <SourceLocation " << Entry.getOffset() << ":";
if (NextStart)
@@ -2147,7 +2196,7 @@
: LocalSLocEntryTable[ID + 1].getOffset());
}
// Dump loaded SLocEntries.
- llvm::Optional<unsigned> NextStart;
+ llvm::Optional<SourceLocation::UIntTy> NextStart;
for (unsigned Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) {
int ID = -(int)Index - 2;
if (SLocEntryLoaded[Index]) {
diff --git a/src/llvm-project/clang/lib/Basic/TargetInfo.cpp b/src/llvm-project/clang/lib/Basic/TargetInfo.cpp
index 642ee75..5f8e04c 100644
--- a/src/llvm-project/clang/lib/Basic/TargetInfo.cpp
+++ b/src/llvm-project/clang/lib/Basic/TargetInfo.cpp
@@ -17,7 +17,6 @@
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/IR/DataLayout.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetParser.h"
#include <cstdlib>
@@ -67,9 +66,12 @@
// From the glibc documentation, on GNU systems, malloc guarantees 16-byte
// alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
// https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html.
- // This alignment guarantee also applies to Windows and Android.
+ // This alignment guarantee also applies to Windows and Android. On Darwin,
+ // the alignment is 16 bytes on both 64-bit and 32-bit systems.
if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid())
NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
+ else if (T.isOSDarwin())
+ NewAlign = 128;
else
NewAlign = 0; // Infer from basic type alignment.
HalfWidth = 16;
@@ -96,25 +98,30 @@
Char16Type = UnsignedShort;
Char32Type = UnsignedInt;
Int64Type = SignedLongLong;
+ Int16Type = SignedShort;
SigAtomicType = SignedInt;
ProcessIDType = SignedInt;
UseSignedCharForObjCBool = true;
UseBitFieldTypeAlignment = true;
UseZeroLengthBitfieldAlignment = false;
+ UseLeadingZeroLengthBitfield = true;
UseExplicitBitFieldAlignment = true;
ZeroLengthBitfieldBoundary = 0;
+ MaxAlignedAttribute = 0;
HalfFormat = &llvm::APFloat::IEEEhalf();
FloatFormat = &llvm::APFloat::IEEEsingle();
DoubleFormat = &llvm::APFloat::IEEEdouble();
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
Float128Format = &llvm::APFloat::IEEEquad();
MCountName = "mcount";
+ UserLabelPrefix = "_";
RegParmMax = 0;
SSERegParmMax = 0;
HasAlignMac68kSupport = false;
HasBuiltinMSVaList = false;
IsRenderScriptTarget = false;
HasAArch64SVETypes = false;
+ HasRISCVVTypes = false;
AllowAMDGPUUnsafeFPAtomics = false;
ARMCDECoprocMask = 0;
@@ -143,8 +150,9 @@
// Out of line virtual dtor for TargetInfo.
TargetInfo::~TargetInfo() {}
-void TargetInfo::resetDataLayout(StringRef DL) {
- DataLayout.reset(new llvm::DataLayout(DL));
+void TargetInfo::resetDataLayout(StringRef DL, const char *ULP) {
+ DataLayoutString = DL.str();
+ UserLabelPrefix = ULP;
}
bool
@@ -338,7 +346,7 @@
/// Apply changes to the target information with respect to certain
/// language options which change the target configuration and adjust
/// the language based on the target options where applicable.
-void TargetInfo::adjust(LangOptions &Opts) {
+void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
if (Opts.NoBitFieldTypeAlign)
UseBitFieldTypeAlignment = false;
@@ -388,6 +396,23 @@
HalfFormat = &llvm::APFloat::IEEEhalf();
FloatFormat = &llvm::APFloat::IEEEsingle();
LongDoubleFormat = &llvm::APFloat::IEEEquad();
+
+ // OpenCL C v3.0 s6.7.5 - The generic address space requires support for
+ // OpenCL C 2.0 or OpenCL C 3.0 with the __opencl_c_generic_address_space
+ // feature
+ // OpenCL C v3.0 s6.2.1 - OpenCL pipes require support of OpenCL C 2.0
+ // or later and __opencl_c_pipes feature
+ // FIXME: These language options are also defined in setLangDefaults()
+ // for OpenCL C 2.0 but with no access to target capabilities. Target
+ // should be immutable once created and thus these language options need
+ // to be defined only once.
+ if (Opts.OpenCLVersion == 300) {
+ const auto &OpenCLFeaturesMap = getSupportedOpenCLOpts();
+ Opts.OpenCLGenericAddressSpace = hasFeatureEnabled(
+ OpenCLFeaturesMap, "__opencl_c_generic_address_space");
+ Opts.OpenCLPipes =
+ hasFeatureEnabled(OpenCLFeaturesMap, "__opencl_c_pipes");
+ }
}
if (Opts.DoubleSize) {
@@ -422,6 +447,11 @@
// its corresponding signed type.
PaddingOnUnsignedFixedPoint |= Opts.PaddingOnUnsignedFixedPoint;
CheckFixedPointBits();
+
+ if (Opts.ProtectParens && !checkArithmeticFenceSupported()) {
+ Diags.Report(diag::err_opt_not_valid_on_target) << "-fprotect-parens";
+ Opts.ProtectParens = false;
+ }
}
bool TargetInfo::initFeatureMap(
@@ -472,8 +502,8 @@
/// a valid clobber in an inline asm statement. This is used by
/// Sema.
bool TargetInfo::isValidClobber(StringRef Name) const {
- return (isValidGCCRegisterName(Name) ||
- Name == "memory" || Name == "cc");
+ return (isValidGCCRegisterName(Name) || Name == "memory" || Name == "cc" ||
+ Name == "unwind");
}
/// isValidGCCRegisterName - Returns whether the passed in string
diff --git a/src/llvm-project/clang/lib/Basic/Targets.cpp b/src/llvm-project/clang/lib/Basic/Targets.cpp
index 90a67d0..ba91d04 100644
--- a/src/llvm-project/clang/lib/Basic/Targets.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets.cpp
@@ -22,6 +22,7 @@
#include "Targets/Hexagon.h"
#include "Targets/Lanai.h"
#include "Targets/Le64.h"
+#include "Targets/M68k.h"
#include "Targets/MSP430.h"
#include "Targets/Mips.h"
#include "Targets/NVPTX.h"
@@ -303,6 +304,16 @@
return new MipsTargetInfo(Triple, Opts);
}
+ case llvm::Triple::m68k:
+ switch (os) {
+ case llvm::Triple::Linux:
+ return new LinuxTargetInfo<M68kTargetInfo>(Triple, Opts);
+ case llvm::Triple::NetBSD:
+ return new NetBSDTargetInfo<M68kTargetInfo>(Triple, Opts);
+ default:
+ return new M68kTargetInfo(Triple, Opts);
+ }
+
case llvm::Triple::le32:
switch (os) {
case llvm::Triple::NaCl:
@@ -584,13 +595,13 @@
}
case llvm::Triple::spir: {
- if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ if (os != llvm::Triple::UnknownOS ||
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
return nullptr;
return new SPIR32TargetInfo(Triple, Opts);
}
case llvm::Triple::spir64: {
- if (Triple.getOS() != llvm::Triple::UnknownOS ||
+ if (os != llvm::Triple::UnknownOS ||
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
return nullptr;
return new SPIR64TargetInfo(Triple, Opts);
@@ -600,7 +611,7 @@
Triple.getVendor() != llvm::Triple::UnknownVendor ||
!Triple.isOSBinFormatWasm())
return nullptr;
- switch (Triple.getOS()) {
+ switch (os) {
case llvm::Triple::WASI:
return new WASITargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
case llvm::Triple::Emscripten:
@@ -615,7 +626,7 @@
Triple.getVendor() != llvm::Triple::UnknownVendor ||
!Triple.isOSBinFormatWasm())
return nullptr;
- switch (Triple.getOS()) {
+ switch (os) {
case llvm::Triple::WASI:
return new WASITargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
case llvm::Triple::Emscripten:
@@ -715,29 +726,28 @@
return Target.release();
}
+/// validateOpenCLTarget - Check that OpenCL target has valid
+/// options setting based on OpenCL version.
+bool TargetInfo::validateOpenCLTarget(const LangOptions &Opts,
+ DiagnosticsEngine &Diags) const {
+ const llvm::StringMap<bool> &OpenCLFeaturesMap = getSupportedOpenCLOpts();
-/// getOpenCLFeatureDefines - Define OpenCL macros based on target settings
-/// and language version
-void TargetInfo::getOpenCLFeatureDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
-
- auto defineOpenCLExtMacro = [&](llvm::StringRef Name, unsigned AvailVer,
- unsigned CoreVersions,
- unsigned OptionalVersions) {
- // Check if extension is supported by target and is available in this
- // OpenCL version
- auto It = getTargetOpts().OpenCLFeaturesMap.find(Name);
- if ((It != getTargetOpts().OpenCLFeaturesMap.end()) && It->getValue() &&
- OpenCLOptions::OpenCLOptionInfo(AvailVer, CoreVersions,
- OptionalVersions)
- .isAvailableIn(Opts))
- Builder.defineMacro(Name);
+ auto diagnoseNotSupportedCore = [&](llvm::StringRef Name, auto... OptArgs) {
+ if (OpenCLOptions::isOpenCLOptionCoreIn(Opts, OptArgs...) &&
+ !hasFeatureEnabled(OpenCLFeaturesMap, Name))
+ Diags.Report(diag::warn_opencl_unsupported_core_feature)
+ << Name << Opts.OpenCLCPlusPlus
+ << Opts.getOpenCLVersionTuple().getAsString();
};
-#define OPENCL_GENERIC_EXTENSION(Ext, Avail, Core, Opt) \
- defineOpenCLExtMacro(#Ext, Avail, Core, Opt);
+#define OPENCL_GENERIC_EXTENSION(Ext, ...) \
+ diagnoseNotSupportedCore(#Ext, __VA_ARGS__);
#include "clang/Basic/OpenCLExtensions.def"
- // FIXME: OpenCL options which affect language semantics/syntax
- // should be moved into LangOptions, thus macro definitions of
- // such options is better to be done in clang::InitializePreprocessor
+ // Validate that feature macros are set properly for OpenCL C 3.0.
+ // In other cases assume that target is always valid.
+ if (Opts.OpenCLCPlusPlus || Opts.OpenCLVersion < 300)
+ return true;
+
+ return OpenCLOptions::diagnoseUnsupportedFeatureDependencies(*this, Diags) &&
+ OpenCLOptions::diagnoseFeatureExtensionDifferences(*this, Diags);
}
diff --git a/src/llvm-project/clang/lib/Basic/Targets/AArch64.cpp b/src/llvm-project/clang/lib/Basic/Targets/AArch64.cpp
index f171346..e163ebf 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/AArch64.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/AArch64.cpp
@@ -182,6 +182,7 @@
void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
MacroBuilder &Builder) const {
+ Builder.defineMacro("__ARM_FEATURE_FRINT", "1");
// Also include the Armv8.4 defines
getTargetDefinesARMV84A(Opts, Builder);
}
@@ -286,9 +287,27 @@
if (HasCRC)
Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
- if (HasCrypto)
+ // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained feature
+ // macros for AES, SHA2, SHA3 and SM4
+ if (HasAES && HasSHA2)
Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+ if (HasAES)
+ Builder.defineMacro("__ARM_FEATURE_AES", "1");
+
+ if (HasSHA2)
+ Builder.defineMacro("__ARM_FEATURE_SHA2", "1");
+
+ if (HasSHA3) {
+ Builder.defineMacro("__ARM_FEATURE_SHA3", "1");
+ Builder.defineMacro("__ARM_FEATURE_SHA512", "1");
+ }
+
+ if (HasSM4) {
+ Builder.defineMacro("__ARM_FEATURE_SM3", "1");
+ Builder.defineMacro("__ARM_FEATURE_SM4", "1");
+ }
+
if (HasUnaligned)
Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
@@ -333,7 +352,7 @@
Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_INT8", "1");
if ((FPU & NeonMode) && HasFP16FML)
- Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
+ Builder.defineMacro("__ARM_FEATURE_FP16_FML", "1");
if (Opts.hasSignReturnAddress()) {
// Bitmask:
@@ -359,6 +378,9 @@
if (HasLS64)
Builder.defineMacro("__ARM_FEATURE_LS64", "1");
+ if (HasRandGen)
+ Builder.defineMacro("__ARM_FEATURE_RNG", "1");
+
switch (ArchKind) {
default:
break;
@@ -409,7 +431,8 @@
Feature == "sve2-aes" || Feature == "sve2-sha3" ||
Feature == "sve2-sm4" || Feature == "f64mm" || Feature == "f32mm" ||
Feature == "i8mm" || Feature == "bf16") &&
- (FPU & SveMode));
+ (FPU & SveMode)) ||
+ (Feature == "ls64" && HasLS64);
}
bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
@@ -417,6 +440,10 @@
FPU = FPUMode;
HasCRC = false;
HasCrypto = false;
+ HasAES = false;
+ HasSHA2 = false;
+ HasSHA3 = false;
+ HasSM4 = false;
HasUnaligned = true;
HasFullFP16 = false;
HasDotProd = false;
@@ -424,6 +451,7 @@
HasMTE = false;
HasTME = false;
HasLS64 = false;
+ HasRandGen = false;
HasMatMul = false;
HasBFloat16 = false;
HasSVE2 = false;
@@ -485,6 +513,16 @@
HasCRC = true;
if (Feature == "+crypto")
HasCrypto = true;
+ if (Feature == "+aes")
+ HasAES = true;
+ if (Feature == "+sha2")
+ HasSHA2 = true;
+ if (Feature == "+sha3") {
+ HasSHA2 = true;
+ HasSHA3 = true;
+ }
+ if (Feature == "+sm4")
+ HasSM4 = true;
if (Feature == "+strict-align")
HasUnaligned = false;
if (Feature == "+v8.1a")
@@ -523,6 +561,8 @@
HasLSE = true;
if (Feature == "+ls64")
HasLS64 = true;
+ if (Feature == "+rand")
+ HasRandGen = true;
if (Feature == "+flagm")
HasFlagM = true;
}
@@ -537,6 +577,7 @@
switch (CC) {
case CC_C:
case CC_Swift:
+ case CC_SwiftAsync:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_OpenCLKernel:
@@ -712,6 +753,9 @@
if (Size == 64)
return true;
+ if (Size == 512)
+ return HasLS64;
+
SuggestedModifier = "w";
return false;
}
@@ -738,9 +782,9 @@
void AArch64leTargetInfo::setDataLayout() {
if (getTriple().isOSBinFormatMachO()) {
if(getTriple().isArch32Bit())
- resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128");
+ resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128", "_");
else
- resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
+ resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128", "_");
} else
resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
}
@@ -789,7 +833,8 @@
void WindowsARM64TargetInfo::setDataLayout() {
resetDataLayout(Triple.isOSBinFormatMachO()
? "e-m:o-i64:64-i128:128-n32:64-S128"
- : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
+ : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128",
+ Triple.isOSBinFormatMachO() ? "_" : "");
}
TargetInfo::BuiltinVaListKind
@@ -810,6 +855,7 @@
case CC_PreserveMost:
case CC_PreserveAll:
case CC_Swift:
+ case CC_SwiftAsync:
case CC_Win64:
return CCCR_OK;
default:
diff --git a/src/llvm-project/clang/lib/Basic/Targets/AArch64.h b/src/llvm-project/clang/lib/Basic/Targets/AArch64.h
index 2809fbc..46882a8 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/AArch64.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/AArch64.h
@@ -30,6 +30,10 @@
unsigned FPU;
bool HasCRC;
bool HasCrypto;
+ bool HasAES;
+ bool HasSHA2;
+ bool HasSHA3;
+ bool HasSM4;
bool HasUnaligned;
bool HasFullFP16;
bool HasDotProd;
@@ -38,6 +42,7 @@
bool HasTME;
bool HasPAuth;
bool HasLS64;
+ bool HasRandGen;
bool HasMatMul;
bool HasSVE2;
bool HasSVE2AES;
diff --git a/src/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp b/src/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp
index 91c1e83..fac786d 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -18,7 +18,6 @@
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Frontend/OpenMP/OMPGridValues.h"
-#include "llvm/IR/DataLayout.h"
using namespace clang;
using namespace clang::targets;
@@ -51,6 +50,11 @@
Global, // cuda_device
Constant, // cuda_constant
Local, // cuda_shared
+ Global, // sycl_global
+ Global, // sycl_global_device
+ Global, // sycl_global_host
+ Local, // sycl_local
+ Private, // sycl_private
Generic, // ptr32_sptr
Generic, // ptr32_uptr
Generic // ptr64
@@ -68,6 +72,12 @@
Global, // cuda_device
Constant, // cuda_constant
Local, // cuda_shared
+ // SYCL address space values for this map are dummy
+ Generic, // sycl_global
+ Generic, // sycl_global_device
+ Generic, // sycl_global_host
+ Generic, // sycl_local
+ Generic, // sycl_private
Generic, // ptr32_sptr
Generic, // ptr32_uptr
Generic // ptr64
@@ -174,6 +184,8 @@
// XXX - What does the member GPU mean if device name string passed here?
if (isAMDGCN(getTriple())) {
switch (llvm::AMDGPU::parseArchAMDGCN(CPU)) {
+ case GK_GFX1035:
+ case GK_GFX1034:
case GK_GFX1033:
case GK_GFX1032:
case GK_GFX1031:
@@ -183,6 +195,7 @@
Features["dot2-insts"] = true;
Features["dot5-insts"] = true;
Features["dot6-insts"] = true;
+ Features["dot7-insts"] = true;
Features["dl-insts"] = true;
Features["flat-address-space"] = true;
Features["16-bit-insts"] = true;
@@ -192,6 +205,7 @@
Features["gfx10-insts"] = true;
Features["gfx10-3-insts"] = true;
Features["s-memrealtime"] = true;
+ Features["s-memtime-inst"] = true;
break;
case GK_GFX1012:
case GK_GFX1011:
@@ -199,7 +213,9 @@
Features["dot2-insts"] = true;
Features["dot5-insts"] = true;
Features["dot6-insts"] = true;
+ Features["dot7-insts"] = true;
LLVM_FALLTHROUGH;
+ case GK_GFX1013:
case GK_GFX1010:
Features["dl-insts"] = true;
Features["ci-insts"] = true;
@@ -210,7 +226,11 @@
Features["gfx9-insts"] = true;
Features["gfx10-insts"] = true;
Features["s-memrealtime"] = true;
+ Features["s-memtime-inst"] = true;
break;
+ case GK_GFX90A:
+ Features["gfx90a-insts"] = true;
+ LLVM_FALLTHROUGH;
case GK_GFX908:
Features["dot3-insts"] = true;
Features["dot4-insts"] = true;
@@ -222,6 +242,7 @@
Features["dl-insts"] = true;
Features["dot1-insts"] = true;
Features["dot2-insts"] = true;
+ Features["dot7-insts"] = true;
LLVM_FALLTHROUGH;
case GK_GFX90C:
case GK_GFX909:
@@ -252,6 +273,7 @@
case GK_GFX602:
case GK_GFX601:
case GK_GFX600:
+ Features["s-memtime-inst"] = true;
break;
case GK_NONE:
break;
@@ -313,7 +335,6 @@
llvm::AMDGPU::getArchAttrR600(GPUKind)) {
resetDataLayout(isAMDGCN(getTriple()) ? DataLayoutStringAMDGCN
: DataLayoutStringR600);
- assert(DataLayout->getAllocaAddrSpace() == Private);
GridValues = llvm::omp::AMDGPUGpuGridValues;
setAddressSpaceMap(Triple.getOS() == llvm::Triple::Mesa3D ||
@@ -326,7 +347,7 @@
AllowAMDGPUUnsafeFPAtomics = Opts.AllowAMDGPUUnsafeFPAtomics;
// Set pointer width and alignment for target address space 0.
- PointerWidth = PointerAlign = DataLayout->getPointerSizeInBits();
+ PointerWidth = PointerAlign = getPointerWidthV(Generic);
if (getMaxPointerWidth() == 64) {
LongWidth = LongAlign = 64;
SizeType = UnsignedLong;
@@ -337,8 +358,8 @@
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
}
-void AMDGPUTargetInfo::adjust(LangOptions &Opts) {
- TargetInfo::adjust(Opts);
+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.
diff --git a/src/llvm-project/clang/lib/Basic/Targets/AMDGPU.h b/src/llvm-project/clang/lib/Basic/Targets/AMDGPU.h
index 8ee0ca3..2e580ec 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/AMDGPU.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/AMDGPU.h
@@ -93,7 +93,7 @@
void setAddressSpaceMap(bool DefaultIsPrivate);
- void adjust(LangOptions &Opts) override;
+ void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
uint64_t getPointerWidthV(unsigned AddrSpace) const override {
if (isR600(getTriple()))
@@ -287,10 +287,13 @@
Opts["cl_clang_storage_class_specifiers"] = true;
Opts["__cl_clang_variadic_functions"] = true;
Opts["__cl_clang_function_pointers"] = true;
+ Opts["__cl_clang_non_portable_kernel_param_types"] = true;
+ Opts["__cl_clang_bitfields"] = true;
bool IsAMDGCN = isAMDGCN(getTriple());
Opts["cl_khr_fp64"] = hasFP64();
+ Opts["__opencl_c_fp64"] = hasFP64();
if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
Opts["cl_khr_byte_addressable_store"] = true;
@@ -307,9 +310,12 @@
Opts["cl_khr_mipmap_image"] = true;
Opts["cl_khr_mipmap_image_writes"] = true;
Opts["cl_khr_subgroups"] = true;
- Opts["cl_khr_3d_image_writes"] = true;
Opts["cl_amd_media_ops"] = true;
Opts["cl_amd_media_ops2"] = true;
+
+ Opts["__opencl_c_images"] = true;
+ Opts["__opencl_c_3d_image_writes"] = true;
+ Opts["cl_khr_3d_image_writes"] = true;
}
}
diff --git a/src/llvm-project/clang/lib/Basic/Targets/ARM.cpp b/src/llvm-project/clang/lib/Basic/Targets/ARM.cpp
index a2c96ad..0e4048f 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/ARM.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/ARM.cpp
@@ -44,7 +44,8 @@
if (T.isOSBinFormatMachO()) {
resetDataLayout(BigEndian
? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
- : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
+ : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
+ "_");
} else if (T.isOSWindows()) {
assert(!BigEndian && "Windows on ARM does not support big endian");
resetDataLayout("e"
@@ -93,12 +94,13 @@
if (T.isOSBinFormatMachO() && IsAAPCS16) {
assert(!BigEndian && "AAPCS16 does not support big-endian");
- resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128");
+ resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128", "_");
} else if (T.isOSBinFormatMachO())
resetDataLayout(
BigEndian
? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
- : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
+ : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32",
+ "_");
else
resetDataLayout(
BigEndian
@@ -426,6 +428,8 @@
MVE = 0;
CRC = 0;
Crypto = 0;
+ SHA2 = 0;
+ AES = 0;
DSP = 0;
Unaligned = 1;
SoftFloat = false;
@@ -476,6 +480,10 @@
CRC = 1;
} else if (Feature == "+crypto") {
Crypto = 1;
+ } else if (Feature == "+sha2") {
+ SHA2 = 1;
+ } else if (Feature == "+aes") {
+ AES = 1;
} else if (Feature == "+dsp") {
DSP = 1;
} else if (Feature == "+fp64") {
@@ -639,8 +647,14 @@
if (ArchVersion >= 8) {
// ACLE 6.5.7 Crypto Extension
- if (Crypto)
+ // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained
+ // feature macros for AES and SHA2
+ if (SHA2 && AES)
Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+ if (SHA2)
+ Builder.defineMacro("__ARM_FEATURE_SHA2", "1");
+ if (AES)
+ Builder.defineMacro("__ARM_FEATURE_AES", "1");
// ACLE 6.5.8 CRC32 Extension
if (CRC)
Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
@@ -755,8 +769,12 @@
// Note, this is always on in gcc, even though it doesn't make sense.
Builder.defineMacro("__APCS_32__");
+ // __VFP_FP__ means that the floating-point format is VFP, not that a hardware
+ // FPU is present. Moreover, the VFP format is the only one supported by
+ // clang. For these reasons, this macro is always defined.
+ Builder.defineMacro("__VFP_FP__");
+
if (FPUModeIsVFP((FPUMode)FPU)) {
- Builder.defineMacro("__VFP_FP__");
if (FPU & VFP2FPU)
Builder.defineMacro("__ARM_VFPV2__");
if (FPU & VFP3FPU)
@@ -1120,6 +1138,7 @@
case CC_AAPCS:
case CC_AAPCS_VFP:
case CC_Swift:
+ case CC_SwiftAsync:
case CC_OpenCLKernel:
return CCCR_OK;
default:
@@ -1199,6 +1218,7 @@
case CC_PreserveMost:
case CC_PreserveAll:
case CC_Swift:
+ case CC_SwiftAsync:
return CCCR_OK;
default:
return CCCR_Warning;
diff --git a/src/llvm-project/clang/lib/Basic/Targets/ARM.h b/src/llvm-project/clang/lib/Basic/Targets/ARM.h
index 1e80f74..0910064 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/ARM.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/ARM.h
@@ -72,6 +72,8 @@
unsigned CRC : 1;
unsigned Crypto : 1;
+ unsigned SHA2 : 1;
+ unsigned AES : 1;
unsigned DSP : 1;
unsigned Unaligned : 1;
unsigned DotProd : 1;
diff --git a/src/llvm-project/clang/lib/Basic/Targets/AVR.cpp b/src/llvm-project/clang/lib/Basic/Targets/AVR.cpp
index 664eea0..e87b733 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/AVR.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/AVR.cpp
@@ -308,6 +308,7 @@
Builder.defineMacro("__AVR");
Builder.defineMacro("__AVR__");
Builder.defineMacro("__ELF__");
+ Builder.defineMacro("__flash", "__attribute__((address_space(1)))");
if (!this->CPU.empty()) {
auto It = llvm::find_if(
diff --git a/src/llvm-project/clang/lib/Basic/Targets/AVR.h b/src/llvm-project/clang/lib/Basic/Targets/AVR.h
index 94f006e..89a80ca 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/AVR.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/AVR.h
@@ -52,6 +52,7 @@
IntPtrType = SignedInt;
Char16Type = UnsignedInt;
WIntType = SignedInt;
+ Int16Type = SignedInt;
Char32Type = UnsignedLong;
SigAtomicType = SignedChar;
resetDataLayout("e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8");
diff --git a/src/llvm-project/clang/lib/Basic/Targets/BPF.h b/src/llvm-project/clang/lib/Basic/Targets/BPF.h
index a5ee436..393a91f 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/BPF.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/BPF.h
@@ -88,7 +88,7 @@
return None;
}
- bool allowDebugInfoForExternalVar() const override { return true; }
+ bool allowDebugInfoForExternalRef() const override { return true; }
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
switch (CC) {
diff --git a/src/llvm-project/clang/lib/Basic/Targets/Hexagon.cpp b/src/llvm-project/clang/lib/Basic/Targets/Hexagon.cpp
index a8b4380..9c37dee 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/Hexagon.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/Hexagon.cpp
@@ -65,6 +65,9 @@
} else if (CPU == "hexagonv67t") {
Builder.defineMacro("__HEXAGON_V67T__");
Builder.defineMacro("__HEXAGON_ARCH__", "67");
+ } else if (CPU == "hexagonv68") {
+ Builder.defineMacro("__HEXAGON_V68__");
+ Builder.defineMacro("__HEXAGON_ARCH__", "68");
}
if (hasFeature("hvx-length64b")) {
@@ -129,14 +132,37 @@
}
const char *const HexagonTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
- "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
- "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26",
- "r27", "r28", "r29", "r30", "r31", "p0", "p1", "p2", "p3",
- "sa0", "lc0", "sa1", "lc1", "m0", "m1", "usr", "ugp",
+ // Scalar registers:
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
+ "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
+ "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
"r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14",
"r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28",
- "r31:30"
+ "r31:30",
+ // Predicate registers:
+ "p0", "p1", "p2", "p3",
+ // Control registers:
+ "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11",
+ "c12", "c13", "c14", "c15", "c16", "c17", "c18", "c19", "c20", "c21",
+ "c22", "c23", "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31",
+ "c1:0", "c3:2", "c5:4", "c7:6", "c9:8", "c11:10", "c13:12", "c15:14",
+ "c17:16", "c19:18", "c21:20", "c23:22", "c25:24", "c27:26", "c29:28",
+ "c31:30",
+ // Control register aliases:
+ "sa0", "lc0", "sa1", "lc1", "p3:0", "m0", "m1", "usr", "pc", "ugp",
+ "gp", "cs0", "cs1", "upcyclelo", "upcyclehi", "framelimit", "framekey",
+ "pktcountlo", "pktcounthi", "utimerlo", "utimerhi",
+ "upcycle", "pktcount", "utimer",
+ // HVX vector registers:
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
+ "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
+ "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+ "v1:0", "v3:2", "v5:4", "v7:6", "v9:8", "v11:10", "v13:12", "v15:14",
+ "v17:16", "v19:18", "v21:20", "v23:22", "v25:24", "v27:26", "v29:28",
+ "v31:30",
+ "v3:0", "v7:4", "v11:8", "v15:12", "v19:16", "v23:20", "v27:24", "v31:28",
+ // HVX vector predicates:
+ "q0", "q1", "q2", "q3",
};
ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
@@ -188,6 +214,7 @@
{{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}},
{{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}},
{{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}},
+ {{"hexagonv68"}, {"68"}},
};
const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
diff --git a/src/llvm-project/clang/lib/Basic/Targets/Le64.cpp b/src/llvm-project/clang/lib/Basic/Targets/Le64.cpp
index cacd10d..5c961ff 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/Le64.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/Le64.cpp
@@ -19,15 +19,8 @@
using namespace clang;
using namespace clang::targets;
-const Builtin::Info Le64TargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) \
- {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
-#include "clang/Basic/BuiltinsLe64.def"
-};
-
ArrayRef<Builtin::Info> Le64TargetInfo::getTargetBuiltins() const {
- return llvm::makeArrayRef(BuiltinInfo, clang::Le64::LastTSBuiltin -
- Builtin::FirstTSBuiltin);
+ return {};
}
void Le64TargetInfo::getTargetDefines(const LangOptions &Opts,
diff --git a/src/llvm-project/clang/lib/Basic/Targets/Le64.h b/src/llvm-project/clang/lib/Basic/Targets/Le64.h
index 253d568..13a0b04 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/Le64.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/Le64.h
@@ -22,7 +22,6 @@
namespace targets {
class LLVM_LIBRARY_VISIBILITY Le64TargetInfo : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
public:
Le64TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
diff --git a/src/llvm-project/clang/lib/Basic/Targets/M68k.cpp b/src/llvm-project/clang/lib/Basic/Targets/M68k.cpp
new file mode 100644
index 0000000..c0cd8fa
--- /dev/null
+++ b/src/llvm-project/clang/lib/Basic/Targets/M68k.cpp
@@ -0,0 +1,236 @@
+//===--- M68k.cpp - Implement M68k targets feature support-------------===//
+//
+// Part of the LLVM Project, under the Apache 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 M68k TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "M68k.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/TargetBuiltins.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/TargetParser.h"
+#include <cstdint>
+#include <cstring>
+#include <limits>
+
+namespace clang {
+namespace targets {
+
+M68kTargetInfo::M68kTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &)
+ : TargetInfo(Triple) {
+
+ std::string Layout = "";
+
+ // M68k is Big Endian
+ Layout += "E";
+
+ // FIXME how to wire it with the used object format?
+ Layout += "-m:e";
+
+ // M68k pointers are always 32 bit wide even for 16-bit CPUs
+ Layout += "-p:32:16:32";
+
+ // M68k integer data types
+ Layout += "-i8:8:8-i16:16:16-i32:16:32";
+
+ // FIXME no floats at the moment
+
+ // The registers can hold 8, 16, 32 bits
+ Layout += "-n8:16:32";
+
+ // 16 bit alignment for both stack and aggregate
+ // in order to conform to ABI used by GCC
+ Layout += "-a:0:16-S16";
+
+ resetDataLayout(Layout);
+
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
+}
+
+bool M68kTargetInfo::setCPU(const std::string &Name) {
+ StringRef N = Name;
+ CPU = llvm::StringSwitch<CPUKind>(N)
+ .Case("generic", CK_68000)
+ .Case("M68000", CK_68000)
+ .Case("M68010", CK_68010)
+ .Case("M68020", CK_68020)
+ .Case("M68030", CK_68030)
+ .Case("M68040", CK_68040)
+ .Case("M68060", CK_68060)
+ .Default(CK_Unknown);
+ return CPU != CK_Unknown;
+}
+
+void M68kTargetInfo::getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ using llvm::Twine;
+
+ Builder.defineMacro("__m68k__");
+
+ Builder.defineMacro("mc68000");
+ Builder.defineMacro("__mc68000");
+ Builder.defineMacro("__mc68000__");
+
+ // For sub-architecture
+ switch (CPU) {
+ case CK_68010:
+ Builder.defineMacro("mc68010");
+ Builder.defineMacro("__mc68010");
+ Builder.defineMacro("__mc68010__");
+ break;
+ case CK_68020:
+ Builder.defineMacro("mc68020");
+ Builder.defineMacro("__mc68020");
+ Builder.defineMacro("__mc68020__");
+ break;
+ case CK_68030:
+ Builder.defineMacro("mc68030");
+ Builder.defineMacro("__mc68030");
+ Builder.defineMacro("__mc68030__");
+ break;
+ case CK_68040:
+ Builder.defineMacro("mc68040");
+ Builder.defineMacro("__mc68040");
+ Builder.defineMacro("__mc68040__");
+ break;
+ case CK_68060:
+ Builder.defineMacro("mc68060");
+ Builder.defineMacro("__mc68060");
+ Builder.defineMacro("__mc68060__");
+ break;
+ default:
+ break;
+ }
+}
+
+ArrayRef<Builtin::Info> M68kTargetInfo::getTargetBuiltins() const {
+ // FIXME: Implement.
+ return None;
+}
+
+bool M68kTargetInfo::hasFeature(StringRef Feature) const {
+ // FIXME elaborate moar
+ return Feature == "M68000";
+}
+
+const char *const M68kTargetInfo::GCCRegNames[] = {
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+ "pc"};
+
+ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {
+ return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {
+ // No aliases.
+ return None;
+}
+
+bool M68kTargetInfo::validateAsmConstraint(
+ const char *&Name, TargetInfo::ConstraintInfo &info) const {
+ switch (*Name) {
+ case 'a': // address register
+ case 'd': // data register
+ info.setAllowsRegister();
+ return true;
+ case 'I': // constant integer in the range [1,8]
+ info.setRequiresImmediate(1, 8);
+ return true;
+ case 'J': // constant signed 16-bit integer
+ info.setRequiresImmediate(std::numeric_limits<int16_t>::min(),
+ std::numeric_limits<int16_t>::max());
+ return true;
+ case 'K': // constant that is NOT in the range of [-0x80, 0x80)
+ info.setRequiresImmediate();
+ return true;
+ case 'L': // constant integer in the range [-8,-1]
+ info.setRequiresImmediate(-8, -1);
+ return true;
+ case 'M': // constant that is NOT in the range of [-0x100, 0x100]
+ info.setRequiresImmediate();
+ return true;
+ case 'N': // constant integer in the range [24,31]
+ info.setRequiresImmediate(24, 31);
+ return true;
+ case 'O': // constant integer 16
+ info.setRequiresImmediate(16);
+ return true;
+ case 'P': // constant integer in the range [8,15]
+ info.setRequiresImmediate(8, 15);
+ return true;
+ case 'C':
+ ++Name;
+ switch (*Name) {
+ case '0': // constant integer 0
+ info.setRequiresImmediate(0);
+ return true;
+ case 'i': // constant integer
+ case 'j': // integer constant that doesn't fit in 16 bits
+ info.setRequiresImmediate();
+ return true;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+llvm::Optional<std::string>
+M68kTargetInfo::handleAsmEscapedChar(char EscChar) const {
+ char C;
+ switch (EscChar) {
+ case '.':
+ case '#':
+ C = EscChar;
+ break;
+ case '/':
+ C = '%';
+ break;
+ case '$':
+ C = 's';
+ break;
+ case '&':
+ C = 'd';
+ break;
+ default:
+ return llvm::None;
+ }
+
+ return std::string(1, C);
+}
+
+std::string M68kTargetInfo::convertConstraint(const char *&Constraint) const {
+ if (*Constraint == 'C')
+ // Two-character constraint; add "^" hint for later parsing
+ return std::string("^") + std::string(Constraint++, 2);
+
+ return std::string(1, *Constraint);
+}
+
+const char *M68kTargetInfo::getClobbers() const {
+ // FIXME: Is this really right?
+ return "";
+}
+
+TargetInfo::BuiltinVaListKind M68kTargetInfo::getBuiltinVaListKind() const {
+ return TargetInfo::VoidPtrBuiltinVaList;
+}
+
+} // namespace targets
+} // namespace clang
diff --git a/src/llvm-project/clang/lib/Basic/Targets/M68k.h b/src/llvm-project/clang/lib/Basic/Targets/M68k.h
new file mode 100644
index 0000000..a42ca67
--- /dev/null
+++ b/src/llvm-project/clang/lib/Basic/Targets/M68k.h
@@ -0,0 +1,59 @@
+//===--- M68k.h - Declare M68k target feature support -------*- 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 declares M68k TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_M68K_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_M68K_H
+
+#include "OSTargets.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo {
+ static const char *const GCCRegNames[];
+
+ enum CPUKind {
+ CK_Unknown,
+ CK_68000,
+ CK_68010,
+ CK_68020,
+ CK_68030,
+ CK_68040,
+ CK_68060
+ } CPU = CK_Unknown;
+
+public:
+ M68kTargetInfo(const llvm::Triple &Triple, const TargetOptions &);
+
+ void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const override;
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+ bool hasFeature(StringRef Feature) const override;
+ ArrayRef<const char *> getGCCRegNames() const override;
+ ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
+ std::string convertConstraint(const char *&Constraint) const override;
+ bool validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const override;
+ llvm::Optional<std::string> handleAsmEscapedChar(char EscChar) const override;
+ const char *getClobbers() const override;
+ BuiltinVaListKind getBuiltinVaListKind() const override;
+ bool setCPU(const std::string &Name) override;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif
diff --git a/src/llvm-project/clang/lib/Basic/Targets/NVPTX.cpp b/src/llvm-project/clang/lib/Basic/Targets/NVPTX.cpp
index b7f0dce..56f8a17 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/NVPTX.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/NVPTX.cpp
@@ -45,6 +45,8 @@
if (!Feature.startswith("+ptx"))
continue;
PTXVersion = llvm::StringSwitch<unsigned>(Feature)
+ .Case("+ptx72", 72)
+ .Case("+ptx71", 71)
.Case("+ptx70", 70)
.Case("+ptx65", 65)
.Case("+ptx64", 64)
@@ -200,14 +202,18 @@
case CudaArch::GFX906:
case CudaArch::GFX908:
case CudaArch::GFX909:
+ case CudaArch::GFX90a:
case CudaArch::GFX90c:
case CudaArch::GFX1010:
case CudaArch::GFX1011:
case CudaArch::GFX1012:
+ case CudaArch::GFX1013:
case CudaArch::GFX1030:
case CudaArch::GFX1031:
case CudaArch::GFX1032:
case CudaArch::GFX1033:
+ case CudaArch::GFX1034:
+ case CudaArch::GFX1035:
case CudaArch::LAST:
break;
case CudaArch::UNUSED:
@@ -246,6 +252,8 @@
return "750";
case CudaArch::SM_80:
return "800";
+ case CudaArch::SM_86:
+ return "860";
}
llvm_unreachable("unhandled CudaArch");
}();
diff --git a/src/llvm-project/clang/lib/Basic/Targets/NVPTX.h b/src/llvm-project/clang/lib/Basic/Targets/NVPTX.h
index 038dec4..c7db3cd 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/NVPTX.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/NVPTX.h
@@ -35,6 +35,11 @@
1, // cuda_device
4, // cuda_constant
3, // cuda_shared
+ 1, // sycl_global
+ 1, // sycl_global_device
+ 1, // sycl_global_host
+ 3, // sycl_local
+ 0, // sycl_private
0, // ptr32_sptr
0, // ptr32_uptr
0 // ptr64
@@ -130,8 +135,11 @@
Opts["cl_clang_storage_class_specifiers"] = true;
Opts["__cl_clang_function_pointers"] = true;
Opts["__cl_clang_variadic_functions"] = true;
+ Opts["__cl_clang_non_portable_kernel_param_types"] = true;
+ Opts["__cl_clang_bitfields"] = true;
Opts["cl_khr_fp64"] = true;
+ Opts["__opencl_c_fp64"] = true;
Opts["cl_khr_byte_addressable_store"] = true;
Opts["cl_khr_global_int32_base_atomics"] = true;
Opts["cl_khr_global_int32_extended_atomics"] = true;
diff --git a/src/llvm-project/clang/lib/Basic/Targets/OSTargets.cpp b/src/llvm-project/clang/lib/Basic/Targets/OSTargets.cpp
index 15e475a..7cd4a51 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/OSTargets.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/OSTargets.cpp
@@ -55,6 +55,8 @@
} else {
Triple.getOSVersion(Maj, Min, Rev);
PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
+ if (PlatformName == "ios" && Triple.isMacCatalystEnvironment())
+ PlatformName = "maccatalyst";
}
// If -target arch-pc-win32-macho option specified, we're
diff --git a/src/llvm-project/clang/lib/Basic/Targets/OSTargets.h b/src/llvm-project/clang/lib/Basic/Targets/OSTargets.h
index 67fa1a5..e24fb5c 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/OSTargets.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/OSTargets.h
@@ -13,7 +13,6 @@
#define LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
#include "Targets.h"
-#include "llvm/MC/MCSectionMachO.h"
namespace clang {
namespace targets {
@@ -114,15 +113,6 @@
this->MCountName = "\01mcount";
}
- std::string isValidSectionSpecifier(StringRef SR) const override {
- // Let MCSectionMachO validate this.
- StringRef Segment, Section;
- unsigned TAA, StubSize;
- bool HasTAA;
- return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
- TAA, HasTAA, StubSize);
- }
-
const char *getStaticInitSectionSpecifier() const override {
// FIXME: We should return 0 when building kexts.
return "__TEXT,__StaticInit,regular,pure_instructions";
@@ -261,6 +251,9 @@
case llvm::Triple::arm:
this->MCountName = "__mcount";
break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ break;
}
}
};
@@ -491,6 +484,9 @@
case llvm::Triple::sparcv9:
this->MCountName = "_mcount";
break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ break;
}
}
};
@@ -679,6 +675,12 @@
Builder.defineMacro("_POWER");
Builder.defineMacro("_AIX");
+ Builder.defineMacro("__TOS_AIX__");
+
+ if (Opts.C11) {
+ Builder.defineMacro("__STDC_NO_ATOMICS__");
+ Builder.defineMacro("__STDC_NO_THREADS__");
+ }
if (Opts.EnableAIXExtendedAltivecABI)
Builder.defineMacro("__EXTABI__");
@@ -699,6 +701,7 @@
if (OsVersion >= std::make_pair(6, 1)) Builder.defineMacro("_AIX61");
if (OsVersion >= std::make_pair(7, 1)) Builder.defineMacro("_AIX71");
if (OsVersion >= std::make_pair(7, 2)) Builder.defineMacro("_AIX72");
+ if (OsVersion >= std::make_pair(7, 3)) Builder.defineMacro("_AIX73");
// FIXME: Do not define _LONG_LONG when -fno-long-long is specified.
Builder.defineMacro("_LONG_LONG");
@@ -788,10 +791,11 @@
ZOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->WCharType = TargetInfo::UnsignedInt;
+ this->MaxAlignedAttribute = 128;
this->UseBitFieldTypeAlignment = false;
this->UseZeroLengthBitfieldAlignment = true;
+ this->UseLeadingZeroLengthBitfield = false;
this->ZeroLengthBitfieldBoundary = 32;
- this->MinGlobalAlign = 0;
this->DefaultAlignForAttributeAligned = 128;
}
};
@@ -940,11 +944,21 @@
MacroBuilder &Builder) const final {
WebAssemblyOSTargetInfo<Target>::getOSDefines(Opts, Triple, Builder);
Builder.defineMacro("__EMSCRIPTEN__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("__EMSCRIPTEN_PTHREADS__");
}
public:
- explicit EmscriptenTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : WebAssemblyOSTargetInfo<Target>(Triple, Opts) {}
+ explicit EmscriptenTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : WebAssemblyOSTargetInfo<Target>(Triple, Opts) {
+ // Keeping the alignment of long double to 8 bytes even though its size is
+ // 16 bytes allows emscripten to have an 8-byte-aligned max_align_t which
+ // in turn gives is a 8-byte aligned malloc.
+ // Emscripten's ABI is unstable and we may change this back to 128 to match
+ // the WebAssembly default in the future.
+ this->LongDoubleAlign = 64;
+ }
};
} // namespace targets
diff --git a/src/llvm-project/clang/lib/Basic/Targets/PPC.cpp b/src/llvm-project/clang/lib/Basic/Targets/PPC.cpp
index 6c30368..5965688 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/PPC.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/PPC.cpp
@@ -56,6 +56,8 @@
HasP10Vector = true;
} else if (Feature == "+pcrelative-memops") {
HasPCRelativeMemops = true;
+ } else if (Feature == "+prefix-instrs") {
+ HasPrefixInstrs = true;
} else if (Feature == "+spe" || Feature == "+efpu2") {
HasStrictFP = false;
HasSPE = true;
@@ -67,6 +69,16 @@
PairedVectorMemops = true;
} else if (Feature == "+mma") {
HasMMA = true;
+ } else if (Feature == "+rop-protect") {
+ HasROPProtect = true;
+ } else if (Feature == "+privileged") {
+ HasPrivileged = true;
+ } else if (Feature == "+isa-v207-instructions") {
+ IsISA2_07 = true;
+ } else if (Feature == "+isa-v30-instructions") {
+ IsISA3_0 = true;
+ } else if (Feature == "+isa-v31-instructions") {
+ IsISA3_1 = true;
}
// TODO: Finish this list and add an assert that we've handled them
// all.
@@ -75,10 +87,164 @@
return true;
}
+static void defineXLCompatMacros(MacroBuilder &Builder) {
+ Builder.defineMacro("__popcntb", "__builtin_ppc_popcntb");
+ Builder.defineMacro("__poppar4", "__builtin_ppc_poppar4");
+ Builder.defineMacro("__poppar8", "__builtin_ppc_poppar8");
+ Builder.defineMacro("__eieio", "__builtin_ppc_eieio");
+ Builder.defineMacro("__iospace_eieio", "__builtin_ppc_iospace_eieio");
+ Builder.defineMacro("__isync", "__builtin_ppc_isync");
+ Builder.defineMacro("__lwsync", "__builtin_ppc_lwsync");
+ Builder.defineMacro("__iospace_lwsync", "__builtin_ppc_iospace_lwsync");
+ Builder.defineMacro("__sync", "__builtin_ppc_sync");
+ Builder.defineMacro("__iospace_sync", "__builtin_ppc_iospace_sync");
+ Builder.defineMacro("__dcbfl", "__builtin_ppc_dcbfl");
+ Builder.defineMacro("__dcbflp", "__builtin_ppc_dcbflp");
+ Builder.defineMacro("__dcbst", "__builtin_ppc_dcbst");
+ Builder.defineMacro("__dcbt", "__builtin_ppc_dcbt");
+ Builder.defineMacro("__dcbtst", "__builtin_ppc_dcbtst");
+ Builder.defineMacro("__dcbz", "__builtin_ppc_dcbz");
+ Builder.defineMacro("__icbt", "__builtin_ppc_icbt");
+ Builder.defineMacro("__compare_and_swap", "__builtin_ppc_compare_and_swap");
+ Builder.defineMacro("__compare_and_swaplp",
+ "__builtin_ppc_compare_and_swaplp");
+ Builder.defineMacro("__fetch_and_add", "__builtin_ppc_fetch_and_add");
+ Builder.defineMacro("__fetch_and_addlp", "__builtin_ppc_fetch_and_addlp");
+ Builder.defineMacro("__fetch_and_and", "__builtin_ppc_fetch_and_and");
+ Builder.defineMacro("__fetch_and_andlp", "__builtin_ppc_fetch_and_andlp");
+ Builder.defineMacro("__fetch_and_or", "__builtin_ppc_fetch_and_or");
+ Builder.defineMacro("__fetch_and_orlp", "__builtin_ppc_fetch_and_orlp");
+ Builder.defineMacro("__fetch_and_swap", "__builtin_ppc_fetch_and_swap");
+ Builder.defineMacro("__fetch_and_swaplp", "__builtin_ppc_fetch_and_swaplp");
+ Builder.defineMacro("__ldarx", "__builtin_ppc_ldarx");
+ Builder.defineMacro("__lwarx", "__builtin_ppc_lwarx");
+ Builder.defineMacro("__lharx", "__builtin_ppc_lharx");
+ Builder.defineMacro("__lbarx", "__builtin_ppc_lbarx");
+ Builder.defineMacro("__stfiw", "__builtin_ppc_stfiw");
+ Builder.defineMacro("__stdcx", "__builtin_ppc_stdcx");
+ Builder.defineMacro("__stwcx", "__builtin_ppc_stwcx");
+ Builder.defineMacro("__sthcx", "__builtin_ppc_sthcx");
+ Builder.defineMacro("__stbcx", "__builtin_ppc_stbcx");
+ Builder.defineMacro("__tdw", "__builtin_ppc_tdw");
+ Builder.defineMacro("__tw", "__builtin_ppc_tw");
+ Builder.defineMacro("__trap", "__builtin_ppc_trap");
+ Builder.defineMacro("__trapd", "__builtin_ppc_trapd");
+ Builder.defineMacro("__fcfid", "__builtin_ppc_fcfid");
+ Builder.defineMacro("__fcfud", "__builtin_ppc_fcfud");
+ Builder.defineMacro("__fctid", "__builtin_ppc_fctid");
+ Builder.defineMacro("__fctidz", "__builtin_ppc_fctidz");
+ Builder.defineMacro("__fctiw", "__builtin_ppc_fctiw");
+ Builder.defineMacro("__fctiwz", "__builtin_ppc_fctiwz");
+ Builder.defineMacro("__fctudz", "__builtin_ppc_fctudz");
+ Builder.defineMacro("__fctuwz", "__builtin_ppc_fctuwz");
+ Builder.defineMacro("__cmpeqb", "__builtin_ppc_cmpeqb");
+ Builder.defineMacro("__cmprb", "__builtin_ppc_cmprb");
+ Builder.defineMacro("__setb", "__builtin_ppc_setb");
+ Builder.defineMacro("__cmpb", "__builtin_ppc_cmpb");
+ Builder.defineMacro("__mulhd", "__builtin_ppc_mulhd");
+ Builder.defineMacro("__mulhdu", "__builtin_ppc_mulhdu");
+ Builder.defineMacro("__mulhw", "__builtin_ppc_mulhw");
+ Builder.defineMacro("__mulhwu", "__builtin_ppc_mulhwu");
+ Builder.defineMacro("__maddhd", "__builtin_ppc_maddhd");
+ Builder.defineMacro("__maddhdu", "__builtin_ppc_maddhdu");
+ Builder.defineMacro("__maddld", "__builtin_ppc_maddld");
+ Builder.defineMacro("__rlwnm", "__builtin_ppc_rlwnm");
+ Builder.defineMacro("__rlwimi", "__builtin_ppc_rlwimi");
+ Builder.defineMacro("__rldimi", "__builtin_ppc_rldimi");
+ Builder.defineMacro("__load2r", "__builtin_ppc_load2r");
+ Builder.defineMacro("__load4r", "__builtin_ppc_load4r");
+ Builder.defineMacro("__load8r", "__builtin_ppc_load8r");
+ Builder.defineMacro("__store2r", "__builtin_ppc_store2r");
+ Builder.defineMacro("__store4r", "__builtin_ppc_store4r");
+ Builder.defineMacro("__store8r", "__builtin_ppc_store8r");
+ Builder.defineMacro("__extract_exp", "__builtin_ppc_extract_exp");
+ Builder.defineMacro("__extract_sig", "__builtin_ppc_extract_sig");
+ Builder.defineMacro("__mtfsb0", "__builtin_ppc_mtfsb0");
+ Builder.defineMacro("__mtfsb1", "__builtin_ppc_mtfsb1");
+ Builder.defineMacro("__mtfsf", "__builtin_ppc_mtfsf");
+ Builder.defineMacro("__mtfsfi", "__builtin_ppc_mtfsfi");
+ Builder.defineMacro("__insert_exp", "__builtin_ppc_insert_exp");
+ Builder.defineMacro("__fmsub", "__builtin_ppc_fmsub");
+ Builder.defineMacro("__fmsubs", "__builtin_ppc_fmsubs");
+ Builder.defineMacro("__fnmadd", "__builtin_ppc_fnmadd");
+ Builder.defineMacro("__fnmadds", "__builtin_ppc_fnmadds");
+ Builder.defineMacro("__fnmsub", "__builtin_ppc_fnmsub");
+ Builder.defineMacro("__fnmsubs", "__builtin_ppc_fnmsubs");
+ Builder.defineMacro("__fre", "__builtin_ppc_fre");
+ Builder.defineMacro("__fres", "__builtin_ppc_fres");
+ Builder.defineMacro("__swdiv_nochk", "__builtin_ppc_swdiv_nochk");
+ Builder.defineMacro("__swdivs_nochk", "__builtin_ppc_swdivs_nochk");
+ Builder.defineMacro("__alloca", "__builtin_alloca");
+ Builder.defineMacro("__vcipher", "__builtin_altivec_crypto_vcipher");
+ Builder.defineMacro("__vcipherlast", "__builtin_altivec_crypto_vcipherlast");
+ Builder.defineMacro("__vncipher", "__builtin_altivec_crypto_vncipher");
+ Builder.defineMacro("__vncipherlast",
+ "__builtin_altivec_crypto_vncipherlast");
+ Builder.defineMacro("__vpermxor", "__builtin_altivec_crypto_vpermxor");
+ Builder.defineMacro("__vpmsumb", "__builtin_altivec_crypto_vpmsumb");
+ Builder.defineMacro("__vpmsumd", "__builtin_altivec_crypto_vpmsumd");
+ Builder.defineMacro("__vpmsumh", "__builtin_altivec_crypto_vpmsumh");
+ Builder.defineMacro("__vpmsumw", "__builtin_altivec_crypto_vpmsumw");
+ Builder.defineMacro("__divde", "__builtin_divde");
+ Builder.defineMacro("__divwe", "__builtin_divwe");
+ Builder.defineMacro("__divdeu", "__builtin_divdeu");
+ Builder.defineMacro("__divweu", "__builtin_divweu");
+ Builder.defineMacro("__alignx", "__builtin_ppc_alignx");
+ Builder.defineMacro("__bcopy", "bcopy");
+ Builder.defineMacro("__bpermd", "__builtin_bpermd");
+ Builder.defineMacro("__cntlz4", "__builtin_clz");
+ Builder.defineMacro("__cntlz8", "__builtin_clzll");
+ Builder.defineMacro("__cmplx", "__builtin_complex");
+ Builder.defineMacro("__cmplxf", "__builtin_complex");
+ Builder.defineMacro("__cnttz4", "__builtin_ctz");
+ Builder.defineMacro("__cnttz8", "__builtin_ctzll");
+ Builder.defineMacro("__darn", "__builtin_darn");
+ Builder.defineMacro("__darn_32", "__builtin_darn_32");
+ Builder.defineMacro("__darn_raw", "__builtin_darn_raw");
+ Builder.defineMacro("__dcbf", "__builtin_dcbf");
+ Builder.defineMacro("__fmadd", "__builtin_fma");
+ Builder.defineMacro("__fmadds", "__builtin_fmaf");
+ Builder.defineMacro("__labs", "__builtin_labs");
+ Builder.defineMacro("__llabs", "__builtin_llabs");
+ Builder.defineMacro("__popcnt4", "__builtin_popcount");
+ Builder.defineMacro("__popcnt8", "__builtin_popcountll");
+ Builder.defineMacro("__readflm", "__builtin_readflm");
+ Builder.defineMacro("__rotatel4", "__builtin_rotateleft32");
+ Builder.defineMacro("__rotatel8", "__builtin_rotateleft64");
+ Builder.defineMacro("__rdlam", "__builtin_ppc_rdlam");
+ Builder.defineMacro("__setflm", "__builtin_setflm");
+ Builder.defineMacro("__setrnd", "__builtin_setrnd");
+ Builder.defineMacro("__dcbtstt", "__builtin_ppc_dcbtstt");
+ Builder.defineMacro("__dcbtt", "__builtin_ppc_dcbtt");
+ Builder.defineMacro("__mftbu", "__builtin_ppc_mftbu");
+ Builder.defineMacro("__mfmsr", "__builtin_ppc_mfmsr");
+ Builder.defineMacro("__mtmsr", "__builtin_ppc_mtmsr");
+ Builder.defineMacro("__mfspr", "__builtin_ppc_mfspr");
+ Builder.defineMacro("__mtspr", "__builtin_ppc_mtspr");
+ Builder.defineMacro("__fric", "__builtin_ppc_fric");
+ Builder.defineMacro("__frim", "__builtin_ppc_frim");
+ Builder.defineMacro("__frims", "__builtin_ppc_frims");
+ Builder.defineMacro("__frin", "__builtin_ppc_frin");
+ Builder.defineMacro("__frins", "__builtin_ppc_frins");
+ Builder.defineMacro("__frip", "__builtin_ppc_frip");
+ Builder.defineMacro("__frips", "__builtin_ppc_frips");
+ Builder.defineMacro("__friz", "__builtin_ppc_friz");
+ Builder.defineMacro("__frizs", "__builtin_ppc_frizs");
+ Builder.defineMacro("__fsel", "__builtin_ppc_fsel");
+ Builder.defineMacro("__fsels", "__builtin_ppc_fsels");
+ Builder.defineMacro("__frsqrte", "__builtin_ppc_frsqrte");
+ Builder.defineMacro("__frsqrtes", "__builtin_ppc_frsqrtes");
+ Builder.defineMacro("__fsqrt", "__builtin_ppc_fsqrt");
+ Builder.defineMacro("__fsqrts", "__builtin_ppc_fsqrts");
+}
+
/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
/// #defines that are not tied to a specific subtarget.
void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
+
+ defineXLCompatMacros(Builder);
+
// Target identification.
Builder.defineMacro("__ppc__");
Builder.defineMacro("__PPC__");
@@ -130,6 +296,11 @@
Builder.defineMacro("__LONG_DOUBLE_IBM128__");
}
+ if (getTriple().isOSAIX() && Opts.LongDoubleSize == 64) {
+ assert(LongDoubleWidth == 64);
+ Builder.defineMacro("__LONGDOUBLE64");
+ }
+
// Define this for elfv2 (64-bit only) or 64-bit darwin.
if (ABI == "elfv2" ||
(getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64))
@@ -194,8 +365,14 @@
Builder.defineMacro("__POWER9_VECTOR__");
if (HasMMA)
Builder.defineMacro("__MMA__");
+ if (HasROPProtect)
+ Builder.defineMacro("__ROP_PROTECT__");
+ if (HasPrivileged)
+ Builder.defineMacro("__PRIVILEGED__");
if (HasP10Vector)
Builder.defineMacro("__POWER10_VECTOR__");
+ if (HasPCRelativeMemops)
+ Builder.defineMacro("__PCREL__");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
@@ -320,11 +497,25 @@
.Case("pwr8", true)
.Default(false);
+ // ROP Protect is off by default.
+ Features["rop-protect"] = false;
+ // Privileged instructions are off by default.
+ Features["privileged"] = false;
+
Features["spe"] = llvm::StringSwitch<bool>(CPU)
.Case("8548", true)
.Case("e500", true)
.Default(false);
+ Features["isa-v207-instructions"] = llvm::StringSwitch<bool>(CPU)
+ .Case("ppc64le", true)
+ .Case("pwr9", true)
+ .Case("pwr8", true)
+ .Default(false);
+
+ Features["isa-v30-instructions"] =
+ llvm::StringSwitch<bool>(CPU).Case("pwr9", true).Default(false);
+
// Power10 includes all the same features as Power9 plus any features specific
// to the Power10 core.
if (CPU == "pwr10" || CPU == "power10") {
@@ -356,6 +547,19 @@
return false;
}
+ if (!(ArchDefs & ArchDefinePwr8) &&
+ llvm::find(FeaturesVec, "+rop-protect") != FeaturesVec.end()) {
+ // We can turn on ROP Protect on Power 8 and above.
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mrop-protect" << CPU;
+ return false;
+ }
+
+ if (!(ArchDefs & ArchDefinePwr8) &&
+ llvm::find(FeaturesVec, "+privileged") != FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mprivileged" << CPU;
+ return false;
+ }
+
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
@@ -367,6 +571,8 @@
Features["mma"] = true;
Features["power10-vector"] = true;
Features["pcrelative-memops"] = true;
+ Features["prefix-instrs"] = true;
+ Features["isa-v31-instructions"] = true;
return;
}
@@ -392,8 +598,14 @@
.Case("paired-vector-memops", PairedVectorMemops)
.Case("power10-vector", HasP10Vector)
.Case("pcrelative-memops", HasPCRelativeMemops)
+ .Case("prefix-instrs", HasPrefixInstrs)
.Case("spe", HasSPE)
.Case("mma", HasMMA)
+ .Case("rop-protect", HasROPProtect)
+ .Case("privileged", HasPrivileged)
+ .Case("isa-v207-instructions", IsISA2_07)
+ .Case("isa-v30-instructions", IsISA3_0)
+ .Case("isa-v31-instructions", IsISA3_1)
.Default(false);
}
@@ -422,6 +634,8 @@
Features["power8-vector"] = Features["power9-vector"] = true;
if (Name == "pcrel")
Features["pcrelative-memops"] = true;
+ else if (Name == "prefixed")
+ Features["prefix-instrs"] = true;
else
Features[Name] = true;
} else {
@@ -442,6 +656,8 @@
Features["power10-vector"] = false;
if (Name == "pcrel")
Features["pcrelative-memops"] = false;
+ else if (Name == "prefixed")
+ Features["prefix-instrs"] = false;
else
Features[Name] = false;
}
@@ -524,17 +740,17 @@
}
static constexpr llvm::StringLiteral ValidCPUNames[] = {
- {"generic"}, {"440"}, {"450"}, {"601"}, {"602"},
- {"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"},
- {"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"},
- {"7450"}, {"g4+"}, {"750"}, {"8548"}, {"970"},
- {"g5"}, {"a2"}, {"e500"}, {"e500mc"}, {"e5500"},
- {"power3"}, {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"},
- {"pwr5"}, {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"},
- {"power6x"}, {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"},
- {"pwr8"}, {"power9"}, {"pwr9"}, {"power10"}, {"pwr10"},
- {"powerpc"}, {"ppc"}, {"powerpc64"}, {"ppc64"}, {"powerpc64le"},
- {"ppc64le"}, {"future"}};
+ {"generic"}, {"440"}, {"450"}, {"601"}, {"602"},
+ {"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"},
+ {"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"},
+ {"7450"}, {"g4+"}, {"750"}, {"8548"}, {"970"},
+ {"g5"}, {"a2"}, {"e500"}, {"e500mc"}, {"e5500"},
+ {"power3"}, {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"},
+ {"pwr5"}, {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"},
+ {"power6x"}, {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"},
+ {"pwr8"}, {"power9"}, {"pwr9"}, {"power10"}, {"pwr10"},
+ {"powerpc"}, {"ppc"}, {"ppc32"}, {"powerpc64"}, {"ppc64"},
+ {"powerpc64le"}, {"ppc64le"}, {"future"}};
bool PPCTargetInfo::isValidCPUName(StringRef Name) const {
return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
@@ -544,14 +760,15 @@
Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
}
-void PPCTargetInfo::adjust(LangOptions &Opts) {
+void PPCTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
if (HasAltivec)
Opts.AltiVec = 1;
- TargetInfo::adjust(Opts);
+ TargetInfo::adjust(Diags, Opts);
if (LongDoubleFormat != &llvm::APFloat::IEEEdouble())
LongDoubleFormat = Opts.PPCIEEELongDouble
? &llvm::APFloat::IEEEquad()
: &llvm::APFloat::PPCDoubleDouble();
+ Opts.IEEE128 = 1;
}
ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {
diff --git a/src/llvm-project/clang/lib/Basic/Targets/PPC.h b/src/llvm-project/clang/lib/Basic/Targets/PPC.h
index 56c8f33..7c14a4e 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/PPC.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/PPC.h
@@ -59,6 +59,8 @@
// Target cpu features.
bool HasAltivec = false;
bool HasMMA = false;
+ bool HasROPProtect = false;
+ bool HasPrivileged = false;
bool HasVSX = false;
bool HasP8Vector = false;
bool HasP8Crypto = false;
@@ -71,6 +73,10 @@
bool PairedVectorMemops = false;
bool HasP10Vector = false;
bool HasPCRelativeMemops = false;
+ bool HasPrefixInstrs = false;
+ bool IsISA2_07 = false;
+ bool IsISA3_0 = false;
+ bool IsISA3_1 = false;
protected:
std::string ABI;
@@ -86,7 +92,7 @@
}
// Set the language option for altivec based on our value.
- void adjust(LangOptions &Opts) override;
+ void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
// Note: GCC recognizes the following additional cpus:
// 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801,
@@ -427,7 +433,7 @@
}
if (Triple.isOSAIX() || Triple.isOSLinux())
- DataLayout += "-v256:256:256-v512:512:512";
+ DataLayout += "-S128-v256:256:256-v512:512:512";
resetDataLayout(DataLayout);
// PPC64 supports atomics up to 8 bytes.
@@ -451,6 +457,8 @@
switch (CC) {
case CC_Swift:
return CCCR_OK;
+ case CC_SwiftAsync:
+ return CCCR_Error;
default:
return CCCR_Warning;
}
@@ -466,7 +474,7 @@
BoolWidth = BoolAlign = 32; // XXX support -mone-byte-bool?
PtrDiffType = SignedInt; // for http://llvm.org/bugs/show_bug.cgi?id=15726
LongLongAlign = 32;
- resetDataLayout("E-m:o-p:32:32-f64:32:64-n32");
+ resetDataLayout("E-m:o-p:32:32-f64:32:64-n32", "_");
}
BuiltinVaListKind getBuiltinVaListKind() const override {
@@ -480,7 +488,7 @@
DarwinPPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: DarwinTargetInfo<PPC64TargetInfo>(Triple, Opts) {
HasAlignMac68kSupport = true;
- resetDataLayout("E-m:o-i64:64-n32:64");
+ resetDataLayout("E-m:o-i64:64-n32:64", "_");
}
};
diff --git a/src/llvm-project/clang/lib/Basic/Targets/RISCV.cpp b/src/llvm-project/clang/lib/Basic/Targets/RISCV.cpp
index 786201ea..9705129 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/RISCV.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/RISCV.cpp
@@ -12,6 +12,7 @@
#include "RISCV.h"
#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/TargetParser.h"
@@ -30,7 +31,13 @@
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"};
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+
+ // Vector registers
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
return llvm::makeArrayRef(GCCRegNames);
}
@@ -80,9 +87,34 @@
// An address that is held in a general-purpose register.
Info.setAllowsMemory();
return true;
+ case 'S': // A symbolic address
+ Info.setAllowsRegister();
+ return true;
+ case 'v':
+ // A vector register.
+ if (Name[1] == 'r' || Name[1] == 'm') {
+ Info.setAllowsRegister();
+ Name += 1;
+ return true;
+ }
+ return false;
}
}
+std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
+ std::string R;
+ switch (*Constraint) {
+ case 'v':
+ R = std::string("v");
+ Constraint += 1;
+ break;
+ default:
+ R = TargetInfo::convertConstraint(Constraint);
+ break;
+ }
+ return R;
+}
+
void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ELF__");
@@ -197,6 +229,29 @@
Builder.defineMacro("__riscv_zvlsseg", "10000");
}
+const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
+#include "clang/Basic/BuiltinsRISCV.def"
+};
+
+ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
+ return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
+ Builtin::FirstTSBuiltin);
+}
+
+bool RISCVTargetInfo::initFeatureMap(
+ llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+
+ if (getTriple().getArch() == llvm::Triple::riscv64)
+ Features["64bit"] = true;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+}
+
/// Return true if has this feature, need to sync with handleTargetFeatures.
bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
@@ -204,6 +259,7 @@
.Case("riscv", true)
.Case("riscv32", !Is64Bit)
.Case("riscv64", Is64Bit)
+ .Case("64bit", Is64Bit)
.Case("m", HasM)
.Case("a", HasA)
.Case("f", HasF)
diff --git a/src/llvm-project/clang/lib/Basic/Targets/RISCV.h b/src/llvm-project/clang/lib/Basic/Targets/RISCV.h
index f1e9215..7e08465 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/RISCV.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/RISCV.h
@@ -47,6 +47,8 @@
bool HasZvamo = false;
bool HasZvlsseg = false;
+ static const Builtin::Info BuiltinInfo[];
+
public:
RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
@@ -56,6 +58,9 @@
SuitableAlign = 128;
WCharType = SignedInt;
WIntType = UnsignedInt;
+ HasRISCVVTypes = true;
+ MCountName = "_mcount";
+ HasFloat16 = true;
}
bool setCPU(const std::string &Name) override {
@@ -69,7 +74,7 @@
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
- ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override;
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
@@ -93,6 +98,13 @@
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override;
+ std::string convertConstraint(const char *&Constraint) const override;
+
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override;
+
bool hasFeature(StringRef Feature) const override;
bool handleTargetFeatures(std::vector<std::string> &Features,
diff --git a/src/llvm-project/clang/lib/Basic/Targets/SPIR.h b/src/llvm-project/clang/lib/Basic/Targets/SPIR.h
index a2e8126..50f34ab 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/SPIR.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/SPIR.h
@@ -21,7 +21,7 @@
namespace clang {
namespace targets {
-static const unsigned SPIRAddrSpaceMap[] = {
+static const unsigned SPIRDefIsPrivMap[] = {
0, // Default
1, // opencl_global
3, // opencl_local
@@ -33,6 +33,35 @@
0, // cuda_device
0, // cuda_constant
0, // cuda_shared
+ // SYCL address space values for this map are dummy
+ 0, // sycl_global
+ 0, // sycl_global_device
+ 0, // sycl_global_host
+ 0, // sycl_local
+ 0, // sycl_private
+ 0, // ptr32_sptr
+ 0, // ptr32_uptr
+ 0 // ptr64
+};
+
+static const unsigned SPIRDefIsGenMap[] = {
+ 4, // Default
+ // OpenCL address space values for this map are dummy and they can't be used
+ 0, // opencl_global
+ 0, // opencl_local
+ 0, // opencl_constant
+ 0, // opencl_private
+ 0, // opencl_generic
+ 0, // opencl_global_device
+ 0, // opencl_global_host
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0, // cuda_shared
+ 1, // sycl_global
+ 5, // sycl_global_device
+ 6, // sycl_global_host
+ 3, // sycl_local
+ 0, // sycl_private
0, // ptr32_sptr
0, // ptr32_uptr
0 // ptr64
@@ -49,7 +78,7 @@
TLSSupported = false;
VLASupported = false;
LongWidth = LongAlign = 64;
- AddrSpaceMap = &SPIRAddrSpaceMap;
+ AddrSpaceMap = &SPIRDefIsPrivMap;
UseAddrSpaceMapMangling = true;
HasLegalHalfType = true;
HasFloat16 = true;
@@ -88,6 +117,11 @@
return TargetInfo::VoidPtrBuiltinVaList;
}
+ Optional<unsigned>
+ getDWARFAddressSpace(unsigned AddressSpace) const override {
+ return AddressSpace;
+ }
+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
: CCCR_Warning;
@@ -97,6 +131,22 @@
return CC_SpirFunction;
}
+ void setAddressSpaceMap(bool DefaultIsGeneric) {
+ AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap;
+ }
+
+ void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override {
+ TargetInfo::adjust(Diags, Opts);
+ // FIXME: SYCL specification considers unannotated pointers and references
+ // to be pointing to the generic address space. See section 5.9.3 of
+ // SYCL 2020 specification.
+ // Currently, there is no way of representing SYCL's default address space
+ // language semantic along with the semantics of embedded C's default
+ // address space in the same address space map. Hence the map needs to be
+ // reset to allow mapping to the desired value of 'Default' entry for SYCL.
+ setAddressSpaceMap(/*DefaultIsGeneric=*/Opts.SYCLIsDevice);
+ }
+
void setSupportedOpenCLOpts() override {
// Assume all OpenCL extensions and optional core features are supported
// for SPIR since it is a generic target.
@@ -107,6 +157,7 @@
bool hasInt128Type() const override { return false; }
};
+
class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
public:
SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
diff --git a/src/llvm-project/clang/lib/Basic/Targets/SystemZ.cpp b/src/llvm-project/clang/lib/Basic/Targets/SystemZ.cpp
index ad3915e..e3e0da2 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/SystemZ.cpp
@@ -92,7 +92,8 @@
{{"arch10"}, 10}, {{"zEC12"}, 10},
{{"arch11"}, 11}, {{"z13"}, 11},
{{"arch12"}, 12}, {{"z14"}, 12},
- {{"arch13"}, 13}, {{"z15"}, 13}
+ {{"arch13"}, 13}, {{"z15"}, 13},
+ {{"arch14"}, 14}
};
int SystemZTargetInfo::getISARevision(StringRef Name) const {
@@ -120,6 +121,7 @@
.Case("arch11", ISARevision >= 11)
.Case("arch12", ISARevision >= 12)
.Case("arch13", ISARevision >= 13)
+ .Case("arch14", ISARevision >= 14)
.Case("htm", HasTransactionalExecution)
.Case("vx", HasVector)
.Default(false);
@@ -144,7 +146,7 @@
if (HasVector)
Builder.defineMacro("__VX__");
if (Opts.ZVector)
- Builder.defineMacro("__VEC__", "10303");
+ Builder.defineMacro("__VEC__", "10304");
}
ArrayRef<Builtin::Info> SystemZTargetInfo::getTargetBuiltins() const {
diff --git a/src/llvm-project/clang/lib/Basic/Targets/SystemZ.h b/src/llvm-project/clang/lib/Basic/Targets/SystemZ.h
index 39fdcf9..b749c3f 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/SystemZ.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/SystemZ.h
@@ -108,6 +108,8 @@
Features["vector-enhancements-1"] = true;
if (ISARevision >= 13)
Features["vector-enhancements-2"] = true;
+ if (ISARevision >= 14)
+ Features["nnp-assist"] = true;
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
@@ -143,6 +145,8 @@
case CC_Swift:
case CC_OpenCLKernel:
return CCCR_OK;
+ case CC_SwiftAsync:
+ return CCCR_Error;
default:
return CCCR_Warning;
}
diff --git a/src/llvm-project/clang/lib/Basic/Targets/TCE.h b/src/llvm-project/clang/lib/Basic/Targets/TCE.h
index 445fe4f..251b4d4 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/TCE.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/TCE.h
@@ -42,6 +42,11 @@
0, // cuda_device
0, // cuda_constant
0, // cuda_shared
+ 0, // sycl_global
+ 0, // sycl_global_device
+ 0, // sycl_global_host
+ 0, // sycl_local
+ 0, // sycl_private
0, // ptr32_sptr
0, // ptr32_uptr
0, // ptr64
diff --git a/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.cpp b/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.cpp
index 87fa49b..7ef7984 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.cpp
@@ -234,6 +234,16 @@
Builtin::FirstTSBuiltin);
}
+void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags,
+ LangOptions &Opts) {
+ // If the Atomics feature isn't available, turn off POSIXThreads and
+ // ThreadModel, so that we don't predefine _REENTRANT or __STDCPP_THREADS__.
+ if (!HasAtomics) {
+ Opts.POSIXThreads = false;
+ Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
+ }
+}
+
void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
diff --git a/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.h b/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.h
index bab936f..4a5ba25 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.h
@@ -129,6 +129,8 @@
case CC_C:
case CC_Swift:
return CCCR_OK;
+ case CC_SwiftAsync:
+ return CCCR_Error;
default:
return CCCR_Warning;
}
@@ -137,6 +139,8 @@
bool hasExtIntType() const override { return true; }
bool hasProtectedVisibility() const override { return false; }
+
+ void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
};
class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo
@@ -145,7 +149,10 @@
explicit WebAssembly32TargetInfo(const llvm::Triple &T,
const TargetOptions &Opts)
: WebAssemblyTargetInfo(T, Opts) {
- resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128");
+ if (T.isOSEmscripten())
+ resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32:64-S128-ni:1:10:20");
+ else
+ resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20");
}
protected:
@@ -164,7 +171,10 @@
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
IntPtrType = SignedLong;
- resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
+ if (T.isOSEmscripten())
+ resetDataLayout("e-m:e-p:64:64-i64:64-f128:64-n32:64-S128-ni:1:10:20");
+ else
+ resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20");
}
protected:
diff --git a/src/llvm-project/clang/lib/Basic/Targets/X86.cpp b/src/llvm-project/clang/lib/Basic/Targets/X86.cpp
index c5ad1c7..9db96c2 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/X86.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/X86.cpp
@@ -117,7 +117,20 @@
for (auto &F : CPUFeatures)
setFeatureEnabled(Features, F, true);
- if (!TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec))
+ std::vector<std::string> UpdatedFeaturesVec;
+ for (const auto &Feature : FeaturesVec) {
+ // Expand general-regs-only to -x86, -mmx and -sse
+ if (Feature == "+general-regs-only") {
+ UpdatedFeaturesVec.push_back("-x87");
+ UpdatedFeaturesVec.push_back("-mmx");
+ UpdatedFeaturesVec.push_back("-sse");
+ continue;
+ }
+
+ UpdatedFeaturesVec.push_back(Feature);
+ }
+
+ if (!TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec))
return false;
// Can't do this earlier because we need to be able to explicitly enable
@@ -126,20 +139,20 @@
// Enable popcnt if sse4.2 is enabled and popcnt is not explicitly disabled.
auto I = Features.find("sse4.2");
if (I != Features.end() && I->getValue() &&
- llvm::find(FeaturesVec, "-popcnt") == FeaturesVec.end())
+ llvm::find(UpdatedFeaturesVec, "-popcnt") == UpdatedFeaturesVec.end())
Features["popcnt"] = true;
// Additionally, if SSE is enabled and mmx is not explicitly disabled,
// then enable MMX.
I = Features.find("sse");
if (I != Features.end() && I->getValue() &&
- llvm::find(FeaturesVec, "-mmx") == FeaturesVec.end())
+ llvm::find(UpdatedFeaturesVec, "-mmx") == UpdatedFeaturesVec.end())
Features["mmx"] = true;
// Enable xsave if avx is enabled and xsave is not explicitly disabled.
I = Features.find("avx");
if (I != Features.end() && I->getValue() &&
- llvm::find(FeaturesVec, "-xsave") == FeaturesVec.end())
+ llvm::find(UpdatedFeaturesVec, "-xsave") == UpdatedFeaturesVec.end())
Features["xsave"] = true;
return true;
@@ -467,6 +480,7 @@
case CK_Cooperlake:
case CK_Cannonlake:
case CK_IcelakeClient:
+ case CK_Rocketlake:
case CK_IcelakeServer:
case CK_Tigerlake:
case CK_SapphireRapids:
@@ -865,6 +879,7 @@
.Case("fma4", true)
.Case("fsgsbase", true)
.Case("fxsr", true)
+ .Case("general-regs-only", true)
.Case("gfni", true)
.Case("hreset", true)
.Case("invpcid", true)
@@ -1315,6 +1330,7 @@
case CK_Tigerlake:
case CK_SapphireRapids:
case CK_IcelakeClient:
+ case CK_Rocketlake:
case CK_IcelakeServer:
case CK_Alderlake:
case CK_KNL:
@@ -1397,13 +1413,13 @@
return Size <= 64;
case 'z':
// XMM0/YMM/ZMM0
- if (FeatureMap.lookup("avx512f"))
+ if (hasFeatureEnabled(FeatureMap, "avx512f"))
// ZMM0 can be used if target supports AVX512F.
return Size <= 512U;
- else if (FeatureMap.lookup("avx"))
+ else if (hasFeatureEnabled(FeatureMap, "avx"))
// YMM0 can be used if target supports AVX.
return Size <= 256U;
- else if (FeatureMap.lookup("sse"))
+ else if (hasFeatureEnabled(FeatureMap, "sse"))
return Size <= 128U;
return false;
case 'i':
@@ -1417,10 +1433,10 @@
break;
case 'v':
case 'x':
- if (FeatureMap.lookup("avx512f"))
+ if (hasFeatureEnabled(FeatureMap, "avx512f"))
// 512-bit zmm registers can be used if target supports AVX512F.
return Size <= 512U;
- else if (FeatureMap.lookup("avx"))
+ else if (hasFeatureEnabled(FeatureMap, "avx"))
// 256-bit ymm registers can be used if target supports AVX.
return Size <= 256U;
return Size <= 128U;
diff --git a/src/llvm-project/clang/lib/Basic/Targets/X86.h b/src/llvm-project/clang/lib/Basic/Targets/X86.h
index 91a365c..fcaaf50 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/X86.h
+++ b/src/llvm-project/clang/lib/Basic/Targets/X86.h
@@ -35,6 +35,11 @@
0, // cuda_device
0, // cuda_constant
0, // cuda_shared
+ 0, // sycl_global
+ 0, // sycl_global_device
+ 0, // sycl_global_host
+ 0, // sycl_local
+ 0, // sycl_private
270, // ptr32_sptr
271, // ptr32_uptr
272 // ptr64
@@ -333,6 +338,10 @@
bool setFPMath(StringRef Name) override;
+ bool supportsExtendIntArgs() const override {
+ return getTriple().getArch() != llvm::Triple::x86;
+ }
+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
// Most of the non-ARM calling conventions are i386 conventions.
switch (CC) {
@@ -348,11 +357,15 @@
case CC_IntelOclBicc:
case CC_OpenCLKernel:
return CCCR_OK;
+ case CC_SwiftAsync:
+ return CCCR_Error;
default:
return CCCR_Warning;
}
}
+ bool checkArithmeticFenceSupported() const override { return true; }
+
CallingConv getDefaultCallingConv() const override {
return CC_C;
}
@@ -383,11 +396,13 @@
LongDoubleWidth = 96;
LongDoubleAlign = 32;
SuitableAlign = 128;
- resetDataLayout(Triple.isOSBinFormatMachO() ?
- "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-"
- "f80:32-n8:16:32-S128" :
- "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-"
- "f80:32-n8:16:32-S128");
+ resetDataLayout(
+ Triple.isOSBinFormatMachO()
+ ? "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-"
+ "f80:32-n8:16:32-S128"
+ : "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-"
+ "f80:32-n8:16:32-S128",
+ Triple.isOSBinFormatMachO() ? "_" : "");
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
IntPtrType = SignedInt;
@@ -491,7 +506,7 @@
SizeType = UnsignedLong;
IntPtrType = SignedLong;
resetDataLayout("e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-"
- "f80:128-n8:16:32-S128");
+ "f80:128-n8:16:32-S128", "_");
HasAlignMac68kSupport = true;
}
@@ -519,7 +534,8 @@
resetDataLayout(IsWinCOFF ? "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:"
"64-i64:64-f80:32-n8:16:32-a:0:32-S32"
: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:"
- "64-i64:64-f80:32-n8:16:32-a:0:32-S32");
+ "64-i64:64-f80:32-n8:16:32-a:0:32-S32",
+ IsWinCOFF ? "_" : "");
}
};
@@ -568,7 +584,8 @@
this->WCharType = TargetInfo::UnsignedShort;
DoubleAlign = LongLongAlign = 64;
resetDataLayout("e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:"
- "32-n8:16:32-a:0:32-S32");
+ "32-n8:16:32-a:0:32-S32",
+ "_");
}
void getTargetDefines(const LangOptions &Opts,
@@ -648,7 +665,7 @@
public:
X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: X86TargetInfo(Triple, Opts) {
- const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32;
+ const bool IsX32 = getTriple().isX32();
bool IsWinCOFF =
getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;
@@ -702,6 +719,7 @@
switch (CC) {
case CC_C:
case CC_Swift:
+ case CC_SwiftAsync:
case CC_X86VectorCall:
case CC_IntelOclBicc:
case CC_Win64:
@@ -783,6 +801,7 @@
case CC_PreserveAll:
case CC_X86_64SysV:
case CC_Swift:
+ case CC_SwiftAsync:
case CC_X86RegCall:
case CC_OpenCLKernel:
return CCCR_OK;
@@ -863,7 +882,7 @@
if (T.isiOS())
UseSignedCharForObjCBool = false;
resetDataLayout("e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:"
- "16:32:64-S128");
+ "16:32:64-S128", "_");
}
bool handleTargetFeatures(std::vector<std::string> &Features,
diff --git a/src/llvm-project/clang/lib/Basic/Targets/XCore.cpp b/src/llvm-project/clang/lib/Basic/Targets/XCore.cpp
index da614f1..ba64f15 100644
--- a/src/llvm-project/clang/lib/Basic/Targets/XCore.cpp
+++ b/src/llvm-project/clang/lib/Basic/Targets/XCore.cpp
@@ -28,6 +28,7 @@
void XCoreTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
+ Builder.defineMacro("__xcore__");
Builder.defineMacro("__XS1B__");
}
diff --git a/src/llvm-project/clang/lib/Basic/XRayInstr.cpp b/src/llvm-project/clang/lib/Basic/XRayInstr.cpp
index 79052e05..822e14b 100644
--- a/src/llvm-project/clang/lib/Basic/XRayInstr.cpp
+++ b/src/llvm-project/clang/lib/Basic/XRayInstr.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/XRayInstr.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
namespace clang {
@@ -30,4 +31,30 @@
return ParsedKind;
}
+void serializeXRayInstrValue(XRayInstrSet Set,
+ SmallVectorImpl<StringRef> &Values) {
+ if (Set.Mask == XRayInstrKind::All) {
+ Values.push_back("all");
+ return;
+ }
+
+ if (Set.Mask == XRayInstrKind::None) {
+ Values.push_back("none");
+ return;
+ }
+
+ if (Set.has(XRayInstrKind::Custom))
+ Values.push_back("custom");
+
+ if (Set.has(XRayInstrKind::Typed))
+ Values.push_back("typed");
+
+ if (Set.has(XRayInstrKind::FunctionEntry) &&
+ Set.has(XRayInstrKind::FunctionExit))
+ Values.push_back("function");
+ else if (Set.has(XRayInstrKind::FunctionEntry))
+ Values.push_back("function-entry");
+ else if (Set.has(XRayInstrKind::FunctionExit))
+ Values.push_back("function-exit");
+}
} // namespace clang
diff --git a/src/llvm-project/clang/lib/CMakeLists.txt b/src/llvm-project/clang/lib/CMakeLists.txt
index be09c0c..2b49fb9 100644
--- a/src/llvm-project/clang/lib/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/CMakeLists.txt
@@ -25,3 +25,4 @@
add_subdirectory(StaticAnalyzer)
add_subdirectory(Format)
add_subdirectory(Testing)
+add_subdirectory(Interpreter)
diff --git a/src/llvm-project/clang/lib/CodeGen/BackendUtil.cpp b/src/llvm-project/clang/lib/CodeGen/BackendUtil.cpp
index 52bcd97..481f534 100644
--- a/src/llvm-project/clang/lib/CodeGen/BackendUtil.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/BackendUtil.cpp
@@ -65,6 +65,7 @@
#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
+#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
@@ -76,14 +77,15 @@
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h"
#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
+#include "llvm/Transforms/Utils/Debugify.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
#include "llvm/Transforms/Utils/SymbolRewriter.h"
-#include "llvm/Transforms/Utils/UniqueInternalLinkageNames.h"
#include <memory>
using namespace clang;
using namespace llvm;
@@ -243,7 +245,7 @@
auto Opts = getSancovOptsFromCGOpts(CGOpts);
PM.add(createModuleSanitizerCoverageLegacyPassPass(
Opts, CGOpts.SanitizeCoverageAllowlistFiles,
- CGOpts.SanitizeCoverageBlocklistFiles));
+ CGOpts.SanitizeCoverageIgnorelistFiles));
}
// Check if ASan should use GC-friendly instrumentation for globals.
@@ -286,16 +288,21 @@
bool UseAfterScope = CGOpts.SanitizeAddressUseAfterScope;
bool UseOdrIndicator = CGOpts.SanitizeAddressUseOdrIndicator;
bool UseGlobalsGC = asanUseGlobalsGC(T, CGOpts);
+ llvm::AsanDtorKind DestructorKind = CGOpts.getSanitizeAddressDtor();
+ llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn =
+ CGOpts.getSanitizeAddressUseAfterReturn();
PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/ false, Recover,
- UseAfterScope));
+ UseAfterScope, UseAfterReturn));
PM.add(createModuleAddressSanitizerLegacyPassPass(
- /*CompileKernel*/ false, Recover, UseGlobalsGC, UseOdrIndicator));
+ /*CompileKernel*/ false, Recover, UseGlobalsGC, UseOdrIndicator,
+ DestructorKind));
}
static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
PM.add(createAddressSanitizerFunctionPass(
- /*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false));
+ /*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false,
+ /*UseAfterReturn*/ llvm::AsanDetectStackUseAfterReturnMode::Never));
PM.add(createModuleAddressSanitizerLegacyPassPass(
/*CompileKernel*/ true, /*Recover*/ true, /*UseGlobalsGC*/ true,
/*UseOdrIndicator*/ false));
@@ -307,14 +314,19 @@
static_cast<const PassManagerBuilderWrapper &>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress);
- PM.add(
- createHWAddressSanitizerLegacyPassPass(/*CompileKernel*/ false, Recover));
+ PM.add(createHWAddressSanitizerLegacyPassPass(
+ /*CompileKernel*/ false, Recover,
+ /*DisableOptimization*/ CGOpts.OptimizationLevel == 0));
}
static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
- legacy::PassManagerBase &PM) {
+ legacy::PassManagerBase &PM) {
+ const PassManagerBuilderWrapper &BuilderWrapper =
+ static_cast<const PassManagerBuilderWrapper &>(Builder);
+ const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
PM.add(createHWAddressSanitizerLegacyPassPass(
- /*CompileKernel*/ true, /*Recover*/ true));
+ /*CompileKernel*/ true, /*Recover*/ true,
+ /*DisableOptimization*/ CGOpts.OptimizationLevel == 0));
}
static void addGeneralOptsForMemorySanitizer(const PassManagerBuilder &Builder,
@@ -361,8 +373,18 @@
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper&>(Builder);
const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
- PM.add(
- createDataFlowSanitizerLegacyPassPass(LangOpts.SanitizerBlacklistFiles));
+ PM.add(createDataFlowSanitizerLegacyPassPass(LangOpts.NoSanitizeFiles));
+}
+
+static void addEntryExitInstrumentationPass(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ PM.add(createEntryExitInstrumenterPass());
+}
+
+static void
+addPostInlineEntryExitInstrumentationPass(const PassManagerBuilder &Builder,
+ legacy::PassManagerBase &PM) {
+ PM.add(createPostInlineEntryExitInstrumenterPass());
}
static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
@@ -389,6 +411,10 @@
case CodeGenOptions::SVML:
TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML);
break;
+ case CodeGenOptions::Darwin_libsystem_m:
+ TLII->addVectorizableFunctionsFromVecLib(
+ TargetLibraryInfoImpl::DarwinLibSystemM);
+ break;
default:
break;
}
@@ -513,7 +539,6 @@
Options.NoNaNsFPMath = LangOpts.NoHonorNaNs;
Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
Options.UnsafeFPMath = LangOpts.UnsafeFPMath;
- Options.StackAlignmentOverride = CodeGenOpts.StackAlignment;
Options.BBSections =
llvm::StringSwitch<llvm::BasicBlockSection>(CodeGenOpts.BBSections)
@@ -537,23 +562,16 @@
Options.EnableMachineFunctionSplitter = CodeGenOpts.SplitMachineFunctions;
Options.FunctionSections = CodeGenOpts.FunctionSections;
Options.DataSections = CodeGenOpts.DataSections;
- Options.IgnoreXCOFFVisibility = CodeGenOpts.IgnoreXCOFFVisibility;
+ Options.IgnoreXCOFFVisibility = LangOpts.IgnoreXCOFFVisibility;
Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames;
Options.UniqueBasicBlockSectionNames =
CodeGenOpts.UniqueBasicBlockSectionNames;
- Options.StackProtectorGuard =
- llvm::StringSwitch<llvm::StackProtectorGuards>(CodeGenOpts
- .StackProtectorGuard)
- .Case("tls", llvm::StackProtectorGuards::TLS)
- .Case("global", llvm::StackProtectorGuards::Global)
- .Default(llvm::StackProtectorGuards::None);
- Options.StackProtectorGuardOffset = CodeGenOpts.StackProtectorGuardOffset;
- Options.StackProtectorGuardReg = CodeGenOpts.StackProtectorGuardReg;
Options.TLSSize = CodeGenOpts.TLSSize;
Options.EmulatedTLS = CodeGenOpts.EmulatedTLS;
Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS;
Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
+ Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;
Options.EmitAddrsig = CodeGenOpts.Addrsig;
Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;
@@ -585,6 +603,7 @@
Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path);
Options.MCOptions.Argv0 = CodeGenOpts.Argv0;
Options.MCOptions.CommandLineArgs = CodeGenOpts.CommandLineArgs;
+ Options.DebugStrictDwarf = CodeGenOpts.DebugStrictDwarf;
return true;
}
@@ -716,9 +735,7 @@
addBoundsCheckingPass);
}
- if (CodeGenOpts.SanitizeCoverageType ||
- CodeGenOpts.SanitizeCoverageIndirectCalls ||
- CodeGenOpts.SanitizeCoverageTraceCmp) {
+ if (CodeGenOpts.hasSanitizeCoverage()) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addSanitizerCoveragePass);
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
@@ -781,6 +798,20 @@
addDataFlowSanitizerPass);
}
+ if (CodeGenOpts.InstrumentFunctions ||
+ CodeGenOpts.InstrumentFunctionEntryBare ||
+ CodeGenOpts.InstrumentFunctionsAfterInlining ||
+ CodeGenOpts.InstrumentForProfiling) {
+ PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
+ addEntryExitInstrumentationPass);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addEntryExitInstrumentationPass);
+ PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
+ addPostInlineEntryExitInstrumentationPass);
+ PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
+ addPostInlineEntryExitInstrumentationPass);
+ }
+
// Set up the per-function pass manager.
FPM.add(new TargetLibraryInfoWrapperPass(*TLII));
if (CodeGenOpts.VerifyModule)
@@ -790,12 +821,6 @@
if (!CodeGenOpts.RewriteMapFiles.empty())
addSymbolRewriterPass(CodeGenOpts, &MPM);
- // Add UniqueInternalLinkageNames Pass which renames internal linkage symbols
- // with unique names.
- if (CodeGenOpts.UniqueInternalLinkageNames) {
- MPM.add(createUniqueInternalLinkageNamesPass());
- }
-
if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts, LangOpts)) {
MPM.add(createGCOVProfilerPass(*Options));
if (CodeGenOpts.getDebugInfo() == codegenoptions::NoDebugInfo)
@@ -850,7 +875,15 @@
BackendArgs.push_back("-limit-float-precision");
BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());
}
+ // Check for the default "clang" invocation that won't set any cl::opt values.
+ // Skip trying to parse the command line invocation to avoid the issues
+ // described below.
+ if (BackendArgs.size() == 1)
+ return;
BackendArgs.push_back(nullptr);
+ // FIXME: The command line parser below is not thread-safe and shares a global
+ // state, so this call might crash or overwrite the options of another Clang
+ // instance in the same process.
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
BackendArgs.data());
}
@@ -925,7 +958,16 @@
if (TM)
TheModule->setDataLayout(TM->createDataLayout());
- legacy::PassManager PerModulePasses;
+ DebugifyCustomPassManager PerModulePasses;
+ DebugInfoPerPassMap DIPreservationMap;
+ if (CodeGenOpts.EnableDIPreservationVerify) {
+ PerModulePasses.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
+ PerModulePasses.setDIPreservationMap(DIPreservationMap);
+
+ if (!CodeGenOpts.DIBugsReportFilePath.empty())
+ PerModulePasses.setOrigDIVerifyBugsReportFilePath(
+ CodeGenOpts.DIBugsReportFilePath);
+ }
PerModulePasses.add(
createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
@@ -1058,6 +1100,89 @@
}
}
+static void addSanitizers(const Triple &TargetTriple,
+ const CodeGenOptions &CodeGenOpts,
+ const LangOptions &LangOpts, PassBuilder &PB) {
+ PB.registerOptimizerLastEPCallback([&](ModulePassManager &MPM,
+ PassBuilder::OptimizationLevel Level) {
+ if (CodeGenOpts.hasSanitizeCoverage()) {
+ auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
+ MPM.addPass(ModuleSanitizerCoveragePass(
+ SancovOpts, CodeGenOpts.SanitizeCoverageAllowlistFiles,
+ CodeGenOpts.SanitizeCoverageIgnorelistFiles));
+ }
+
+ auto MSanPass = [&](SanitizerMask Mask, bool CompileKernel) {
+ if (LangOpts.Sanitize.has(Mask)) {
+ int TrackOrigins = CodeGenOpts.SanitizeMemoryTrackOrigins;
+ bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
+
+ MPM.addPass(
+ MemorySanitizerPass({TrackOrigins, Recover, CompileKernel}));
+ FunctionPassManager FPM;
+ FPM.addPass(
+ MemorySanitizerPass({TrackOrigins, Recover, CompileKernel}));
+ if (Level != PassBuilder::OptimizationLevel::O0) {
+ // MemorySanitizer inserts complex instrumentation that mostly
+ // follows the logic of the original code, but operates on
+ // "shadow" values. It can benefit from re-running some
+ // general purpose optimization passes.
+ FPM.addPass(EarlyCSEPass());
+ // TODO: Consider add more passes like in
+ // addGeneralOptsForMemorySanitizer. EarlyCSEPass makes visible
+ // difference on size. It's not clear if the rest is still
+ // usefull. InstCombinePass breakes
+ // compiler-rt/test/msan/select_origin.cpp.
+ }
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ }
+ };
+ MSanPass(SanitizerKind::Memory, false);
+ MSanPass(SanitizerKind::KernelMemory, true);
+
+ if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
+ MPM.addPass(ThreadSanitizerPass());
+ MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
+ }
+
+ auto ASanPass = [&](SanitizerMask Mask, bool CompileKernel) {
+ if (LangOpts.Sanitize.has(Mask)) {
+ bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
+ bool UseAfterScope = CodeGenOpts.SanitizeAddressUseAfterScope;
+ bool ModuleUseAfterScope = asanUseGlobalsGC(TargetTriple, CodeGenOpts);
+ bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator;
+ llvm::AsanDtorKind DestructorKind =
+ CodeGenOpts.getSanitizeAddressDtor();
+ llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn =
+ CodeGenOpts.getSanitizeAddressUseAfterReturn();
+ MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
+ MPM.addPass(ModuleAddressSanitizerPass(
+ CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator,
+ DestructorKind));
+ MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
+ CompileKernel, Recover, UseAfterScope, UseAfterReturn)));
+ }
+ };
+ ASanPass(SanitizerKind::Address, false);
+ ASanPass(SanitizerKind::KernelAddress, true);
+
+ auto HWASanPass = [&](SanitizerMask Mask, bool CompileKernel) {
+ if (LangOpts.Sanitize.has(Mask)) {
+ bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
+ MPM.addPass(HWAddressSanitizerPass(
+ CompileKernel, Recover,
+ /*DisableOptimization=*/CodeGenOpts.OptimizationLevel == 0));
+ }
+ };
+ HWASanPass(SanitizerKind::HWAddress, false);
+ HWASanPass(SanitizerKind::KernelHWAddress, true);
+
+ if (LangOpts.Sanitize.has(SanitizerKind::DataFlow)) {
+ MPM.addPass(DataFlowSanitizerPass(LangOpts.NoSanitizeFiles));
+ }
+ });
+}
+
/// A clean version of `EmitAssembly` that uses the new pass manager.
///
/// Not all features are currently supported in this system, but where
@@ -1147,13 +1272,22 @@
// Only enable CGProfilePass when using integrated assembler, since
// non-integrated assemblers don't recognize .cgprofile section.
PTO.CallGraphProfile = !CodeGenOpts.DisableIntegratedAS;
- PTO.Coroutines = LangOpts.Coroutines;
- PTO.UniqueLinkageNames = CodeGenOpts.UniqueInternalLinkageNames;
+ LoopAnalysisManager LAM;
+ FunctionAnalysisManager FAM;
+ CGSCCAnalysisManager CGAM;
+ ModuleAnalysisManager MAM;
+
+ bool DebugPassStructure = CodeGenOpts.DebugPass == "Structure";
PassInstrumentationCallbacks PIC;
- StandardInstrumentations SI(CodeGenOpts.DebugPassManager);
- SI.registerCallbacks(PIC);
- PassBuilder PB(CodeGenOpts.DebugPassManager, TM.get(), PTO, PGOOpt, &PIC);
+ PrintPassOptions PrintPassOpts;
+ PrintPassOpts.Indent = DebugPassStructure;
+ PrintPassOpts.SkipAnalyses = DebugPassStructure;
+ StandardInstrumentations SI(CodeGenOpts.DebugPassManager ||
+ DebugPassStructure,
+ /*VerifyEach*/ false, PrintPassOpts);
+ SI.registerCallbacks(PIC, &FAM);
+ PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC);
// Attempt to load pass plugins and register their callbacks with PB.
for (auto &PluginFN : CodeGenOpts.PassPlugins) {
@@ -1169,11 +1303,6 @@
get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
#include "llvm/Support/Extension.def"
- LoopAnalysisManager LAM(CodeGenOpts.DebugPassManager);
- FunctionAnalysisManager FAM(CodeGenOpts.DebugPassManager);
- CGSCCAnalysisManager CGAM(CodeGenOpts.DebugPassManager);
- ModuleAnalysisManager MAM(CodeGenOpts.DebugPassManager);
-
// Register the AA manager first so that our version is the one used.
FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
@@ -1191,7 +1320,7 @@
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
- ModulePassManager MPM(CodeGenOpts.DebugPassManager);
+ ModulePassManager MPM;
if (!CodeGenOpts.DisableLLVMPasses) {
// Map our optimization levels into one of the distinct levels used to
@@ -1222,10 +1351,11 @@
// If we reached here with a non-empty index file name, then the index
// file was empty and we are not performing ThinLTO backend compilation
- // (used in testing in a distributed build environment). Drop any the type
- // test assume sequences inserted for whole program vtables so that
- // codegen doesn't complain.
- if (!CodeGenOpts.ThinLTOIndexFile.empty())
+ // (used in testing in a distributed build environment).
+ bool IsThinLTOPostLink = !CodeGenOpts.ThinLTOIndexFile.empty();
+ // If so drop any the type test assume sequences inserted for whole program
+ // vtables so that codegen doesn't complain.
+ if (IsThinLTOPostLink)
PB.registerPipelineStartEPCallback(
[](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr,
@@ -1233,12 +1363,20 @@
/*DropTypeTests=*/true));
});
- if (Level != PassBuilder::OptimizationLevel::O0) {
+ if (CodeGenOpts.InstrumentFunctions ||
+ CodeGenOpts.InstrumentFunctionEntryBare ||
+ CodeGenOpts.InstrumentFunctionsAfterInlining ||
+ CodeGenOpts.InstrumentForProfiling) {
PB.registerPipelineStartEPCallback(
[](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
MPM.addPass(createModuleToFunctionPassAdaptor(
EntryExitInstrumenterPass(/*PostInlining=*/false)));
});
+ PB.registerOptimizerLastEPCallback(
+ [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
+ MPM.addPass(createModuleToFunctionPassAdaptor(
+ EntryExitInstrumenterPass(/*PostInlining=*/true)));
+ });
}
// Register callbacks to schedule sanitizer passes at the appropriate part
@@ -1249,81 +1387,10 @@
FPM.addPass(BoundsCheckingPass());
});
- if (CodeGenOpts.SanitizeCoverageType ||
- CodeGenOpts.SanitizeCoverageIndirectCalls ||
- CodeGenOpts.SanitizeCoverageTraceCmp) {
- PB.registerOptimizerLastEPCallback(
- [this](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
- auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
- MPM.addPass(ModuleSanitizerCoveragePass(
- SancovOpts, CodeGenOpts.SanitizeCoverageAllowlistFiles,
- CodeGenOpts.SanitizeCoverageBlocklistFiles));
- });
- }
-
- if (LangOpts.Sanitize.has(SanitizerKind::Memory)) {
- int TrackOrigins = CodeGenOpts.SanitizeMemoryTrackOrigins;
- bool Recover = CodeGenOpts.SanitizeRecover.has(SanitizerKind::Memory);
- PB.registerOptimizerLastEPCallback(
- [TrackOrigins, Recover](ModulePassManager &MPM,
- PassBuilder::OptimizationLevel Level) {
- MPM.addPass(MemorySanitizerPass({TrackOrigins, Recover, false}));
- MPM.addPass(createModuleToFunctionPassAdaptor(
- MemorySanitizerPass({TrackOrigins, Recover, false})));
- });
- }
- if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
- PB.registerOptimizerLastEPCallback(
- [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
- MPM.addPass(ThreadSanitizerPass());
- MPM.addPass(
- createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
- });
- }
-
- auto ASanPass = [&](SanitizerMask Mask, bool CompileKernel) {
- if (LangOpts.Sanitize.has(Mask)) {
- bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
- bool UseAfterScope = CodeGenOpts.SanitizeAddressUseAfterScope;
- bool ModuleUseAfterScope = asanUseGlobalsGC(TargetTriple, CodeGenOpts);
- bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator;
- PB.registerOptimizerLastEPCallback(
- [CompileKernel, Recover, UseAfterScope, ModuleUseAfterScope,
- UseOdrIndicator](ModulePassManager &MPM,
- PassBuilder::OptimizationLevel Level) {
- MPM.addPass(
- RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
- MPM.addPass(ModuleAddressSanitizerPass(CompileKernel, Recover,
- ModuleUseAfterScope,
- UseOdrIndicator));
- MPM.addPass(createModuleToFunctionPassAdaptor(
- AddressSanitizerPass(CompileKernel, Recover, UseAfterScope)));
- });
- }
- };
- ASanPass(SanitizerKind::Address, false);
- ASanPass(SanitizerKind::KernelAddress, true);
-
- auto HWASanPass = [&](SanitizerMask Mask, bool CompileKernel) {
- if (LangOpts.Sanitize.has(Mask)) {
- bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);
- PB.registerOptimizerLastEPCallback(
- [CompileKernel, Recover](ModulePassManager &MPM,
- PassBuilder::OptimizationLevel Level) {
- MPM.addPass(HWAddressSanitizerPass(CompileKernel, Recover));
- });
- }
- };
- HWASanPass(SanitizerKind::HWAddress, false);
- HWASanPass(SanitizerKind::KernelHWAddress, true);
-
- if (LangOpts.Sanitize.has(SanitizerKind::DataFlow)) {
- PB.registerOptimizerLastEPCallback(
- [this](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
- MPM.addPass(
- DataFlowSanitizerPass(LangOpts.SanitizerBlacklistFiles));
- });
- }
+ // Don't add sanitizers if we are here from ThinLTO PostLink. That already
+ // done on PreLink stage.
+ if (!IsThinLTOPostLink)
+ addSanitizers(TargetTriple, CodeGenOpts, LangOpts, PB);
if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts, LangOpts))
PB.registerPipelineStartEPCallback(
@@ -1455,10 +1522,7 @@
// we should only invoke this using the individual indexes written out
// via a WriteIndexesThinBackend.
FunctionImporter::ImportMapTy ImportList;
- std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedImports;
- MapVector<llvm::StringRef, llvm::BitcodeModule> ModuleMap;
- if (!lto::loadReferencedModules(*M, *CombinedIndex, ImportList, ModuleMap,
- OwnedImports))
+ if (!lto::initImportList(*M, *CombinedIndex, ImportList))
return;
auto AddStream = [&](size_t Task) {
@@ -1535,7 +1599,7 @@
if (Error E =
thinBackend(Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
- ModuleMap, CGOpts.CmdArgs)) {
+ /* ModuleMap */ nullptr, CGOpts.CmdArgs)) {
handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';
});
@@ -1547,7 +1611,7 @@
const CodeGenOptions &CGOpts,
const clang::TargetOptions &TOpts,
const LangOptions &LOpts,
- const llvm::DataLayout &TDesc, Module *M,
+ StringRef TDesc, Module *M,
BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS) {
@@ -1601,11 +1665,11 @@
// DataLayout.
if (AsmHelper.TM) {
std::string DLDesc = M->getDataLayout().getStringRepresentation();
- if (DLDesc != TDesc.getStringRepresentation()) {
+ if (DLDesc != TDesc) {
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "backend data layout '%0' does not match "
"expected target description '%1'");
- Diags.Report(DiagID) << DLDesc << TDesc.getStringRepresentation();
+ Diags.Report(DiagID) << DLDesc << TDesc;
}
}
}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGAtomic.cpp b/src/llvm-project/clang/lib/CodeGen/CGAtomic.cpp
index c7256e2..b6722ad 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGAtomic.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGAtomic.cpp
@@ -85,7 +85,7 @@
(C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) *
lvalue.getAlignment();
VoidPtrAddr = CGF.Builder.CreateConstGEP1_64(
- VoidPtrAddr, OffsetInChars.getQuantity());
+ CGF.Int8Ty, VoidPtrAddr, OffsetInChars.getQuantity());
auto Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
VoidPtrAddr,
CGF.Builder.getIntNTy(AtomicSizeInBits)->getPointerTo(),
@@ -427,6 +427,8 @@
else
switch ((llvm::AtomicOrderingCABI)FOS) {
case llvm::AtomicOrderingCABI::relaxed:
+ // 31.7.2.18: "The failure argument shall not be memory_order_release
+ // nor memory_order_acq_rel". Fallback to monotonic.
case llvm::AtomicOrderingCABI::release:
case llvm::AtomicOrderingCABI::acq_rel:
FailureOrder = llvm::AtomicOrdering::Monotonic;
@@ -439,59 +441,48 @@
FailureOrder = llvm::AtomicOrdering::SequentiallyConsistent;
break;
}
- if (isStrongerThan(FailureOrder, SuccessOrder)) {
- // Don't assert on undefined behavior "failure argument shall be no
- // stronger than the success argument".
- FailureOrder =
- llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder);
- }
+ // Prior to c++17, "the failure argument shall be no stronger than the
+ // success argument". This condition has been lifted and the only
+ // precondition is 31.7.2.18. Effectively treat this as a DR and skip
+ // language version checks.
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
FailureOrder, Scope);
return;
}
// Create all the relevant BB's
- llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr,
- *SeqCstBB = nullptr;
- MonotonicBB = CGF.createBasicBlock("monotonic_fail", CGF.CurFn);
- if (SuccessOrder != llvm::AtomicOrdering::Monotonic &&
- SuccessOrder != llvm::AtomicOrdering::Release)
- AcquireBB = CGF.createBasicBlock("acquire_fail", CGF.CurFn);
- if (SuccessOrder == llvm::AtomicOrdering::SequentiallyConsistent)
- SeqCstBB = CGF.createBasicBlock("seqcst_fail", CGF.CurFn);
-
- llvm::BasicBlock *ContBB = CGF.createBasicBlock("atomic.continue", CGF.CurFn);
-
- llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(FailureOrderVal, MonotonicBB);
-
- // Emit all the different atomics
+ auto *MonotonicBB = CGF.createBasicBlock("monotonic_fail", CGF.CurFn);
+ auto *AcquireBB = CGF.createBasicBlock("acquire_fail", CGF.CurFn);
+ auto *SeqCstBB = CGF.createBasicBlock("seqcst_fail", CGF.CurFn);
+ auto *ContBB = CGF.createBasicBlock("atomic.continue", CGF.CurFn);
// MonotonicBB is arbitrarily chosen as the default case; in practice, this
// doesn't matter unless someone is crazy enough to use something that
// doesn't fold to a constant for the ordering.
+ llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(FailureOrderVal, MonotonicBB);
+ // Implemented as acquire, since it's the closest in LLVM.
+ SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),
+ AcquireBB);
+ SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire),
+ AcquireBB);
+ SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),
+ SeqCstBB);
+
+ // Emit all the different atomics
CGF.Builder.SetInsertPoint(MonotonicBB);
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
Size, SuccessOrder, llvm::AtomicOrdering::Monotonic, Scope);
CGF.Builder.CreateBr(ContBB);
- if (AcquireBB) {
- CGF.Builder.SetInsertPoint(AcquireBB);
- emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
- Size, SuccessOrder, llvm::AtomicOrdering::Acquire, Scope);
- CGF.Builder.CreateBr(ContBB);
- SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),
- AcquireBB);
- SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire),
- AcquireBB);
- }
- if (SeqCstBB) {
- CGF.Builder.SetInsertPoint(SeqCstBB);
- emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
- llvm::AtomicOrdering::SequentiallyConsistent, Scope);
- CGF.Builder.CreateBr(ContBB);
- SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),
- SeqCstBB);
- }
+ CGF.Builder.SetInsertPoint(AcquireBB);
+ emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
+ llvm::AtomicOrdering::Acquire, Scope);
+ CGF.Builder.CreateBr(ContBB);
+
+ CGF.Builder.SetInsertPoint(SeqCstBB);
+ emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
+ llvm::AtomicOrdering::SequentiallyConsistent, Scope);
+ CGF.Builder.CreateBr(ContBB);
CGF.Builder.SetInsertPoint(ContBB);
}
@@ -602,21 +593,25 @@
break;
case AtomicExpr::AO__atomic_add_fetch:
- PostOp = llvm::Instruction::Add;
+ PostOp = E->getValueType()->isFloatingType() ? llvm::Instruction::FAdd
+ : llvm::Instruction::Add;
LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_add:
case AtomicExpr::AO__opencl_atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_add:
- Op = llvm::AtomicRMWInst::Add;
+ Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FAdd
+ : llvm::AtomicRMWInst::Add;
break;
case AtomicExpr::AO__atomic_sub_fetch:
- PostOp = llvm::Instruction::Sub;
+ PostOp = E->getValueType()->isFloatingType() ? llvm::Instruction::FSub
+ : llvm::Instruction::Sub;
LLVM_FALLTHROUGH;
case AtomicExpr::AO__c11_atomic_fetch_sub:
case AtomicExpr::AO__opencl_atomic_fetch_sub:
case AtomicExpr::AO__atomic_fetch_sub:
- Op = llvm::AtomicRMWInst::Sub;
+ Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FSub
+ : llvm::AtomicRMWInst::Sub;
break;
case AtomicExpr::AO__atomic_min_fetch:
@@ -813,6 +808,8 @@
bool Oversized = getContext().toBits(TInfo.Width) > MaxInlineWidthInBits;
bool Misaligned = (Ptr.getAlignment() % TInfo.Width) != 0;
bool UseLibcall = Misaligned | Oversized;
+ bool ShouldCastToIntPtrTy = true;
+
CharUnits MaxInlineWidth =
getContext().toCharUnitsFromBits(MaxInlineWidthInBits);
@@ -892,11 +889,14 @@
EmitStoreOfScalar(Val1Scalar, MakeAddrLValue(Temp, Val1Ty));
break;
}
- LLVM_FALLTHROUGH;
+ LLVM_FALLTHROUGH;
case AtomicExpr::AO__atomic_fetch_add:
case AtomicExpr::AO__atomic_fetch_sub:
case AtomicExpr::AO__atomic_add_fetch:
case AtomicExpr::AO__atomic_sub_fetch:
+ ShouldCastToIntPtrTy = !MemTy->isFloatingType();
+ LLVM_FALLTHROUGH;
+
case AtomicExpr::AO__c11_atomic_store:
case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_store:
@@ -937,15 +937,23 @@
LValue AtomicVal = MakeAddrLValue(Ptr, AtomicTy);
AtomicInfo Atomics(*this, AtomicVal);
- Ptr = Atomics.emitCastToAtomicIntPointer(Ptr);
- if (Val1.isValid()) Val1 = Atomics.convertToAtomicIntPointer(Val1);
- if (Val2.isValid()) Val2 = Atomics.convertToAtomicIntPointer(Val2);
- if (Dest.isValid())
- Dest = Atomics.emitCastToAtomicIntPointer(Dest);
- else if (E->isCmpXChg())
+ if (ShouldCastToIntPtrTy) {
+ Ptr = Atomics.emitCastToAtomicIntPointer(Ptr);
+ if (Val1.isValid())
+ Val1 = Atomics.convertToAtomicIntPointer(Val1);
+ if (Val2.isValid())
+ Val2 = Atomics.convertToAtomicIntPointer(Val2);
+ }
+ if (Dest.isValid()) {
+ if (ShouldCastToIntPtrTy)
+ Dest = Atomics.emitCastToAtomicIntPointer(Dest);
+ } else if (E->isCmpXChg())
Dest = CreateMemTemp(RValTy, "cmpxchg.bool");
- else if (!RValTy->isVoidType())
- Dest = Atomics.emitCastToAtomicIntPointer(Atomics.CreateTempAlloca());
+ else if (!RValTy->isVoidType()) {
+ Dest = Atomics.CreateTempAlloca();
+ if (ShouldCastToIntPtrTy)
+ Dest = Atomics.emitCastToAtomicIntPointer(Dest);
+ }
// Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary .
if (UseLibcall) {
@@ -1722,11 +1730,6 @@
std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
RValue Expected, RValue Desired, llvm::AtomicOrdering Success,
llvm::AtomicOrdering Failure, bool IsWeak) {
- if (isStrongerThan(Failure, Success))
- // Don't assert on undefined behavior "failure argument shall be no stronger
- // than the success argument".
- Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(Success);
-
// Check whether we should use a library call.
if (shouldUseLibcall()) {
// Produce a source address.
diff --git a/src/llvm-project/clang/lib/CodeGen/CGBlocks.cpp b/src/llvm-project/clang/lib/CodeGen/CGBlocks.cpp
index 91c726f..f39a56f 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGBlocks.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGBlocks.cpp
@@ -1023,7 +1023,7 @@
type, VK_LValue, SourceLocation());
ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue,
- &declRef, VK_RValue, FPOptionsOverride());
+ &declRef, VK_PRValue, FPOptionsOverride());
// FIXME: Pass a specific location for the expr init so that the store is
// attributed to a reasonable location - otherwise it may be attributed to
// locations of subexpressions in the initialization.
@@ -1190,8 +1190,10 @@
// First argument of a block call is a generic block literal casted to
// generic void pointer, i.e. i8 addrspace(4)*
+ llvm::Type *GenericVoidPtrTy =
+ CGM.getOpenCLRuntime().getGenericVoidPointerType();
llvm::Value *BlockDescriptor = Builder.CreatePointerCast(
- BlockPtr, CGM.getOpenCLRuntime().getGenericVoidPointerType());
+ BlockPtr, GenericVoidPtrTy);
QualType VoidPtrQualTy = Ctx.getPointerType(
Ctx.getAddrSpaceQualType(Ctx.VoidTy, LangAS::opencl_generic));
Args.add(RValue::get(BlockDescriptor), VoidPtrQualTy);
@@ -1203,7 +1205,8 @@
Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
else {
llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
- Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
+ Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
+ getPointerAlign());
}
} else {
// Bitcast the block literal to a generic block literal.
@@ -1219,7 +1222,7 @@
EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
// Load the function.
- Func = Builder.CreateAlignedLoad(FuncPtr, getPointerAlign());
+ Func = Builder.CreateAlignedLoad(VoidPtrTy, FuncPtr, getPointerAlign());
}
const FunctionType *FuncTy = FnType->castAs<FunctionType>();
@@ -1372,7 +1375,7 @@
llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",
Init));
b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(),
- b.CreateStructGEP(literal, 0),
+ b.CreateStructGEP(literal->getValueType(), literal, 0),
CGM.getPointerAlign().getAsAlign());
b.CreateRetVoid();
// We can't use the normal LLVM global initialisation array, because we
@@ -1899,7 +1902,7 @@
} else {
Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn, /*IsThunk=*/false);
CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
}
}
@@ -1945,21 +1948,13 @@
if (CGM.supportsCOMDAT())
Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));
- IdentifierInfo *II = &C.Idents.get(FuncName);
-
SmallVector<QualType, 2> ArgTys;
ArgTys.push_back(C.VoidPtrTy);
ArgTys.push_back(C.VoidPtrTy);
- QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {});
- FunctionDecl *FD = FunctionDecl::Create(
- C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
- FunctionTy, nullptr, SC_Static, false, false);
setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI,
CGM);
- // This is necessary to avoid inheriting the previous line number.
- FD->setImplicit();
- StartFunction(FD, ReturnTy, Fn, FI, args);
+ StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
auto AL = ApplyDebugLocation::CreateArtificial(*this);
llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
@@ -2140,21 +2135,12 @@
if (CGM.supportsCOMDAT())
Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));
- IdentifierInfo *II = &C.Idents.get(FuncName);
-
SmallVector<QualType, 1> ArgTys;
ArgTys.push_back(C.VoidPtrTy);
- QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {});
-
- FunctionDecl *FD = FunctionDecl::Create(
- C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
- FunctionTy, nullptr, SC_Static, false, false);
setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI,
CGM);
- // This is necessary to avoid inheriting the previous line number.
- FD->setImplicit();
- StartFunction(FD, ReturnTy, Fn, FI, args);
+ StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
markAsIgnoreThreadCheckingAtRuntime(Fn);
auto AL = ApplyDebugLocation::CreateArtificial(*this);
@@ -2392,21 +2378,15 @@
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__Block_byref_object_copy_", &CGF.CGM.getModule());
- IdentifierInfo *II
- = &Context.Idents.get("__Block_byref_object_copy_");
-
SmallVector<QualType, 2> ArgTys;
ArgTys.push_back(Context.VoidPtrTy);
ArgTys.push_back(Context.VoidPtrTy);
- QualType FunctionTy = Context.getFunctionType(ReturnTy, ArgTys, {});
-
- FunctionDecl *FD = FunctionDecl::Create(
- Context, Context.getTranslationUnitDecl(), SourceLocation(),
- SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false);
CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
- CGF.StartFunction(FD, ReturnTy, Fn, FI, args);
+ CGF.StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
+ // Create a scope with an artificial location for the body of this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(CGF);
if (generator.needsCopy()) {
llvm::Type *byrefPtrType = byrefInfo.Type->getPointerTo(0);
@@ -2468,20 +2448,14 @@
"__Block_byref_object_dispose_",
&CGF.CGM.getModule());
- IdentifierInfo *II
- = &Context.Idents.get("__Block_byref_object_dispose_");
-
SmallVector<QualType, 1> ArgTys;
ArgTys.push_back(Context.VoidPtrTy);
- QualType FunctionTy = Context.getFunctionType(R, ArgTys, {});
-
- FunctionDecl *FD = FunctionDecl::Create(
- Context, Context.getTranslationUnitDecl(), SourceLocation(),
- SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false);
CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
- CGF.StartFunction(FD, R, Fn, FI, args);
+ CGF.StartFunction(GlobalDecl(), R, Fn, FI, args);
+ // Create a scope with an artificial location for the body of this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(CGF);
if (generator.needsDispose()) {
Address addr = CGF.GetAddrOfLocalVar(&Src);
@@ -2884,7 +2858,7 @@
"expected Function or GlobalVariable");
const NamedDecl *ND = nullptr;
- for (const auto &Result : DC->lookup(&II))
+ for (const auto *Result : DC->lookup(&II))
if ((ND = dyn_cast<FunctionDecl>(Result)) ||
(ND = dyn_cast<VarDecl>(Result)))
break;
@@ -2936,9 +2910,8 @@
if (NSConcreteGlobalBlock)
return NSConcreteGlobalBlock;
- NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock",
- Int8PtrTy->getPointerTo(),
- nullptr);
+ NSConcreteGlobalBlock =
+ GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock", Int8PtrTy, 0, nullptr);
configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock);
return NSConcreteGlobalBlock;
}
@@ -2947,9 +2920,8 @@
if (NSConcreteStackBlock)
return NSConcreteStackBlock;
- NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock",
- Int8PtrTy->getPointerTo(),
- nullptr);
+ NSConcreteStackBlock =
+ GetOrCreateLLVMGlobal("_NSConcreteStackBlock", Int8PtrTy, 0, nullptr);
configureBlocksRuntimeObject(*this, NSConcreteStackBlock);
return NSConcreteStackBlock;
}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGBuilder.h b/src/llvm-project/clang/lib/CodeGen/CGBuilder.h
index 38e96c0..4fad44a 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGBuilder.h
+++ b/src/llvm-project/clang/lib/CodeGen/CGBuilder.h
@@ -66,35 +66,28 @@
// Note that we intentionally hide the CreateLoad APIs that don't
// take an alignment.
llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
- return CreateAlignedLoad(Addr.getPointer(),
+ return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
Addr.getAlignment().getAsAlign(), Name);
}
llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
// This overload is required to prevent string literals from
// ending up in the IsVolatile overload.
- return CreateAlignedLoad(Addr.getPointer(),
+ return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
Addr.getAlignment().getAsAlign(), Name);
}
llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
const llvm::Twine &Name = "") {
- return CreateAlignedLoad(
- Addr.getPointer(), Addr.getAlignment().getAsAlign(), IsVolatile, Name);
+ return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
+ Addr.getAlignment().getAsAlign(), IsVolatile,
+ Name);
}
using CGBuilderBaseTy::CreateAlignedLoad;
- llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
- const llvm::Twine &Name = "") {
- return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
- }
- llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
- const char *Name) {
- return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
- }
llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
CharUnits Align,
const llvm::Twine &Name = "") {
assert(Addr->getType()->getPointerElementType() == Ty);
- return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
+ return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
}
// Note that we intentionally hide the CreateStore APIs that don't
@@ -132,6 +125,28 @@
return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
}
+ // Temporarily use old signature; clang will be updated to an Address overload
+ // in a subsequent patch.
+ llvm::AtomicCmpXchgInst *
+ CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New,
+ llvm::AtomicOrdering SuccessOrdering,
+ llvm::AtomicOrdering FailureOrdering,
+ llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
+ return CGBuilderBaseTy::CreateAtomicCmpXchg(
+ Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering,
+ SSID);
+ }
+
+ // Temporarily use old signature; clang will be updated to an Address overload
+ // in a subsequent patch.
+ llvm::AtomicRMWInst *
+ CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr,
+ llvm::Value *Val, llvm::AtomicOrdering Ordering,
+ llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
+ return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(),
+ Ordering, SSID);
+ }
+
using CGBuilderBaseTy::CreateBitCast;
Address CreateBitCast(Address Addr, llvm::Type *Ty,
const llvm::Twine &Name = "") {
@@ -198,7 +213,7 @@
CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
return Address(
- CreateInBoundsGEP(Addr.getPointer(),
+ CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
{getSize(CharUnits::Zero()), getSize(Index)}, Name),
Addr.getAlignment().alignmentAtOffset(Index * EltSize));
}
@@ -239,13 +254,15 @@
Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
const llvm::Twine &Name = "") {
assert(Addr.getElementType() == TypeCache.Int8Ty);
- return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name),
+ return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
+ getSize(Offset), Name),
Addr.getAlignment().alignmentAtOffset(Offset));
}
Address CreateConstByteGEP(Address Addr, CharUnits Offset,
const llvm::Twine &Name = "") {
assert(Addr.getElementType() == TypeCache.Int8Ty);
- return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name),
+ return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
+ getSize(Offset), Name),
Addr.getAlignment().alignmentAtOffset(Offset));
}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp b/src/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
index 6a197ed..d9b2a5f 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
@@ -26,6 +27,8 @@
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/ValueTracking.h"
@@ -40,6 +43,7 @@
#include "llvm/IR/IntrinsicsNVPTX.h"
#include "llvm/IR/IntrinsicsPowerPC.h"
#include "llvm/IR/IntrinsicsR600.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
#include "llvm/IR/IntrinsicsS390.h"
#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/IR/IntrinsicsX86.h"
@@ -411,7 +415,7 @@
llvm::Type *ITy =
llvm::IntegerType::get(CGF.getLLVMContext(), LoadSize.getQuantity() * 8);
Ptr = CGF.Builder.CreateBitCast(Ptr, ITy->getPointerTo());
- llvm::LoadInst *Load = CGF.Builder.CreateAlignedLoad(Ptr, LoadSize);
+ llvm::LoadInst *Load = CGF.Builder.CreateAlignedLoad(ITy, Ptr, LoadSize);
Load->setVolatile(true);
return Load;
}
@@ -990,6 +994,54 @@
ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res");
}
+static llvm::Value *emitPPCLoadReserveIntrinsic(CodeGenFunction &CGF,
+ unsigned BuiltinID,
+ const CallExpr *E) {
+ Value *Addr = CGF.EmitScalarExpr(E->getArg(0));
+
+ SmallString<64> Asm;
+ raw_svector_ostream AsmOS(Asm);
+ llvm::IntegerType *RetType = CGF.Int32Ty;
+
+ switch (BuiltinID) {
+ case clang::PPC::BI__builtin_ppc_ldarx:
+ AsmOS << "ldarx ";
+ RetType = CGF.Int64Ty;
+ break;
+ case clang::PPC::BI__builtin_ppc_lwarx:
+ AsmOS << "lwarx ";
+ RetType = CGF.Int32Ty;
+ break;
+ case clang::PPC::BI__builtin_ppc_lharx:
+ AsmOS << "lharx ";
+ RetType = CGF.Int16Ty;
+ break;
+ case clang::PPC::BI__builtin_ppc_lbarx:
+ AsmOS << "lbarx ";
+ RetType = CGF.Int8Ty;
+ break;
+ default:
+ llvm_unreachable("Expected only PowerPC load reserve intrinsics");
+ }
+
+ AsmOS << "$0, ${1:y}";
+
+ std::string Constraints = "=r,*Z,~{memory}";
+ std::string MachineClobbers = CGF.getTarget().getClobbers();
+ if (!MachineClobbers.empty()) {
+ Constraints += ',';
+ Constraints += MachineClobbers;
+ }
+
+ llvm::Type *IntPtrType = RetType->getPointerTo();
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(RetType, {IntPtrType}, false);
+
+ llvm::InlineAsm *IA =
+ llvm::InlineAsm::get(FTy, Asm, Constraints, /*hasSideEffects=*/true);
+ return CGF.Builder.CreateCall(IA, {Addr});
+}
+
namespace {
enum class MSVCSetJmpKind {
_setjmpex,
@@ -1677,7 +1729,6 @@
}
QualType ReturnTy = Ctx.VoidTy;
- QualType FuncionTy = Ctx.getFunctionType(ReturnTy, ArgTys, {});
// The helper function has linkonce_odr linkage to enable the linker to merge
// identical functions. To ensure the merging always happens, 'noinline' is
@@ -1688,7 +1739,7 @@
llvm::Function *Fn = llvm::Function::Create(
FuncTy, llvm::GlobalValue::LinkOnceODRLinkage, Name, &CGM.getModule());
Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn, /*IsThunk=*/false);
CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
Fn->setDoesNotThrow();
@@ -1697,14 +1748,7 @@
Fn->addFnAttr(llvm::Attribute::NoInline);
auto NL = ApplyDebugLocation::CreateEmpty(*this);
- IdentifierInfo *II = &Ctx.Idents.get(Name);
- FunctionDecl *FD = FunctionDecl::Create(
- Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
- FuncionTy, nullptr, SC_PrivateExtern, false, false);
- // Avoid generating debug location info for the function.
- FD->setImplicit();
-
- StartFunction(FD, ReturnTy, Fn, FI, Args);
+ StartFunction(GlobalDecl(), ReturnTy, Fn, FI, Args);
// Create a scope with an artificial location for the body of this function.
auto AL = ApplyDebugLocation::CreateArtificial(*this);
@@ -2829,6 +2873,36 @@
Function *FnAssume = CGM.getIntrinsic(Intrinsic::assume);
return RValue::get(Builder.CreateCall(FnAssume, ArgValue));
}
+ case Builtin::BI__arithmetic_fence: {
+ // Create the builtin call if FastMath is selected, and the target
+ // supports the builtin, otherwise just return the argument.
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
+ llvm::FastMathFlags FMF = Builder.getFastMathFlags();
+ bool isArithmeticFenceEnabled =
+ FMF.allowReassoc() &&
+ getContext().getTargetInfo().checkArithmeticFenceSupported();
+ QualType ArgType = E->getArg(0)->getType();
+ if (ArgType->isComplexType()) {
+ if (isArithmeticFenceEnabled) {
+ QualType ElementType = ArgType->castAs<ComplexType>()->getElementType();
+ ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0));
+ Value *Real = Builder.CreateArithmeticFence(ComplexVal.first,
+ ConvertType(ElementType));
+ Value *Imag = Builder.CreateArithmeticFence(ComplexVal.second,
+ ConvertType(ElementType));
+ return RValue::getComplex(std::make_pair(Real, Imag));
+ }
+ ComplexPairTy ComplexVal = EmitComplexExpr(E->getArg(0));
+ Value *Real = ComplexVal.first;
+ Value *Imag = ComplexVal.second;
+ return RValue::getComplex(std::make_pair(Real, Imag));
+ }
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ if (isArithmeticFenceEnabled)
+ return RValue::get(
+ Builder.CreateArithmeticFence(ArgValue, ConvertType(ArgType)));
+ return RValue::get(ArgValue);
+ }
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64: {
@@ -2942,10 +3016,21 @@
case Builtin::BI__builtin_powi:
case Builtin::BI__builtin_powif:
- case Builtin::BI__builtin_powil:
- return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(
- *this, E, Intrinsic::powi, Intrinsic::experimental_constrained_powi));
+ case Builtin::BI__builtin_powil: {
+ llvm::Value *Src0 = EmitScalarExpr(E->getArg(0));
+ llvm::Value *Src1 = EmitScalarExpr(E->getArg(1));
+ if (Builder.getIsFPConstrained()) {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
+ Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_powi,
+ Src0->getType());
+ return RValue::get(Builder.CreateConstrainedFPCall(F, { Src0, Src1 }));
+ }
+
+ Function *F = CGM.getIntrinsic(Intrinsic::powi,
+ { Src0->getType(), Src1->getType() });
+ return RValue::get(Builder.CreateCall(F, { Src0, Src1 }));
+ }
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
case Builtin::BI__builtin_isless:
@@ -2985,10 +3070,35 @@
}
case Builtin::BI__builtin_isnan: {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
- // FIXME: for strictfp/IEEE-754 we need to not trap on SNaN here.
Value *V = EmitScalarExpr(E->getArg(0));
- V = Builder.CreateFCmpUNO(V, V, "cmp");
- return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
+ llvm::Type *Ty = V->getType();
+ const llvm::fltSemantics &Semantics = Ty->getFltSemantics();
+ if (!Builder.getIsFPConstrained() ||
+ Builder.getDefaultConstrainedExcept() == fp::ebIgnore ||
+ !Ty->isIEEE()) {
+ V = Builder.CreateFCmpUNO(V, V, "cmp");
+ return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
+ }
+
+ if (Value *Result = getTargetHooks().testFPKind(V, BuiltinID, Builder, CGM))
+ return RValue::get(Result);
+
+ // NaN has all exp bits set and a non zero significand. Therefore:
+ // isnan(V) == ((exp mask - (abs(V) & exp mask)) < 0)
+ unsigned bitsize = Ty->getScalarSizeInBits();
+ llvm::IntegerType *IntTy = Builder.getIntNTy(bitsize);
+ Value *IntV = Builder.CreateBitCast(V, IntTy);
+ APInt AndMask = APInt::getSignedMaxValue(bitsize);
+ Value *AbsV =
+ Builder.CreateAnd(IntV, llvm::ConstantInt::get(IntTy, AndMask));
+ APInt ExpMask = APFloat::getInf(Semantics).bitcastToAPInt();
+ Value *Sub =
+ Builder.CreateSub(llvm::ConstantInt::get(IntTy, ExpMask), AbsV);
+ // V = sign bit (Sub) <=> V = (Sub < 0)
+ V = Builder.CreateLShr(Sub, llvm::ConstantInt::get(IntTy, bitsize - 1));
+ if (bitsize > 32)
+ V = Builder.CreateTrunc(V, ConvertType(E->getType()));
+ return RValue::get(V);
}
case Builtin::BI__builtin_matrix_transpose: {
@@ -3050,15 +3160,38 @@
// isfinite(x) --> fabs(x) != infinity
// x != NaN via the ordered compare in either case.
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
- // FIXME: for strictfp/IEEE-754 we need to not trap on SNaN here.
Value *V = EmitScalarExpr(E->getArg(0));
- Value *Fabs = EmitFAbs(*this, V);
- Constant *Infinity = ConstantFP::getInfinity(V->getType());
- CmpInst::Predicate Pred = (BuiltinID == Builtin::BI__builtin_isinf)
- ? CmpInst::FCMP_OEQ
- : CmpInst::FCMP_ONE;
- Value *FCmp = Builder.CreateFCmp(Pred, Fabs, Infinity, "cmpinf");
- return RValue::get(Builder.CreateZExt(FCmp, ConvertType(E->getType())));
+ llvm::Type *Ty = V->getType();
+ if (!Builder.getIsFPConstrained() ||
+ Builder.getDefaultConstrainedExcept() == fp::ebIgnore ||
+ !Ty->isIEEE()) {
+ Value *Fabs = EmitFAbs(*this, V);
+ Constant *Infinity = ConstantFP::getInfinity(V->getType());
+ CmpInst::Predicate Pred = (BuiltinID == Builtin::BI__builtin_isinf)
+ ? CmpInst::FCMP_OEQ
+ : CmpInst::FCMP_ONE;
+ Value *FCmp = Builder.CreateFCmp(Pred, Fabs, Infinity, "cmpinf");
+ return RValue::get(Builder.CreateZExt(FCmp, ConvertType(E->getType())));
+ }
+
+ if (Value *Result = getTargetHooks().testFPKind(V, BuiltinID, Builder, CGM))
+ return RValue::get(Result);
+
+ // Inf values have all exp bits set and a zero significand. Therefore:
+ // isinf(V) == ((V << 1) == ((exp mask) << 1))
+ // isfinite(V) == ((V << 1) < ((exp mask) << 1)) using unsigned comparison
+ unsigned bitsize = Ty->getScalarSizeInBits();
+ llvm::IntegerType *IntTy = Builder.getIntNTy(bitsize);
+ Value *IntV = Builder.CreateBitCast(V, IntTy);
+ Value *Shl1 = Builder.CreateShl(IntV, 1);
+ const llvm::fltSemantics &Semantics = Ty->getFltSemantics();
+ APInt ExpMask = APFloat::getInf(Semantics).bitcastToAPInt();
+ Value *ExpMaskShl1 = llvm::ConstantInt::get(IntTy, ExpMask.shl(1));
+ if (BuiltinID == Builtin::BI__builtin_isinf)
+ V = Builder.CreateICmpEQ(Shl1, ExpMaskShl1);
+ else
+ V = Builder.CreateICmpULT(Shl1, ExpMaskShl1);
+ return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
}
case Builtin::BI__builtin_isinf_sign: {
@@ -3223,7 +3356,8 @@
Builder.CreateMemCpy(Dest, Src, SizeVal, false);
if (BuiltinID == Builtin::BImempcpy ||
BuiltinID == Builtin::BI__builtin_mempcpy)
- return RValue::get(Builder.CreateInBoundsGEP(Dest.getPointer(), SizeVal));
+ return RValue::get(Builder.CreateInBoundsGEP(Dest.getElementType(),
+ Dest.getPointer(), SizeVal));
else
return RValue::get(Dest.getPointer());
}
@@ -3328,6 +3462,52 @@
Builder.CreateMemSet(Dest, ByteVal, SizeVal, false);
return RValue::get(Dest.getPointer());
}
+ case Builtin::BI__builtin_wmemchr: {
+ // The MSVC runtime library does not provide a definition of wmemchr, so we
+ // need an inline implementation.
+ if (!getTarget().getTriple().isOSMSVCRT())
+ break;
+
+ llvm::Type *WCharTy = ConvertType(getContext().WCharTy);
+ Value *Str = EmitScalarExpr(E->getArg(0));
+ Value *Chr = EmitScalarExpr(E->getArg(1));
+ Value *Size = EmitScalarExpr(E->getArg(2));
+
+ BasicBlock *Entry = Builder.GetInsertBlock();
+ BasicBlock *CmpEq = createBasicBlock("wmemchr.eq");
+ BasicBlock *Next = createBasicBlock("wmemchr.next");
+ BasicBlock *Exit = createBasicBlock("wmemchr.exit");
+ Value *SizeEq0 = Builder.CreateICmpEQ(Size, ConstantInt::get(SizeTy, 0));
+ Builder.CreateCondBr(SizeEq0, Exit, CmpEq);
+
+ EmitBlock(CmpEq);
+ PHINode *StrPhi = Builder.CreatePHI(Str->getType(), 2);
+ StrPhi->addIncoming(Str, Entry);
+ PHINode *SizePhi = Builder.CreatePHI(SizeTy, 2);
+ SizePhi->addIncoming(Size, Entry);
+ CharUnits WCharAlign =
+ getContext().getTypeAlignInChars(getContext().WCharTy);
+ Value *StrCh = Builder.CreateAlignedLoad(WCharTy, StrPhi, WCharAlign);
+ Value *FoundChr = Builder.CreateConstInBoundsGEP1_32(WCharTy, StrPhi, 0);
+ Value *StrEqChr = Builder.CreateICmpEQ(StrCh, Chr);
+ Builder.CreateCondBr(StrEqChr, Exit, Next);
+
+ EmitBlock(Next);
+ Value *NextStr = Builder.CreateConstInBoundsGEP1_32(WCharTy, StrPhi, 1);
+ Value *NextSize = Builder.CreateSub(SizePhi, ConstantInt::get(SizeTy, 1));
+ Value *NextSizeEq0 =
+ Builder.CreateICmpEQ(NextSize, ConstantInt::get(SizeTy, 0));
+ Builder.CreateCondBr(NextSizeEq0, Exit, CmpEq);
+ StrPhi->addIncoming(NextStr, Next);
+ SizePhi->addIncoming(NextSize, Next);
+
+ EmitBlock(Exit);
+ PHINode *Ret = Builder.CreatePHI(Str->getType(), 3);
+ Ret->addIncoming(llvm::Constant::getNullValue(Str->getType()), Entry);
+ Ret->addIncoming(llvm::Constant::getNullValue(Str->getType()), Next);
+ Ret->addIncoming(FoundChr, CmpEq);
+ return RValue::get(Ret);
+ }
case Builtin::BI__builtin_wmemcmp: {
// The MSVC runtime library does not provide a definition of wmemcmp, so we
// need an inline implementation.
@@ -4654,7 +4834,8 @@
auto *Zero = llvm::ConstantInt::get(IntTy, 0);
for (unsigned I = First; I < NumArgs; ++I) {
auto *Index = llvm::ConstantInt::get(IntTy, I - First);
- auto *GEP = Builder.CreateGEP(TmpPtr, {Zero, Index});
+ auto *GEP = Builder.CreateGEP(Tmp.getElementType(), TmpPtr,
+ {Zero, Index});
if (I == First)
ElemPtr = GEP;
auto *V =
@@ -4959,6 +5140,17 @@
Value *ArgPtr = Builder.CreateLoad(SrcAddr, "ap.val");
return RValue::get(Builder.CreateStore(ArgPtr, DestAddr));
}
+
+ case Builtin::BI__builtin_get_device_side_mangled_name: {
+ auto Name = CGM.getCUDARuntime().getDeviceSideName(
+ cast<DeclRefExpr>(E->getArg(0)->IgnoreImpCasts())->getDecl());
+ auto Str = CGM.GetAddrOfConstantCString(Name, "");
+ llvm::Constant *Zeros[] = {llvm::ConstantInt::get(SizeTy, 0),
+ llvm::ConstantInt::get(SizeTy, 0)};
+ auto *Ptr = llvm::ConstantExpr::getGetElementPtr(Str.getElementType(),
+ Str.getPointer(), Zeros);
+ return RValue::get(Ptr);
+ }
}
// If this is an alias for a lib function (e.g. __builtin_sin), emit
@@ -5138,6 +5330,9 @@
return CGF->EmitWebAssemblyBuiltinExpr(BuiltinID, E);
case llvm::Triple::hexagon:
return CGF->EmitHexagonBuiltinExpr(BuiltinID, E);
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ return CGF->EmitRISCVBuiltinExpr(BuiltinID, E, ReturnValue);
default:
return nullptr;
}
@@ -5344,7 +5539,9 @@
NEONMAP2(vabdq_v, arm_neon_vabdu, arm_neon_vabds, Add1ArgType | UnsignedAlts),
NEONMAP1(vabs_v, arm_neon_vabs, 0),
NEONMAP1(vabsq_v, arm_neon_vabs, 0),
+ NEONMAP0(vadd_v),
NEONMAP0(vaddhn_v),
+ NEONMAP0(vaddq_v),
NEONMAP1(vaesdq_v, arm_neon_aesd, 0),
NEONMAP1(vaeseq_v, arm_neon_aese, 0),
NEONMAP1(vaesimcq_v, arm_neon_aesimc, 0),
@@ -5638,11 +5835,15 @@
NEONMAP0(splatq_laneq_v),
NEONMAP1(vabs_v, aarch64_neon_abs, 0),
NEONMAP1(vabsq_v, aarch64_neon_abs, 0),
+ NEONMAP0(vadd_v),
NEONMAP0(vaddhn_v),
+ NEONMAP0(vaddq_p128),
+ NEONMAP0(vaddq_v),
NEONMAP1(vaesdq_v, aarch64_crypto_aesd, 0),
NEONMAP1(vaeseq_v, aarch64_crypto_aese, 0),
NEONMAP1(vaesimcq_v, aarch64_crypto_aesimc, 0),
NEONMAP1(vaesmcq_v, aarch64_crypto_aesmc, 0),
+ NEONMAP2(vbcaxq_v, aarch64_crypto_bcaxu, aarch64_crypto_bcaxs, Add1ArgType | UnsignedAlts),
NEONMAP1(vbfdot_v, aarch64_neon_bfdot, 0),
NEONMAP1(vbfdotq_v, aarch64_neon_bfdot, 0),
NEONMAP1(vbfmlalbq_v, aarch64_neon_bfmlalb, 0),
@@ -5712,6 +5913,7 @@
NEONMAP1(vcvtx_f32_v, aarch64_neon_fcvtxn, AddRetType | Add1ArgType),
NEONMAP2(vdot_v, aarch64_neon_udot, aarch64_neon_sdot, 0),
NEONMAP2(vdotq_v, aarch64_neon_udot, aarch64_neon_sdot, 0),
+ NEONMAP2(veor3q_v, aarch64_crypto_eor3u, aarch64_crypto_eor3s, Add1ArgType | UnsignedAlts),
NEONMAP0(vext_v),
NEONMAP0(vextq_v),
NEONMAP0(vfma_v),
@@ -5777,12 +5979,21 @@
NEONMAP2(vqsub_v, aarch64_neon_uqsub, aarch64_neon_sqsub, Add1ArgType | UnsignedAlts),
NEONMAP2(vqsubq_v, aarch64_neon_uqsub, aarch64_neon_sqsub, Add1ArgType | UnsignedAlts),
NEONMAP1(vraddhn_v, aarch64_neon_raddhn, Add1ArgType),
+ NEONMAP1(vrax1q_v, aarch64_crypto_rax1, 0),
NEONMAP2(vrecpe_v, aarch64_neon_frecpe, aarch64_neon_urecpe, 0),
NEONMAP2(vrecpeq_v, aarch64_neon_frecpe, aarch64_neon_urecpe, 0),
NEONMAP1(vrecps_v, aarch64_neon_frecps, Add1ArgType),
NEONMAP1(vrecpsq_v, aarch64_neon_frecps, Add1ArgType),
NEONMAP2(vrhadd_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts),
NEONMAP2(vrhaddq_v, aarch64_neon_urhadd, aarch64_neon_srhadd, Add1ArgType | UnsignedAlts),
+ NEONMAP1(vrnd32x_v, aarch64_neon_frint32x, Add1ArgType),
+ NEONMAP1(vrnd32xq_v, aarch64_neon_frint32x, Add1ArgType),
+ NEONMAP1(vrnd32z_v, aarch64_neon_frint32z, Add1ArgType),
+ NEONMAP1(vrnd32zq_v, aarch64_neon_frint32z, Add1ArgType),
+ NEONMAP1(vrnd64x_v, aarch64_neon_frint64x, Add1ArgType),
+ NEONMAP1(vrnd64xq_v, aarch64_neon_frint64x, Add1ArgType),
+ NEONMAP1(vrnd64z_v, aarch64_neon_frint64z, Add1ArgType),
+ NEONMAP1(vrnd64zq_v, aarch64_neon_frint64z, Add1ArgType),
NEONMAP0(vrndi_v),
NEONMAP0(vrndiq_v),
NEONMAP2(vrshl_v, aarch64_neon_urshl, aarch64_neon_srshl, Add1ArgType | UnsignedAlts),
@@ -5800,6 +6011,10 @@
NEONMAP1(vsha256hq_v, aarch64_crypto_sha256h, 0),
NEONMAP1(vsha256su0q_v, aarch64_crypto_sha256su0, 0),
NEONMAP1(vsha256su1q_v, aarch64_crypto_sha256su1, 0),
+ NEONMAP1(vsha512h2q_v, aarch64_crypto_sha512h2, 0),
+ NEONMAP1(vsha512hq_v, aarch64_crypto_sha512h, 0),
+ NEONMAP1(vsha512su0q_v, aarch64_crypto_sha512su0, 0),
+ NEONMAP1(vsha512su1q_v, aarch64_crypto_sha512su1, 0),
NEONMAP0(vshl_n_v),
NEONMAP2(vshl_v, aarch64_neon_ushl, aarch64_neon_sshl, Add1ArgType | UnsignedAlts),
NEONMAP0(vshll_n_v),
@@ -5808,6 +6023,15 @@
NEONMAP0(vshr_n_v),
NEONMAP0(vshrn_n_v),
NEONMAP0(vshrq_n_v),
+ NEONMAP1(vsm3partw1q_v, aarch64_crypto_sm3partw1, 0),
+ NEONMAP1(vsm3partw2q_v, aarch64_crypto_sm3partw2, 0),
+ NEONMAP1(vsm3ss1q_v, aarch64_crypto_sm3ss1, 0),
+ NEONMAP1(vsm3tt1aq_v, aarch64_crypto_sm3tt1a, 0),
+ NEONMAP1(vsm3tt1bq_v, aarch64_crypto_sm3tt1b, 0),
+ NEONMAP1(vsm3tt2aq_v, aarch64_crypto_sm3tt2a, 0),
+ NEONMAP1(vsm3tt2bq_v, aarch64_crypto_sm3tt2b, 0),
+ NEONMAP1(vsm4ekeyq_v, aarch64_crypto_sm4ekey, 0),
+ NEONMAP1(vsm4eq_v, aarch64_crypto_sm4e, 0),
NEONMAP1(vst1_x2_v, aarch64_neon_st1x2, 0),
NEONMAP1(vst1_x3_v, aarch64_neon_st1x3, 0),
NEONMAP1(vst1_x4_v, aarch64_neon_st1x4, 0),
@@ -5820,6 +6044,7 @@
NEONMAP1(vusdot_v, aarch64_neon_usdot, 0),
NEONMAP1(vusdotq_v, aarch64_neon_usdot, 0),
NEONMAP1(vusmmlaq_v, aarch64_neon_usmmla, 0),
+ NEONMAP1(vxarq_v, aarch64_crypto_xar, 0),
};
static const ARMVectorIntrinsicInfo AArch64SISDIntrinsicMap[] = {
@@ -6266,6 +6491,14 @@
if (VTy->getElementType()->isFloatingPointTy())
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, Ty), Ops, "vabs");
return EmitNeonCall(CGM.getIntrinsic(LLVMIntrinsic, Ty), Ops, "vabs");
+ case NEON::BI__builtin_neon_vadd_v:
+ case NEON::BI__builtin_neon_vaddq_v: {
+ llvm::Type *VTy = llvm::FixedVectorType::get(Int8Ty, Quad ? 16 : 8);
+ Ops[0] = Builder.CreateBitCast(Ops[0], VTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
+ Ops[0] = Builder.CreateXor(Ops[0], Ops[1]);
+ return Builder.CreateBitCast(Ops[0], Ty);
+ }
case NEON::BI__builtin_neon_vaddhn_v: {
llvm::FixedVectorType *SrcTy =
llvm::FixedVectorType::getExtendedElementVectorType(VTy);
@@ -6638,6 +6871,13 @@
case NEON::BI__builtin_neon_vrshrq_n_v:
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrshr_n",
1, true);
+ case NEON::BI__builtin_neon_vsha512hq_v:
+ case NEON::BI__builtin_neon_vsha512h2q_v:
+ case NEON::BI__builtin_neon_vsha512su0q_v:
+ case NEON::BI__builtin_neon_vsha512su1q_v: {
+ Function *F = CGM.getIntrinsic(Int);
+ return EmitNeonCall(F, Ops, "");
+ }
case NEON::BI__builtin_neon_vshl_n_v:
case NEON::BI__builtin_neon_vshlq_n_v:
Ops[1] = EmitNeonShiftVector(Ops[1], Ty, false);
@@ -6686,6 +6926,22 @@
Ops.push_back(getAlignmentValue32(PtrOp0));
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "");
}
+ case NEON::BI__builtin_neon_vsm3partw1q_v:
+ case NEON::BI__builtin_neon_vsm3partw2q_v:
+ case NEON::BI__builtin_neon_vsm3ss1q_v:
+ case NEON::BI__builtin_neon_vsm4ekeyq_v:
+ case NEON::BI__builtin_neon_vsm4eq_v: {
+ Function *F = CGM.getIntrinsic(Int);
+ return EmitNeonCall(F, Ops, "");
+ }
+ case NEON::BI__builtin_neon_vsm3tt1aq_v:
+ case NEON::BI__builtin_neon_vsm3tt1bq_v:
+ case NEON::BI__builtin_neon_vsm3tt2aq_v:
+ case NEON::BI__builtin_neon_vsm3tt2bq_v: {
+ Function *F = CGM.getIntrinsic(Int);
+ Ops[3] = Builder.CreateZExt(Ops[3], Int64Ty);
+ return EmitNeonCall(F, Ops, "");
+ }
case NEON::BI__builtin_neon_vst1_x2_v:
case NEON::BI__builtin_neon_vst1q_x2_v:
case NEON::BI__builtin_neon_vst1_x3_v:
@@ -6767,6 +7023,11 @@
}
return SV;
}
+ case NEON::BI__builtin_neon_vxarq_v: {
+ Function *F = CGM.getIntrinsic(Int);
+ Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);
+ return EmitNeonCall(F, Ops, "");
+ }
case NEON::BI__builtin_neon_vzip_v:
case NEON::BI__builtin_neon_vzipq_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
@@ -8579,7 +8840,7 @@
bool IsZExtReturn) {
QualType LangPTy = E->getArg(1)->getType();
llvm::Type *MemEltTy = CGM.getTypes().ConvertType(
- LangPTy->getAs<PointerType>()->getPointeeType());
+ LangPTy->castAs<PointerType>()->getPointeeType());
// The vector type that is returned may be different from the
// eventual type loaded from memory.
@@ -8604,7 +8865,7 @@
unsigned BuiltinID) {
QualType LangPTy = E->getArg(1)->getType();
llvm::Type *MemEltTy = CGM.getTypes().ConvertType(
- LangPTy->getAs<PointerType>()->getPointeeType());
+ LangPTy->castAs<PointerType>()->getPointeeType());
// The vector type that is stored may be different from the
// eventual type stored to memory.
@@ -8881,32 +9142,32 @@
if (IsBoolTy)
EltTy = IntegerType::get(getLLVMContext(), SVEBitsPerBlock / NumOpnds);
- Address Alloca = CreateTempAlloca(llvm::ArrayType::get(EltTy, NumOpnds),
- CharUnits::fromQuantity(16));
+ SmallVector<llvm::Value *, 16> VecOps;
for (unsigned I = 0; I < NumOpnds; ++I)
- Builder.CreateDefaultAlignedStore(
- IsBoolTy ? Builder.CreateZExt(Ops[I], EltTy) : Ops[I],
- Builder.CreateGEP(Alloca.getPointer(),
- {Builder.getInt64(0), Builder.getInt64(I)}));
+ VecOps.push_back(Builder.CreateZExt(Ops[I], EltTy));
+ Value *Vec = BuildVector(VecOps);
SVETypeFlags TypeFlags(Builtin->TypeModifier);
Value *Pred = EmitSVEAllTruePred(TypeFlags);
llvm::Type *OverloadedTy = getSVEVectorForElementType(EltTy);
- Function *F = CGM.getIntrinsic(Intrinsic::aarch64_sve_ld1rq, OverloadedTy);
- Value *Alloca0 = Builder.CreateGEP(
- Alloca.getPointer(), {Builder.getInt64(0), Builder.getInt64(0)});
- Value *LD1RQ = Builder.CreateCall(F, {Pred, Alloca0});
+ Value *InsertSubVec = Builder.CreateInsertVector(
+ OverloadedTy, UndefValue::get(OverloadedTy), Vec, Builder.getInt64(0));
+
+ Function *F =
+ CGM.getIntrinsic(Intrinsic::aarch64_sve_dupq_lane, OverloadedTy);
+ Value *DupQLane =
+ Builder.CreateCall(F, {InsertSubVec, Builder.getInt64(0)});
if (!IsBoolTy)
- return LD1RQ;
+ return DupQLane;
// For svdupq_n_b* we need to add an additional 'cmpne' with '0'.
F = CGM.getIntrinsic(NumOpnds == 2 ? Intrinsic::aarch64_sve_cmpne
: Intrinsic::aarch64_sve_cmpne_wide,
OverloadedTy);
- Value *Call =
- Builder.CreateCall(F, {Pred, LD1RQ, EmitSVEDupX(Builder.getInt64(0))});
+ Value *Call = Builder.CreateCall(
+ F, {Pred, DupQLane, EmitSVEDupX(Builder.getInt64(0))});
return EmitSVEPredicateCast(Call, cast<llvm::ScalableVectorType>(Ty));
}
@@ -9051,6 +9312,38 @@
"cls");
}
+ if (BuiltinID == AArch64::BI__builtin_arm_frint32zf ||
+ BuiltinID == AArch64::BI__builtin_arm_frint32z) {
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ llvm::Type *Ty = Arg->getType();
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_frint32z, Ty),
+ Arg, "frint32z");
+ }
+
+ if (BuiltinID == AArch64::BI__builtin_arm_frint64zf ||
+ BuiltinID == AArch64::BI__builtin_arm_frint64z) {
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ llvm::Type *Ty = Arg->getType();
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_frint64z, Ty),
+ Arg, "frint64z");
+ }
+
+ if (BuiltinID == AArch64::BI__builtin_arm_frint32xf ||
+ BuiltinID == AArch64::BI__builtin_arm_frint32x) {
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ llvm::Type *Ty = Arg->getType();
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_frint32x, Ty),
+ Arg, "frint32x");
+ }
+
+ if (BuiltinID == AArch64::BI__builtin_arm_frint64xf ||
+ BuiltinID == AArch64::BI__builtin_arm_frint64x) {
+ llvm::Value *Arg = EmitScalarExpr(E->getArg(0));
+ llvm::Type *Ty = Arg->getType();
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::aarch64_frint64x, Ty),
+ Arg, "frint64x");
+ }
+
if (BuiltinID == AArch64::BI__builtin_arm_jcvt) {
assert((getContext().getTypeSize(E->getType()) == 32) &&
"__jcvt of unusual size!");
@@ -9073,7 +9366,8 @@
llvm::Value *Val = Builder.CreateCall(F, MemAddr);
llvm::Value *ToRet;
for (size_t i = 0; i < 8; i++) {
- llvm::Value *ValOffsetPtr = Builder.CreateGEP(ValPtr, Builder.getInt32(i));
+ llvm::Value *ValOffsetPtr =
+ Builder.CreateGEP(Int64Ty, ValPtr, Builder.getInt32(i));
Address Addr(ValOffsetPtr, CharUnits::fromQuantity(8));
ToRet = Builder.CreateStore(Builder.CreateExtractValue(Val, i), Addr);
}
@@ -9084,7 +9378,8 @@
SmallVector<llvm::Value *, 9> Args;
Args.push_back(MemAddr);
for (size_t i = 0; i < 8; i++) {
- llvm::Value *ValOffsetPtr = Builder.CreateGEP(ValPtr, Builder.getInt32(i));
+ llvm::Value *ValOffsetPtr =
+ Builder.CreateGEP(Int64Ty, ValPtr, Builder.getInt32(i));
Address Addr(ValOffsetPtr, CharUnits::fromQuantity(8));
Args.push_back(Builder.CreateLoad(Addr));
}
@@ -9099,6 +9394,23 @@
}
}
+ if (BuiltinID == AArch64::BI__builtin_arm_rndr ||
+ BuiltinID == AArch64::BI__builtin_arm_rndrrs) {
+
+ auto Intr = (BuiltinID == AArch64::BI__builtin_arm_rndr
+ ? Intrinsic::aarch64_rndr
+ : Intrinsic::aarch64_rndrrs);
+ Function *F = CGM.getIntrinsic(Intr);
+ llvm::Value *Val = Builder.CreateCall(F);
+ Value *RandomValue = Builder.CreateExtractValue(Val, 0);
+ Value *Status = Builder.CreateExtractValue(Val, 1);
+
+ Address MemAddress = EmitPointerWithAlignment(E->getArg(0));
+ Builder.CreateStore(RandomValue, MemAddress);
+ Status = Builder.CreateZExt(Status, Int32Ty);
+ return Status;
+ }
+
if (BuiltinID == AArch64::BI__clear_cache) {
assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments");
const FunctionDecl *FD = E->getDirectCallee();
@@ -9212,7 +9524,7 @@
llvm::APSInt Value = Result.Val.getInt();
LLVMContext &Context = CGM.getLLVMContext();
- std::string Reg = Value == 31 ? "sp" : "x" + Value.toString(10);
+ std::string Reg = Value == 31 ? "sp" : "x" + toString(Value, 10);
llvm::Metadata *Ops[] = {llvm::MDString::get(Context, Reg)};
llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops);
@@ -9491,6 +9803,15 @@
case NEON::BI__builtin_neon_vabsh_f16:
Ops.push_back(EmitScalarExpr(E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::fabs, HalfTy), Ops, "vabs");
+ case NEON::BI__builtin_neon_vaddq_p128: {
+ llvm::Type *Ty = GetNeonType(this, NeonTypeFlags::Poly128);
+ Ops.push_back(EmitScalarExpr(E->getArg(1)));
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
+ Ops[0] = Builder.CreateXor(Ops[0], Ops[1]);
+ llvm::Type *Int128Ty = llvm::Type::getIntNTy(getLLVMContext(), 128);
+ return Builder.CreateBitCast(Ops[0], Int128Ty);
+ }
case NEON::BI__builtin_neon_vldrq_p128: {
llvm::Type *Int128Ty = llvm::Type::getIntNTy(getLLVMContext(), 128);
llvm::Type *Int128PTy = llvm::PointerType::get(Int128Ty, 0);
@@ -10392,17 +10713,23 @@
}
case NEON::BI__builtin_neon_vrndnh_f16: {
Ops.push_back(EmitScalarExpr(E->getArg(0)));
- Int = Intrinsic::aarch64_neon_frintn;
+ Int = Builder.getIsFPConstrained()
+ ? Intrinsic::experimental_constrained_roundeven
+ : Intrinsic::roundeven;
return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndn");
}
case NEON::BI__builtin_neon_vrndn_v:
case NEON::BI__builtin_neon_vrndnq_v: {
- Int = Intrinsic::aarch64_neon_frintn;
+ Int = Builder.getIsFPConstrained()
+ ? Intrinsic::experimental_constrained_roundeven
+ : Intrinsic::roundeven;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrndn");
}
case NEON::BI__builtin_neon_vrndns_f32: {
Ops.push_back(EmitScalarExpr(E->getArg(0)));
- Int = Intrinsic::aarch64_neon_frintn;
+ Int = Builder.getIsFPConstrained()
+ ? Intrinsic::experimental_constrained_roundeven
+ : Intrinsic::roundeven;
return EmitNeonCall(CGM.getIntrinsic(Int, FloatTy), Ops, "vrndn");
}
case NEON::BI__builtin_neon_vrndph_f16: {
@@ -10440,6 +10767,30 @@
: Intrinsic::trunc;
return EmitNeonCall(CGM.getIntrinsic(Int, HalfTy), Ops, "vrndz");
}
+ case NEON::BI__builtin_neon_vrnd32x_v:
+ case NEON::BI__builtin_neon_vrnd32xq_v: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::aarch64_neon_frint32x;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnd32x");
+ }
+ case NEON::BI__builtin_neon_vrnd32z_v:
+ case NEON::BI__builtin_neon_vrnd32zq_v: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::aarch64_neon_frint32z;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnd32z");
+ }
+ case NEON::BI__builtin_neon_vrnd64x_v:
+ case NEON::BI__builtin_neon_vrnd64xq_v: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::aarch64_neon_frint64x;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnd64x");
+ }
+ case NEON::BI__builtin_neon_vrnd64z_v:
+ case NEON::BI__builtin_neon_vrnd64zq_v: {
+ Ops.push_back(EmitScalarExpr(E->getArg(0)));
+ Int = Intrinsic::aarch64_neon_frint64z;
+ return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrnd64z");
+ }
case NEON::BI__builtin_neon_vrnd_v:
case NEON::BI__builtin_neon_vrndq_v: {
Int = Builder.getIsFPConstrained()
@@ -10610,7 +10961,7 @@
}
case NEON::BI__builtin_neon_vrbit_v:
case NEON::BI__builtin_neon_vrbitq_v: {
- Int = Intrinsic::aarch64_neon_rbit;
+ Int = Intrinsic::bitreverse;
return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vrbit");
}
case NEON::BI__builtin_neon_vaddv_u8:
@@ -11445,14 +11796,14 @@
static Value *EmitX86MaskedLoad(CodeGenFunction &CGF, ArrayRef<Value *> Ops,
Align Alignment) {
// Cast the pointer to right type.
- Value *Ptr = CGF.Builder.CreateBitCast(Ops[0],
- llvm::PointerType::getUnqual(Ops[1]->getType()));
+ llvm::Type *Ty = Ops[1]->getType();
+ Value *Ptr =
+ CGF.Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(Ty));
Value *MaskVec = getMaskVecValue(
- CGF, Ops[2],
- cast<llvm::FixedVectorType>(Ops[1]->getType())->getNumElements());
+ CGF, Ops[2], cast<llvm::FixedVectorType>(Ty)->getNumElements());
- return CGF.Builder.CreateMaskedLoad(Ptr, Alignment, MaskVec, Ops[1]);
+ return CGF.Builder.CreateMaskedLoad(Ty, Ptr, Alignment, MaskVec, Ops[1]);
}
static Value *EmitX86ExpandLoad(CodeGenFunction &CGF,
@@ -11664,7 +12015,7 @@
return EmitX86MaskedCompare(CGF, 1, true, { In, Zero });
}
-static Value *EmitX86ConvertIntToFp(CodeGenFunction &CGF,
+static Value *EmitX86ConvertIntToFp(CodeGenFunction &CGF, const CallExpr *E,
ArrayRef<Value *> Ops, bool IsSigned) {
unsigned Rnd = cast<llvm::ConstantInt>(Ops[3])->getZExtValue();
llvm::Type *Ty = Ops[1]->getType();
@@ -11676,6 +12027,7 @@
Function *F = CGF.CGM.getIntrinsic(IID, { Ty, Ops[0]->getType() });
Res = CGF.Builder.CreateCall(F, { Ops[0], Ops[3] });
} else {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
Res = IsSigned ? CGF.Builder.CreateSIToFP(Ops[0], Ty)
: CGF.Builder.CreateUIToFP(Ops[0], Ty);
}
@@ -11684,8 +12036,9 @@
}
// Lowers X86 FMA intrinsics to IR.
-static Value *EmitX86FMAExpr(CodeGenFunction &CGF, ArrayRef<Value *> Ops,
- unsigned BuiltinID, bool IsAddSub) {
+static Value *EmitX86FMAExpr(CodeGenFunction &CGF, const CallExpr *E,
+ ArrayRef<Value *> Ops, unsigned BuiltinID,
+ bool IsAddSub) {
bool Subtract = false;
Intrinsic::ID IID = Intrinsic::not_intrinsic;
@@ -11742,6 +12095,7 @@
llvm::Type *Ty = A->getType();
Function *FMA;
if (CGF.Builder.getIsFPConstrained()) {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
FMA = CGF.CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, Ty);
Res = CGF.Builder.CreateConstrainedFPCall(FMA, {A, B, C});
} else {
@@ -11783,10 +12137,10 @@
return Res;
}
-static Value *
-EmitScalarFMAExpr(CodeGenFunction &CGF, MutableArrayRef<Value *> Ops,
- Value *Upper, bool ZeroMask = false, unsigned PTIdx = 0,
- bool NegAcc = false) {
+static Value *EmitScalarFMAExpr(CodeGenFunction &CGF, const CallExpr *E,
+ MutableArrayRef<Value *> Ops, Value *Upper,
+ bool ZeroMask = false, unsigned PTIdx = 0,
+ bool NegAcc = false) {
unsigned Rnd = 4;
if (Ops.size() > 4)
Rnd = cast<llvm::ConstantInt>(Ops[4])->getZExtValue();
@@ -11805,6 +12159,7 @@
Res = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(IID),
{Ops[0], Ops[1], Ops[2], Ops[4]});
} else if (CGF.Builder.getIsFPConstrained()) {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
Function *FMA = CGF.CGM.getIntrinsic(
Intrinsic::experimental_constrained_fma, Ops[0]->getType());
Res = CGF.Builder.CreateConstrainedFPCall(FMA, Ops.slice(0, 3));
@@ -11993,7 +12348,8 @@
llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
ConstantInt::get(Int32Ty, Index)};
llvm::Value *CpuValue = Builder.CreateGEP(STy, CpuModel, Idxs);
- CpuValue = Builder.CreateAlignedLoad(CpuValue, CharUnits::fromQuantity(4));
+ CpuValue = Builder.CreateAlignedLoad(Int32Ty, CpuValue,
+ CharUnits::fromQuantity(4));
// Check the value of the field against the requested value.
return Builder.CreateICmpEQ(CpuValue,
@@ -12050,8 +12406,8 @@
Value *Idxs[] = {Builder.getInt32(0), Builder.getInt32(3),
Builder.getInt32(0)};
Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs);
- Value *Features =
- Builder.CreateAlignedLoad(CpuFeatures, CharUnits::fromQuantity(4));
+ Value *Features = Builder.CreateAlignedLoad(Int32Ty, CpuFeatures,
+ CharUnits::fromQuantity(4));
// Check the value of the bit corresponding to the feature requested.
Value *Mask = Builder.getInt32(Features1);
@@ -12065,8 +12421,8 @@
"__cpu_features2");
cast<llvm::GlobalValue>(CpuFeatures2)->setDSOLocal(true);
- Value *Features =
- Builder.CreateAlignedLoad(CpuFeatures2, CharUnits::fromQuantity(4));
+ Value *Features = Builder.CreateAlignedLoad(Int32Ty, CpuFeatures2,
+ CharUnits::fromQuantity(4));
// Check the value of the bit corresponding to the feature requested.
Value *Mask = Builder.getInt32(Features2);
@@ -12142,8 +12498,9 @@
// TODO: The builtins could be removed if the SSE header files used vector
// extension comparisons directly (vector ordered/unordered may need
// additional support via __builtin_isnan()).
- auto getVectorFCmpIR = [this, &Ops](CmpInst::Predicate Pred,
- bool IsSignaling) {
+ auto getVectorFCmpIR = [this, &Ops, E](CmpInst::Predicate Pred,
+ bool IsSignaling) {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
Value *Cmp;
if (IsSignaling)
Cmp = Builder.CreateFCmpS(Pred, Ops[0], Ops[1]);
@@ -12385,31 +12742,31 @@
case X86::BI__builtin_ia32_cvtdq2ps512_mask:
case X86::BI__builtin_ia32_cvtqq2ps512_mask:
case X86::BI__builtin_ia32_cvtqq2pd512_mask:
- return EmitX86ConvertIntToFp(*this, Ops, /*IsSigned*/true);
+ return EmitX86ConvertIntToFp(*this, E, Ops, /*IsSigned*/ true);
case X86::BI__builtin_ia32_cvtudq2ps512_mask:
case X86::BI__builtin_ia32_cvtuqq2ps512_mask:
case X86::BI__builtin_ia32_cvtuqq2pd512_mask:
- return EmitX86ConvertIntToFp(*this, Ops, /*IsSigned*/false);
+ return EmitX86ConvertIntToFp(*this, E, Ops, /*IsSigned*/ false);
case X86::BI__builtin_ia32_vfmaddss3:
case X86::BI__builtin_ia32_vfmaddsd3:
case X86::BI__builtin_ia32_vfmaddss3_mask:
case X86::BI__builtin_ia32_vfmaddsd3_mask:
- return EmitScalarFMAExpr(*this, Ops, Ops[0]);
+ return EmitScalarFMAExpr(*this, E, Ops, Ops[0]);
case X86::BI__builtin_ia32_vfmaddss:
case X86::BI__builtin_ia32_vfmaddsd:
- return EmitScalarFMAExpr(*this, Ops,
+ return EmitScalarFMAExpr(*this, E, Ops,
Constant::getNullValue(Ops[0]->getType()));
case X86::BI__builtin_ia32_vfmaddss3_maskz:
case X86::BI__builtin_ia32_vfmaddsd3_maskz:
- return EmitScalarFMAExpr(*this, Ops, Ops[0], /*ZeroMask*/true);
+ return EmitScalarFMAExpr(*this, E, Ops, Ops[0], /*ZeroMask*/ true);
case X86::BI__builtin_ia32_vfmaddss3_mask3:
case X86::BI__builtin_ia32_vfmaddsd3_mask3:
- return EmitScalarFMAExpr(*this, Ops, Ops[2], /*ZeroMask*/false, 2);
+ return EmitScalarFMAExpr(*this, E, Ops, Ops[2], /*ZeroMask*/ false, 2);
case X86::BI__builtin_ia32_vfmsubss3_mask3:
case X86::BI__builtin_ia32_vfmsubsd3_mask3:
- return EmitScalarFMAExpr(*this, Ops, Ops[2], /*ZeroMask*/false, 2,
- /*NegAcc*/true);
+ return EmitScalarFMAExpr(*this, E, Ops, Ops[2], /*ZeroMask*/ false, 2,
+ /*NegAcc*/ true);
case X86::BI__builtin_ia32_vfmaddps:
case X86::BI__builtin_ia32_vfmaddpd:
case X86::BI__builtin_ia32_vfmaddps256:
@@ -12422,7 +12779,7 @@
case X86::BI__builtin_ia32_vfmaddpd512_maskz:
case X86::BI__builtin_ia32_vfmaddpd512_mask3:
case X86::BI__builtin_ia32_vfmsubpd512_mask3:
- return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/false);
+ return EmitX86FMAExpr(*this, E, Ops, BuiltinID, /*IsAddSub*/ false);
case X86::BI__builtin_ia32_vfmaddsubps512_mask:
case X86::BI__builtin_ia32_vfmaddsubps512_maskz:
case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
@@ -12431,7 +12788,7 @@
case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
- return EmitX86FMAExpr(*this, Ops, BuiltinID, /*IsAddSub*/true);
+ return EmitX86FMAExpr(*this, E, Ops, BuiltinID, /*IsAddSub*/ true);
case X86::BI__builtin_ia32_movdqa32store128_mask:
case X86::BI__builtin_ia32_movdqa64store128_mask:
@@ -13091,8 +13448,8 @@
cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();
unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue() & 0xff;
- // Mask the shift amount to width of two vectors.
- ShiftVal &= (2 * NumElts) - 1;
+ // Mask the shift amount to width of a vector.
+ ShiftVal &= NumElts - 1;
int Indices[16];
for (unsigned i = 0; i != NumElts; ++i)
@@ -13577,6 +13934,7 @@
Value *A = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
Function *F;
if (Builder.getIsFPConstrained()) {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
F = CGM.getIntrinsic(Intrinsic::experimental_constrained_sqrt,
A->getType());
A = Builder.CreateConstrainedFPCall(F, {A});
@@ -13600,6 +13958,7 @@
Value *A = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
Function *F;
if (Builder.getIsFPConstrained()) {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
F = CGM.getIntrinsic(Intrinsic::experimental_constrained_sqrt,
A->getType());
A = Builder.CreateConstrainedFPCall(F, A);
@@ -13629,6 +13988,7 @@
}
}
if (Builder.getIsFPConstrained()) {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_sqrt,
Ops[0]->getType());
return Builder.CreateConstrainedFPCall(F, Ops[0]);
@@ -13794,16 +14154,30 @@
case X86::BI__builtin_ia32_reduce_fadd_ps512: {
Function *F =
CGM.getIntrinsic(Intrinsic::vector_reduce_fadd, Ops[1]->getType());
- Builder.getFastMathFlags().setAllowReassoc(true);
+ Builder.getFastMathFlags().setAllowReassoc();
return Builder.CreateCall(F, {Ops[0], Ops[1]});
}
case X86::BI__builtin_ia32_reduce_fmul_pd512:
case X86::BI__builtin_ia32_reduce_fmul_ps512: {
Function *F =
CGM.getIntrinsic(Intrinsic::vector_reduce_fmul, Ops[1]->getType());
- Builder.getFastMathFlags().setAllowReassoc(true);
+ Builder.getFastMathFlags().setAllowReassoc();
return Builder.CreateCall(F, {Ops[0], Ops[1]});
}
+ case X86::BI__builtin_ia32_reduce_fmax_pd512:
+ case X86::BI__builtin_ia32_reduce_fmax_ps512: {
+ Function *F =
+ CGM.getIntrinsic(Intrinsic::vector_reduce_fmax, Ops[0]->getType());
+ Builder.getFastMathFlags().setNoNaNs();
+ return Builder.CreateCall(F, {Ops[0]});
+ }
+ case X86::BI__builtin_ia32_reduce_fmin_pd512:
+ case X86::BI__builtin_ia32_reduce_fmin_ps512: {
+ Function *F =
+ CGM.getIntrinsic(Intrinsic::vector_reduce_fmin, Ops[0]->getType());
+ Builder.getFastMathFlags().setNoNaNs();
+ return Builder.CreateCall(F, {Ops[0]});
+ }
case X86::BI__builtin_ia32_reduce_mul_d512:
case X86::BI__builtin_ia32_reduce_mul_q512: {
Function *F =
@@ -14175,6 +14549,8 @@
if (IsMaskFCmp) {
// We ignore SAE if strict FP is disabled. We only keep precise
// exception behavior under strict FP.
+ // NOTE: If strict FP does ever go through here a CGFPOptionsRAII
+ // object will be required.
unsigned NumElts =
cast<llvm::FixedVectorType>(Ops[0]->getType())->getNumElements();
Value *Cmp;
@@ -14227,8 +14603,10 @@
case X86::BI__builtin_ia32_vcvtph2ps256:
case X86::BI__builtin_ia32_vcvtph2ps_mask:
case X86::BI__builtin_ia32_vcvtph2ps256_mask:
- case X86::BI__builtin_ia32_vcvtph2ps512_mask:
+ case X86::BI__builtin_ia32_vcvtph2ps512_mask: {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
return EmitX86CvtF16ToFloatExpr(*this, Ops, ConvertType(E->getType()));
+ }
// AVX512 bf16 intrinsics
case X86::BI__builtin_ia32_cvtneps2bf16_128_mask: {
@@ -14401,7 +14779,7 @@
for (int i = 0; i < 6; ++i) {
Value *Extract = Builder.CreateExtractValue(Call, i + 1);
- Value *Ptr = Builder.CreateConstGEP1_32(Ops[2], i * 16);
+ Value *Ptr = Builder.CreateConstGEP1_32(Int8Ty, Ops[2], i * 16);
Ptr = Builder.CreateBitCast(
Ptr, llvm::PointerType::getUnqual(Extract->getType()));
Builder.CreateAlignedStore(Extract, Ptr, Align(1));
@@ -14417,7 +14795,7 @@
for (int i = 0; i < 7; ++i) {
Value *Extract = Builder.CreateExtractValue(Call, i + 1);
- Value *Ptr = Builder.CreateConstGEP1_32(Ops[3], i * 16);
+ Value *Ptr = Builder.CreateConstGEP1_32(Int8Ty, Ops[3], i * 16);
Ptr = Builder.CreateBitCast(
Ptr, llvm::PointerType::getUnqual(Extract->getType()));
Builder.CreateAlignedStore(Extract, Ptr, Align(1));
@@ -14430,27 +14808,50 @@
case X86::BI__builtin_ia32_aesenc256kl_u8:
case X86::BI__builtin_ia32_aesdec256kl_u8: {
Intrinsic::ID IID;
+ StringRef BlockName;
switch (BuiltinID) {
- default: llvm_unreachable("Unexpected builtin");
+ default:
+ llvm_unreachable("Unexpected builtin");
case X86::BI__builtin_ia32_aesenc128kl_u8:
IID = Intrinsic::x86_aesenc128kl;
+ BlockName = "aesenc128kl";
break;
case X86::BI__builtin_ia32_aesdec128kl_u8:
IID = Intrinsic::x86_aesdec128kl;
+ BlockName = "aesdec128kl";
break;
case X86::BI__builtin_ia32_aesenc256kl_u8:
IID = Intrinsic::x86_aesenc256kl;
+ BlockName = "aesenc256kl";
break;
case X86::BI__builtin_ia32_aesdec256kl_u8:
IID = Intrinsic::x86_aesdec256kl;
+ BlockName = "aesdec256kl";
break;
}
Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), {Ops[1], Ops[2]});
- Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 1),
- Ops[0]);
+ BasicBlock *NoError =
+ createBasicBlock(BlockName + "_no_error", this->CurFn);
+ BasicBlock *Error = createBasicBlock(BlockName + "_error", this->CurFn);
+ BasicBlock *End = createBasicBlock(BlockName + "_end", this->CurFn);
+ Value *Ret = Builder.CreateExtractValue(Call, 0);
+ Value *Succ = Builder.CreateTrunc(Ret, Builder.getInt1Ty());
+ Value *Out = Builder.CreateExtractValue(Call, 1);
+ Builder.CreateCondBr(Succ, NoError, Error);
+
+ Builder.SetInsertPoint(NoError);
+ Builder.CreateDefaultAlignedStore(Out, Ops[0]);
+ Builder.CreateBr(End);
+
+ Builder.SetInsertPoint(Error);
+ Constant *Zero = llvm::Constant::getNullValue(Out->getType());
+ Builder.CreateDefaultAlignedStore(Zero, Ops[0]);
+ Builder.CreateBr(End);
+
+ Builder.SetInsertPoint(End);
return Builder.CreateExtractValue(Call, 0);
}
case X86::BI__builtin_ia32_aesencwide128kl_u8:
@@ -14458,36 +14859,63 @@
case X86::BI__builtin_ia32_aesencwide256kl_u8:
case X86::BI__builtin_ia32_aesdecwide256kl_u8: {
Intrinsic::ID IID;
+ StringRef BlockName;
switch (BuiltinID) {
case X86::BI__builtin_ia32_aesencwide128kl_u8:
IID = Intrinsic::x86_aesencwide128kl;
+ BlockName = "aesencwide128kl";
break;
case X86::BI__builtin_ia32_aesdecwide128kl_u8:
IID = Intrinsic::x86_aesdecwide128kl;
+ BlockName = "aesdecwide128kl";
break;
case X86::BI__builtin_ia32_aesencwide256kl_u8:
IID = Intrinsic::x86_aesencwide256kl;
+ BlockName = "aesencwide256kl";
break;
case X86::BI__builtin_ia32_aesdecwide256kl_u8:
IID = Intrinsic::x86_aesdecwide256kl;
+ BlockName = "aesdecwide256kl";
break;
}
+ llvm::Type *Ty = FixedVectorType::get(Builder.getInt64Ty(), 2);
Value *InOps[9];
InOps[0] = Ops[2];
for (int i = 0; i != 8; ++i) {
- Value *Ptr = Builder.CreateConstGEP1_32(Ops[1], i);
- InOps[i + 1] = Builder.CreateAlignedLoad(Ptr, Align(16));
+ Value *Ptr = Builder.CreateConstGEP1_32(Ty, Ops[1], i);
+ InOps[i + 1] = Builder.CreateAlignedLoad(Ty, Ptr, Align(16));
}
Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), InOps);
+ BasicBlock *NoError =
+ createBasicBlock(BlockName + "_no_error", this->CurFn);
+ BasicBlock *Error = createBasicBlock(BlockName + "_error", this->CurFn);
+ BasicBlock *End = createBasicBlock(BlockName + "_end", this->CurFn);
+
+ Value *Ret = Builder.CreateExtractValue(Call, 0);
+ Value *Succ = Builder.CreateTrunc(Ret, Builder.getInt1Ty());
+ Builder.CreateCondBr(Succ, NoError, Error);
+
+ Builder.SetInsertPoint(NoError);
for (int i = 0; i != 8; ++i) {
Value *Extract = Builder.CreateExtractValue(Call, i + 1);
- Value *Ptr = Builder.CreateConstGEP1_32(Ops[0], i);
+ Value *Ptr = Builder.CreateConstGEP1_32(Extract->getType(), Ops[0], i);
Builder.CreateAlignedStore(Extract, Ptr, Align(16));
}
+ Builder.CreateBr(End);
+ Builder.SetInsertPoint(Error);
+ for (int i = 0; i != 8; ++i) {
+ Value *Out = Builder.CreateExtractValue(Call, i + 1);
+ Constant *Zero = llvm::Constant::getNullValue(Out->getType());
+ Value *Ptr = Builder.CreateConstGEP1_32(Out->getType(), Ops[0], i);
+ Builder.CreateAlignedStore(Zero, Ptr, Align(16));
+ }
+ Builder.CreateBr(End);
+
+ Builder.SetInsertPoint(End);
return Builder.CreateExtractValue(Call, 0);
}
}
@@ -14530,7 +14958,7 @@
Ops[0] = Builder.CreateBitCast(Ops[0], Int8PtrTy);
}else {
Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy);
- Ops[0] = Builder.CreateGEP(Ops[1], Ops[0]);
+ Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]);
Ops.pop_back();
}
@@ -14598,7 +15026,7 @@
Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy);
}else {
Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy);
- Ops[1] = Builder.CreateGEP(Ops[2], Ops[1]);
+ Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]);
Ops.pop_back();
}
@@ -14641,6 +15069,143 @@
llvm::Function *F = CGM.getIntrinsic(ID);
return Builder.CreateCall(F, Ops, "");
}
+ case PPC::BI__builtin_vsx_ldrmb: {
+ // Essentially boils down to performing an unaligned VMX load sequence so
+ // as to avoid crossing a page boundary and then shuffling the elements
+ // into the right side of the vector register.
+ int64_t NumBytes = cast<ConstantInt>(Ops[1])->getZExtValue();
+ llvm::Type *ResTy = ConvertType(E->getType());
+ bool IsLE = getTarget().isLittleEndian();
+
+ // If the user wants the entire vector, just load the entire vector.
+ if (NumBytes == 16) {
+ Value *BC = Builder.CreateBitCast(Ops[0], ResTy->getPointerTo());
+ Value *LD = Builder.CreateLoad(Address(BC, CharUnits::fromQuantity(1)));
+ if (!IsLE)
+ return LD;
+
+ // Reverse the bytes on LE.
+ SmallVector<int, 16> RevMask;
+ for (int Idx = 0; Idx < 16; Idx++)
+ RevMask.push_back(15 - Idx);
+ return Builder.CreateShuffleVector(LD, LD, RevMask);
+ }
+
+ llvm::Function *Lvx = CGM.getIntrinsic(Intrinsic::ppc_altivec_lvx);
+ llvm::Function *Lvs = CGM.getIntrinsic(IsLE ? Intrinsic::ppc_altivec_lvsr
+ : Intrinsic::ppc_altivec_lvsl);
+ llvm::Function *Vperm = CGM.getIntrinsic(Intrinsic::ppc_altivec_vperm);
+ Value *HiMem = Builder.CreateGEP(
+ Int8Ty, Ops[0], ConstantInt::get(Ops[1]->getType(), NumBytes - 1));
+ Value *LoLd = Builder.CreateCall(Lvx, Ops[0], "ld.lo");
+ Value *HiLd = Builder.CreateCall(Lvx, HiMem, "ld.hi");
+ Value *Mask1 = Builder.CreateCall(Lvs, Ops[0], "mask1");
+
+ Ops.clear();
+ Ops.push_back(IsLE ? HiLd : LoLd);
+ Ops.push_back(IsLE ? LoLd : HiLd);
+ Ops.push_back(Mask1);
+ Value *AllElts = Builder.CreateCall(Vperm, Ops, "shuffle1");
+ Constant *Zero = llvm::Constant::getNullValue(IsLE ? ResTy : AllElts->getType());
+
+ if (IsLE) {
+ SmallVector<int, 16> Consts;
+ for (int Idx = 0; Idx < 16; Idx++) {
+ int Val = (NumBytes - Idx - 1 >= 0) ? (NumBytes - Idx - 1)
+ : 16 - (NumBytes - Idx);
+ Consts.push_back(Val);
+ }
+ return Builder.CreateShuffleVector(Builder.CreateBitCast(AllElts, ResTy),
+ Zero, Consts);
+ }
+ SmallVector<Constant *, 16> Consts;
+ for (int Idx = 0; Idx < 16; Idx++)
+ Consts.push_back(Builder.getInt8(NumBytes + Idx));
+ Value *Mask2 = ConstantVector::get(Consts);
+ return Builder.CreateBitCast(
+ Builder.CreateCall(Vperm, {Zero, AllElts, Mask2}, "shuffle2"), ResTy);
+ }
+ case PPC::BI__builtin_vsx_strmb: {
+ int64_t NumBytes = cast<ConstantInt>(Ops[1])->getZExtValue();
+ bool IsLE = getTarget().isLittleEndian();
+ auto StoreSubVec = [&](unsigned Width, unsigned Offset, unsigned EltNo) {
+ // Storing the whole vector, simply store it on BE and reverse bytes and
+ // store on LE.
+ if (Width == 16) {
+ Value *BC =
+ Builder.CreateBitCast(Ops[0], Ops[2]->getType()->getPointerTo());
+ Value *StVec = Ops[2];
+ if (IsLE) {
+ SmallVector<int, 16> RevMask;
+ for (int Idx = 0; Idx < 16; Idx++)
+ RevMask.push_back(15 - Idx);
+ StVec = Builder.CreateShuffleVector(Ops[2], Ops[2], RevMask);
+ }
+ return Builder.CreateStore(StVec,
+ Address(BC, CharUnits::fromQuantity(1)));
+ }
+ auto *ConvTy = Int64Ty;
+ unsigned NumElts = 0;
+ switch (Width) {
+ default:
+ llvm_unreachable("width for stores must be a power of 2");
+ case 8:
+ ConvTy = Int64Ty;
+ NumElts = 2;
+ break;
+ case 4:
+ ConvTy = Int32Ty;
+ NumElts = 4;
+ break;
+ case 2:
+ ConvTy = Int16Ty;
+ NumElts = 8;
+ break;
+ case 1:
+ ConvTy = Int8Ty;
+ NumElts = 16;
+ break;
+ }
+ Value *Vec = Builder.CreateBitCast(
+ Ops[2], llvm::FixedVectorType::get(ConvTy, NumElts));
+ Value *Ptr = Builder.CreateGEP(Int8Ty, Ops[0],
+ ConstantInt::get(Int64Ty, Offset));
+ Value *PtrBC = Builder.CreateBitCast(Ptr, ConvTy->getPointerTo());
+ Value *Elt = Builder.CreateExtractElement(Vec, EltNo);
+ if (IsLE && Width > 1) {
+ Function *F = CGM.getIntrinsic(Intrinsic::bswap, ConvTy);
+ Elt = Builder.CreateCall(F, Elt);
+ }
+ return Builder.CreateStore(Elt,
+ Address(PtrBC, CharUnits::fromQuantity(1)));
+ };
+ unsigned Stored = 0;
+ unsigned RemainingBytes = NumBytes;
+ Value *Result;
+ if (NumBytes == 16)
+ return StoreSubVec(16, 0, 0);
+ if (NumBytes >= 8) {
+ Result = StoreSubVec(8, NumBytes - 8, IsLE ? 0 : 1);
+ RemainingBytes -= 8;
+ Stored += 8;
+ }
+ if (RemainingBytes >= 4) {
+ Result = StoreSubVec(4, NumBytes - Stored - 4,
+ IsLE ? (Stored >> 2) : 3 - (Stored >> 2));
+ RemainingBytes -= 4;
+ Stored += 4;
+ }
+ if (RemainingBytes >= 2) {
+ Result = StoreSubVec(2, NumBytes - Stored - 2,
+ IsLE ? (Stored >> 1) : 7 - (Stored >> 1));
+ RemainingBytes -= 2;
+ Stored += 2;
+ }
+ if (RemainingBytes)
+ Result =
+ StoreSubVec(1, NumBytes - Stored - 1, IsLE ? Stored : 15 - Stored);
+ return Result;
+ }
// Square root
case PPC::BI__builtin_vsx_xvsqrtsp:
case PPC::BI__builtin_vsx_xvsqrtdp: {
@@ -14742,6 +15307,92 @@
llvm::Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ResultType);
return Builder.CreateCall(F, X);
}
+ case PPC::BI__builtin_altivec_vadduqm:
+ case PPC::BI__builtin_altivec_vsubuqm: {
+ llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);
+ Ops[0] =
+ Builder.CreateBitCast(Ops[0], llvm::FixedVectorType::get(Int128Ty, 1));
+ Ops[1] =
+ Builder.CreateBitCast(Ops[1], llvm::FixedVectorType::get(Int128Ty, 1));
+ if (BuiltinID == PPC::BI__builtin_altivec_vadduqm)
+ return Builder.CreateAdd(Ops[0], Ops[1], "vadduqm");
+ else
+ return Builder.CreateSub(Ops[0], Ops[1], "vsubuqm");
+ }
+ // Rotate and insert under mask operation.
+ // __rldimi(rs, is, shift, mask)
+ // (rotl64(rs, shift) & mask) | (is & ~mask)
+ // __rlwimi(rs, is, shift, mask)
+ // (rotl(rs, shift) & mask) | (is & ~mask)
+ case PPC::BI__builtin_ppc_rldimi:
+ case PPC::BI__builtin_ppc_rlwimi: {
+ llvm::Type *Ty = Ops[0]->getType();
+ Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
+ if (BuiltinID == PPC::BI__builtin_ppc_rldimi)
+ Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);
+ Value *Shift = Builder.CreateCall(F, {Ops[0], Ops[0], Ops[2]});
+ Value *X = Builder.CreateAnd(Shift, Ops[3]);
+ Value *Y = Builder.CreateAnd(Ops[1], Builder.CreateNot(Ops[3]));
+ return Builder.CreateOr(X, Y);
+ }
+ // Rotate and insert under mask operation.
+ // __rlwnm(rs, shift, mask)
+ // rotl(rs, shift) & mask
+ case PPC::BI__builtin_ppc_rlwnm: {
+ llvm::Type *Ty = Ops[0]->getType();
+ Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
+ Value *Shift = Builder.CreateCall(F, {Ops[0], Ops[0], Ops[1]});
+ return Builder.CreateAnd(Shift, Ops[2]);
+ }
+ case PPC::BI__builtin_ppc_poppar4:
+ case PPC::BI__builtin_ppc_poppar8: {
+ llvm::Type *ArgType = Ops[0]->getType();
+ Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
+ Value *Tmp = Builder.CreateCall(F, Ops[0]);
+
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1));
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+ "cast");
+ return Result;
+ }
+ case PPC::BI__builtin_ppc_cmpb: {
+ if (getTarget().getTriple().isPPC64()) {
+ Function *F =
+ CGM.getIntrinsic(Intrinsic::ppc_cmpb, {Int64Ty, Int64Ty, Int64Ty});
+ return Builder.CreateCall(F, Ops, "cmpb");
+ }
+ // For 32 bit, emit the code as below:
+ // %conv = trunc i64 %a to i32
+ // %conv1 = trunc i64 %b to i32
+ // %shr = lshr i64 %a, 32
+ // %conv2 = trunc i64 %shr to i32
+ // %shr3 = lshr i64 %b, 32
+ // %conv4 = trunc i64 %shr3 to i32
+ // %0 = tail call i32 @llvm.ppc.cmpb32(i32 %conv, i32 %conv1)
+ // %conv5 = zext i32 %0 to i64
+ // %1 = tail call i32 @llvm.ppc.cmpb32(i32 %conv2, i32 %conv4)
+ // %conv614 = zext i32 %1 to i64
+ // %shl = shl nuw i64 %conv614, 32
+ // %or = or i64 %shl, %conv5
+ // ret i64 %or
+ Function *F =
+ CGM.getIntrinsic(Intrinsic::ppc_cmpb, {Int32Ty, Int32Ty, Int32Ty});
+ Value *ArgOneLo = Builder.CreateTrunc(Ops[0], Int32Ty);
+ Value *ArgTwoLo = Builder.CreateTrunc(Ops[1], Int32Ty);
+ Constant *ShiftAmt = ConstantInt::get(Int64Ty, 32);
+ Value *ArgOneHi =
+ Builder.CreateTrunc(Builder.CreateLShr(Ops[0], ShiftAmt), Int32Ty);
+ Value *ArgTwoHi =
+ Builder.CreateTrunc(Builder.CreateLShr(Ops[1], ShiftAmt), Int32Ty);
+ Value *ResLo = Builder.CreateZExt(
+ Builder.CreateCall(F, {ArgOneLo, ArgTwoLo}, "cmpb"), Int64Ty);
+ Value *ResHiShift = Builder.CreateZExt(
+ Builder.CreateCall(F, {ArgOneHi, ArgTwoHi}, "cmpb"), Int64Ty);
+ Value *ResHi = Builder.CreateShl(ResHiShift, ShiftAmt);
+ return Builder.CreateOr(ResLo, ResHi);
+ }
// Copy sign
case PPC::BI__builtin_vsx_xvcpsgnsp:
case PPC::BI__builtin_vsx_xvcpsgndp: {
@@ -14804,6 +15455,47 @@
return Builder.CreateCall(F, X);
}
+ // Fastmath by default
+ case PPC::BI__builtin_ppc_recipdivf:
+ case PPC::BI__builtin_ppc_recipdivd:
+ case PPC::BI__builtin_ppc_rsqrtf:
+ case PPC::BI__builtin_ppc_rsqrtd: {
+ FastMathFlags FMF = Builder.getFastMathFlags();
+ Builder.getFastMathFlags().setFast();
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+
+ if (BuiltinID == PPC::BI__builtin_ppc_recipdivf ||
+ BuiltinID == PPC::BI__builtin_ppc_recipdivd) {
+ Value *Y = EmitScalarExpr(E->getArg(1));
+ Value *FDiv = Builder.CreateFDiv(X, Y, "recipdiv");
+ Builder.getFastMathFlags() &= (FMF);
+ return FDiv;
+ }
+ auto *One = ConstantFP::get(ResultType, 1.0);
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType);
+ Value *FDiv = Builder.CreateFDiv(One, Builder.CreateCall(F, X), "rsqrt");
+ Builder.getFastMathFlags() &= (FMF);
+ return FDiv;
+ }
+ case PPC::BI__builtin_ppc_alignx: {
+ ConstantInt *AlignmentCI = cast<ConstantInt>(Ops[0]);
+ if (AlignmentCI->getValue().ugt(llvm::Value::MaximumAlignment))
+ AlignmentCI = ConstantInt::get(AlignmentCI->getType(),
+ llvm::Value::MaximumAlignment);
+
+ emitAlignmentAssumption(Ops[1], E->getArg(1),
+ /*The expr loc is sufficient.*/ SourceLocation(),
+ AlignmentCI, nullptr);
+ return Ops[1];
+ }
+ case PPC::BI__builtin_ppc_rdlam: {
+ llvm::Type *Ty = Ops[0]->getType();
+ Value *ShiftAmt = Builder.CreateIntCast(Ops[1], Ty, false);
+ Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
+ Value *Rotate = Builder.CreateCall(F, {Ops[0], Ops[0], ShiftAmt});
+ return Builder.CreateAnd(Rotate, Ops[2]);
+ }
// FMA variations
case PPC::BI__builtin_vsx_xvmaddadp:
case PPC::BI__builtin_vsx_xvmaddasp:
@@ -15015,13 +15707,20 @@
return Builder.CreateExtractElement(Unpacked, Index);
}
+ case PPC::BI__builtin_ppc_sthcx: {
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_sthcx);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Int8PtrTy);
+ Ops[1] = Builder.CreateSExt(Ops[1], Int32Ty);
+ return Builder.CreateCall(F, Ops);
+ }
+
// The PPC MMA builtins take a pointer to a __vector_quad as an argument.
// Some of the MMA instructions accumulate their result into an existing
// accumulator whereas the others generate a new accumulator. So we need to
// use custom code generation to expand a builtin call with a pointer to a
// load (if the corresponding instruction accumulates its result) followed by
// the call to the intrinsic and a store of the result.
-#define CUSTOM_BUILTIN(Name, Types, Accumulate) \
+#define CUSTOM_BUILTIN(Name, Intr, Types, Accumulate) \
case PPC::BI__builtin_##Name:
#include "clang/Basic/BuiltinsPPC.def"
{
@@ -15030,7 +15729,8 @@
// return values. So, here we emit code extracting these values from the
// intrinsic results and storing them using that pointer.
if (BuiltinID == PPC::BI__builtin_mma_disassemble_acc ||
- BuiltinID == PPC::BI__builtin_vsx_disassemble_pair) {
+ BuiltinID == PPC::BI__builtin_vsx_disassemble_pair ||
+ BuiltinID == PPC::BI__builtin_mma_disassemble_pair) {
unsigned NumVecs = 2;
auto Intrinsic = Intrinsic::ppc_vsx_disassemble_pair;
if (BuiltinID == PPC::BI__builtin_mma_disassemble_acc) {
@@ -15046,28 +15746,31 @@
for (unsigned i=0; i<NumVecs; i++) {
Value *Vec = Builder.CreateExtractValue(Call, i);
llvm::ConstantInt* Index = llvm::ConstantInt::get(IntTy, i);
- Value *GEP = Builder.CreateInBoundsGEP(Ptr, Index);
+ Value *GEP = Builder.CreateInBoundsGEP(VTy, Ptr, Index);
Builder.CreateAlignedStore(Vec, GEP, MaybeAlign(16));
}
return Call;
}
bool Accumulate;
switch (BuiltinID) {
- #define CUSTOM_BUILTIN(Name, Types, Acc) \
+ #define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
case PPC::BI__builtin_##Name: \
- ID = Intrinsic::ppc_##Name; \
+ ID = Intrinsic::ppc_##Intr; \
Accumulate = Acc; \
break;
#include "clang/Basic/BuiltinsPPC.def"
}
if (BuiltinID == PPC::BI__builtin_vsx_lxvp ||
- BuiltinID == PPC::BI__builtin_vsx_stxvp) {
- if (BuiltinID == PPC::BI__builtin_vsx_lxvp) {
+ BuiltinID == PPC::BI__builtin_vsx_stxvp ||
+ BuiltinID == PPC::BI__builtin_mma_lxvp ||
+ BuiltinID == PPC::BI__builtin_mma_stxvp) {
+ if (BuiltinID == PPC::BI__builtin_vsx_lxvp ||
+ BuiltinID == PPC::BI__builtin_mma_lxvp) {
Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy);
- Ops[0] = Builder.CreateGEP(Ops[1], Ops[0]);
+ Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]);
} else {
Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy);
- Ops[1] = Builder.CreateGEP(Ops[2], Ops[1]);
+ Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]);
}
Ops.pop_back();
llvm::Function *F = CGM.getIntrinsic(ID);
@@ -15085,6 +15788,125 @@
Value *Call = Builder.CreateCall(F, CallOps);
return Builder.CreateAlignedStore(Call, Ops[0], MaybeAlign(64));
}
+
+ case PPC::BI__builtin_ppc_compare_and_swap:
+ case PPC::BI__builtin_ppc_compare_and_swaplp: {
+ Address Addr = EmitPointerWithAlignment(E->getArg(0));
+ Address OldValAddr = EmitPointerWithAlignment(E->getArg(1));
+ Value *OldVal = Builder.CreateLoad(OldValAddr);
+ QualType AtomicTy = E->getArg(0)->getType()->getPointeeType();
+ LValue LV = MakeAddrLValue(Addr, AtomicTy);
+ auto Pair = EmitAtomicCompareExchange(
+ LV, RValue::get(OldVal), RValue::get(Ops[2]), E->getExprLoc(),
+ llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Monotonic, true);
+ // Unlike c11's atomic_compare_exchange, accroding to
+ // https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=functions-compare-swap-compare-swaplp
+ // > In either case, the contents of the memory location specified by addr
+ // > are copied into the memory location specified by old_val_addr.
+ // But it hasn't specified storing to OldValAddr is atomic or not and
+ // which order to use. Now following XL's codegen, treat it as a normal
+ // store.
+ Value *LoadedVal = Pair.first.getScalarVal();
+ Builder.CreateStore(LoadedVal, OldValAddr);
+ return Pair.second;
+ }
+ case PPC::BI__builtin_ppc_fetch_and_add:
+ case PPC::BI__builtin_ppc_fetch_and_addlp: {
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E,
+ llvm::AtomicOrdering::Monotonic);
+ }
+ case PPC::BI__builtin_ppc_fetch_and_and:
+ case PPC::BI__builtin_ppc_fetch_and_andlp: {
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E,
+ llvm::AtomicOrdering::Monotonic);
+ }
+
+ case PPC::BI__builtin_ppc_fetch_and_or:
+ case PPC::BI__builtin_ppc_fetch_and_orlp: {
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E,
+ llvm::AtomicOrdering::Monotonic);
+ }
+ case PPC::BI__builtin_ppc_fetch_and_swap:
+ case PPC::BI__builtin_ppc_fetch_and_swaplp: {
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E,
+ llvm::AtomicOrdering::Monotonic);
+ }
+ case PPC::BI__builtin_ppc_ldarx:
+ case PPC::BI__builtin_ppc_lwarx:
+ case PPC::BI__builtin_ppc_lharx:
+ case PPC::BI__builtin_ppc_lbarx:
+ return emitPPCLoadReserveIntrinsic(*this, BuiltinID, E);
+ case PPC::BI__builtin_ppc_mfspr: {
+ llvm::Type *RetType = CGM.getDataLayout().getTypeSizeInBits(VoidPtrTy) == 32
+ ? Int32Ty
+ : Int64Ty;
+ Function *F = CGM.getIntrinsic(Intrinsic::ppc_mfspr, RetType);
+ return Builder.CreateCall(F, Ops);
+ }
+ case PPC::BI__builtin_ppc_mtspr: {
+ llvm::Type *RetType = CGM.getDataLayout().getTypeSizeInBits(VoidPtrTy) == 32
+ ? Int32Ty
+ : Int64Ty;
+ Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtspr, RetType);
+ return Builder.CreateCall(F, Ops);
+ }
+ case PPC::BI__builtin_ppc_popcntb: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ArgType = ArgValue->getType();
+ Function *F = CGM.getIntrinsic(Intrinsic::ppc_popcntb, {ArgType, ArgType});
+ return Builder.CreateCall(F, Ops, "popcntb");
+ }
+ case PPC::BI__builtin_ppc_mtfsf: {
+ // The builtin takes a uint32 that needs to be cast to an
+ // f64 to be passed to the intrinsic.
+ Value *Cast = Builder.CreateUIToFP(Ops[1], DoubleTy);
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_mtfsf);
+ return Builder.CreateCall(F, {Ops[0], Cast}, "");
+ }
+
+ case PPC::BI__builtin_ppc_swdiv_nochk:
+ case PPC::BI__builtin_ppc_swdivs_nochk: {
+ FastMathFlags FMF = Builder.getFastMathFlags();
+ Builder.getFastMathFlags().setFast();
+ Value *FDiv = Builder.CreateFDiv(Ops[0], Ops[1], "swdiv_nochk");
+ Builder.getFastMathFlags() &= (FMF);
+ return FDiv;
+ }
+ case PPC::BI__builtin_ppc_fric:
+ return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::rint,
+ Intrinsic::experimental_constrained_rint))
+ .getScalarVal();
+ case PPC::BI__builtin_ppc_frim:
+ case PPC::BI__builtin_ppc_frims:
+ return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::floor,
+ Intrinsic::experimental_constrained_floor))
+ .getScalarVal();
+ case PPC::BI__builtin_ppc_frin:
+ case PPC::BI__builtin_ppc_frins:
+ return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::round,
+ Intrinsic::experimental_constrained_round))
+ .getScalarVal();
+ case PPC::BI__builtin_ppc_frip:
+ case PPC::BI__builtin_ppc_frips:
+ return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::ceil,
+ Intrinsic::experimental_constrained_ceil))
+ .getScalarVal();
+ case PPC::BI__builtin_ppc_friz:
+ case PPC::BI__builtin_ppc_frizs:
+ return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::trunc,
+ Intrinsic::experimental_constrained_trunc))
+ .getScalarVal();
+ case PPC::BI__builtin_ppc_fsqrt:
+ case PPC::BI__builtin_ppc_fsqrts:
+ return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
+ *this, E, Intrinsic::sqrt,
+ Intrinsic::experimental_constrained_sqrt))
+ .getScalarVal();
}
}
@@ -15115,7 +15937,7 @@
auto *DP = EmitAMDGPUDispatchPtr(CGF);
// Indexing the HSA kernel_dispatch_packet struct.
auto *Offset = llvm::ConstantInt::get(CGF.Int32Ty, XOffset + Index * 2);
- auto *GEP = CGF.Builder.CreateGEP(DP, Offset);
+ auto *GEP = CGF.Builder.CreateGEP(CGF.Int8Ty, DP, Offset);
auto *DstTy =
CGF.Int16Ty->getPointerTo(GEP->getType()->getPointerAddressSpace());
auto *Cast = CGF.Builder.CreateBitCast(GEP, DstTy);
@@ -15135,7 +15957,7 @@
auto *DP = EmitAMDGPUDispatchPtr(CGF);
// Indexing the HSA kernel_dispatch_packet struct.
auto *Offset = llvm::ConstantInt::get(CGF.Int32Ty, XOffset + Index * 4);
- auto *GEP = CGF.Builder.CreateGEP(DP, Offset);
+ auto *GEP = CGF.Builder.CreateGEP(CGF.Int8Ty, DP, Offset);
auto *DstTy =
CGF.Int32Ty->getPointerTo(GEP->getType()->getPointerAddressSpace());
auto *Cast = CGF.Builder.CreateBitCast(GEP, DstTy);
@@ -15159,8 +15981,10 @@
int ord = cast<llvm::ConstantInt>(Order)->getZExtValue();
// Map C11/C++11 memory ordering to LLVM memory ordering
+ assert(llvm::isValidAtomicOrderingCABI(ord));
switch (static_cast<llvm::AtomicOrderingCABI>(ord)) {
case llvm::AtomicOrderingCABI::acquire:
+ case llvm::AtomicOrderingCABI::consume:
AO = llvm::AtomicOrdering::Acquire;
break;
case llvm::AtomicOrderingCABI::release:
@@ -15172,8 +15996,8 @@
case llvm::AtomicOrderingCABI::seq_cst:
AO = llvm::AtomicOrdering::SequentiallyConsistent;
break;
- case llvm::AtomicOrderingCABI::consume:
case llvm::AtomicOrderingCABI::relaxed:
+ AO = llvm::AtomicOrdering::Monotonic;
break;
}
@@ -15388,6 +16212,23 @@
CI->setConvergent();
return CI;
}
+ case AMDGPU::BI__builtin_amdgcn_image_bvh_intersect_ray:
+ case AMDGPU::BI__builtin_amdgcn_image_bvh_intersect_ray_h:
+ case AMDGPU::BI__builtin_amdgcn_image_bvh_intersect_ray_l:
+ case AMDGPU::BI__builtin_amdgcn_image_bvh_intersect_ray_lh: {
+ llvm::Value *NodePtr = EmitScalarExpr(E->getArg(0));
+ llvm::Value *RayExtent = EmitScalarExpr(E->getArg(1));
+ llvm::Value *RayOrigin = EmitScalarExpr(E->getArg(2));
+ llvm::Value *RayDir = EmitScalarExpr(E->getArg(3));
+ llvm::Value *RayInverseDir = EmitScalarExpr(E->getArg(4));
+ llvm::Value *TextureDescr = EmitScalarExpr(E->getArg(5));
+
+ Function *F = CGM.getIntrinsic(Intrinsic::amdgcn_image_bvh_intersect_ray,
+ {NodePtr->getType(), RayDir->getType()});
+ return Builder.CreateCall(F, {NodePtr, RayExtent, RayOrigin, RayDir,
+ RayInverseDir, TextureDescr});
+ }
+
// amdgcn workitem
case AMDGPU::BI__builtin_amdgcn_workitem_id_x:
return emitRangedBuiltin(*this, Intrinsic::amdgcn_workitem_id_x, 0, 1024);
@@ -15970,6 +16811,34 @@
case NVPTX::BI__bmma_m8n8k128_ld_c:
return MMA_LDST(2, m8n8k128_load_c_s32);
+ // Double MMA loads
+ case NVPTX::BI__dmma_m8n8k4_ld_a:
+ return MMA_LDST(1, m8n8k4_load_a_f64);
+ case NVPTX::BI__dmma_m8n8k4_ld_b:
+ return MMA_LDST(1, m8n8k4_load_b_f64);
+ case NVPTX::BI__dmma_m8n8k4_ld_c:
+ return MMA_LDST(2, m8n8k4_load_c_f64);
+
+ // Alternate float MMA loads
+ case NVPTX::BI__mma_bf16_m16n16k16_ld_a:
+ return MMA_LDST(4, m16n16k16_load_a_bf16);
+ case NVPTX::BI__mma_bf16_m16n16k16_ld_b:
+ return MMA_LDST(4, m16n16k16_load_b_bf16);
+ case NVPTX::BI__mma_bf16_m8n32k16_ld_a:
+ return MMA_LDST(2, m8n32k16_load_a_bf16);
+ case NVPTX::BI__mma_bf16_m8n32k16_ld_b:
+ return MMA_LDST(8, m8n32k16_load_b_bf16);
+ case NVPTX::BI__mma_bf16_m32n8k16_ld_a:
+ return MMA_LDST(8, m32n8k16_load_a_bf16);
+ case NVPTX::BI__mma_bf16_m32n8k16_ld_b:
+ return MMA_LDST(2, m32n8k16_load_b_bf16);
+ case NVPTX::BI__mma_tf32_m16n16k8_ld_a:
+ return MMA_LDST(4, m16n16k8_load_a_tf32);
+ case NVPTX::BI__mma_tf32_m16n16k8_ld_b:
+ return MMA_LDST(2, m16n16k8_load_b_tf32);
+ case NVPTX::BI__mma_tf32_m16n16k8_ld_c:
+ return MMA_LDST(8, m16n16k8_load_c_f32);
+
// NOTE: We need to follow inconsitent naming scheme used by NVCC. Unlike
// PTX and LLVM IR where stores always use fragment D, NVCC builtins always
// use fragment C for both loads and stores.
@@ -16001,6 +16870,14 @@
case NVPTX::BI__bmma_m8n8k128_st_c_i32:
return MMA_LDST(2, m8n8k128_store_d_s32);
+ // Double MMA store
+ case NVPTX::BI__dmma_m8n8k4_st_c_f64:
+ return MMA_LDST(2, m8n8k4_store_d_f64);
+
+ // Alternate float MMA store
+ case NVPTX::BI__mma_m16n16k8_st_c_f32:
+ return MMA_LDST(8, m16n16k8_store_d_f32);
+
default:
llvm_unreachable("Unknown MMA builtin");
}
@@ -16014,10 +16891,14 @@
unsigned NumEltsB;
unsigned NumEltsC;
unsigned NumEltsD;
+
+ // Variants are ordered by layout-A/layout-B/satf, where 'row' has priority
+ // over 'col' for layout. The index of non-satf variants is expected to match
+ // the undocumented layout constants used by CUDA's mma.hpp.
std::array<unsigned, 8> Variants;
unsigned getMMAIntrinsic(int Layout, bool Satf) {
- unsigned Index = Layout * 2 + Satf;
+ unsigned Index = Layout + 4 * Satf;
if (Index >= Variants.size())
return 0;
return Variants[Index];
@@ -16028,95 +16909,121 @@
// Layout and Satf, 0 otherwise.
static NVPTXMmaInfo getNVPTXMmaInfo(unsigned BuiltinID) {
// clang-format off
-#define MMA_VARIANTS(geom, type) {{ \
+#define MMA_VARIANTS(geom, type) \
Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type, \
- Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type##_satfinite, \
Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type, \
- Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type##_satfinite, \
Intrinsic::nvvm_wmma_##geom##_mma_col_row_##type, \
+ Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type
+#define MMA_SATF_VARIANTS(geom, type) \
+ MMA_VARIANTS(geom, type), \
+ Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type##_satfinite, \
+ Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type##_satfinite, \
Intrinsic::nvvm_wmma_##geom##_mma_col_row_##type##_satfinite, \
- Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type, \
- Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type##_satfinite \
- }}
+ Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type##_satfinite
// Sub-integer MMA only supports row.col layout.
-#define MMA_VARIANTS_I4(geom, type) {{ \
- 0, \
+#define MMA_VARIANTS_I4(geom, type) \
0, \
Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type, \
+ 0, \
+ 0, \
+ 0, \
Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type##_satfinite, \
0, \
- 0, \
- 0, \
- 0 \
- }}
+ 0
// b1 MMA does not support .satfinite.
-#define MMA_VARIANTS_B1(geom, type) {{ \
+#define MMA_VARIANTS_B1_XOR(geom, type) \
0, \
- 0, \
- Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type, \
+ Intrinsic::nvvm_wmma_##geom##_mma_xor_popc_row_col_##type, \
0, \
0, \
0, \
0, \
- 0 \
- }}
- // clang-format on
- switch (BuiltinID) {
- // FP MMA
- // Note that 'type' argument of MMA_VARIANT uses D_C notation, while
- // NumEltsN of return value are ordered as A,B,C,D.
- case NVPTX::BI__hmma_m16n16k16_mma_f16f16:
- return {8, 8, 4, 4, MMA_VARIANTS(m16n16k16, f16_f16)};
- case NVPTX::BI__hmma_m16n16k16_mma_f32f16:
- return {8, 8, 4, 8, MMA_VARIANTS(m16n16k16, f32_f16)};
- case NVPTX::BI__hmma_m16n16k16_mma_f16f32:
- return {8, 8, 8, 4, MMA_VARIANTS(m16n16k16, f16_f32)};
- case NVPTX::BI__hmma_m16n16k16_mma_f32f32:
- return {8, 8, 8, 8, MMA_VARIANTS(m16n16k16, f32_f32)};
- case NVPTX::BI__hmma_m32n8k16_mma_f16f16:
- return {8, 8, 4, 4, MMA_VARIANTS(m32n8k16, f16_f16)};
- case NVPTX::BI__hmma_m32n8k16_mma_f32f16:
- return {8, 8, 4, 8, MMA_VARIANTS(m32n8k16, f32_f16)};
- case NVPTX::BI__hmma_m32n8k16_mma_f16f32:
- return {8, 8, 8, 4, MMA_VARIANTS(m32n8k16, f16_f32)};
- case NVPTX::BI__hmma_m32n8k16_mma_f32f32:
- return {8, 8, 8, 8, MMA_VARIANTS(m32n8k16, f32_f32)};
- case NVPTX::BI__hmma_m8n32k16_mma_f16f16:
- return {8, 8, 4, 4, MMA_VARIANTS(m8n32k16, f16_f16)};
- case NVPTX::BI__hmma_m8n32k16_mma_f32f16:
- return {8, 8, 4, 8, MMA_VARIANTS(m8n32k16, f32_f16)};
- case NVPTX::BI__hmma_m8n32k16_mma_f16f32:
- return {8, 8, 8, 4, MMA_VARIANTS(m8n32k16, f16_f32)};
- case NVPTX::BI__hmma_m8n32k16_mma_f32f32:
- return {8, 8, 8, 8, MMA_VARIANTS(m8n32k16, f32_f32)};
+ 0, \
+ 0
+#define MMA_VARIANTS_B1_AND(geom, type) \
+ 0, \
+ Intrinsic::nvvm_wmma_##geom##_mma_and_popc_row_col_##type, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ 0
+ // clang-format on
+ switch (BuiltinID) {
+ // FP MMA
+ // Note that 'type' argument of MMA_SATF_VARIANTS uses D_C notation, while
+ // NumEltsN of return value are ordered as A,B,C,D.
+ case NVPTX::BI__hmma_m16n16k16_mma_f16f16:
+ return {8, 8, 4, 4, {{MMA_SATF_VARIANTS(m16n16k16, f16_f16)}}};
+ case NVPTX::BI__hmma_m16n16k16_mma_f32f16:
+ return {8, 8, 4, 8, {{MMA_SATF_VARIANTS(m16n16k16, f32_f16)}}};
+ case NVPTX::BI__hmma_m16n16k16_mma_f16f32:
+ return {8, 8, 8, 4, {{MMA_SATF_VARIANTS(m16n16k16, f16_f32)}}};
+ case NVPTX::BI__hmma_m16n16k16_mma_f32f32:
+ return {8, 8, 8, 8, {{MMA_SATF_VARIANTS(m16n16k16, f32_f32)}}};
+ case NVPTX::BI__hmma_m32n8k16_mma_f16f16:
+ return {8, 8, 4, 4, {{MMA_SATF_VARIANTS(m32n8k16, f16_f16)}}};
+ case NVPTX::BI__hmma_m32n8k16_mma_f32f16:
+ return {8, 8, 4, 8, {{MMA_SATF_VARIANTS(m32n8k16, f32_f16)}}};
+ case NVPTX::BI__hmma_m32n8k16_mma_f16f32:
+ return {8, 8, 8, 4, {{MMA_SATF_VARIANTS(m32n8k16, f16_f32)}}};
+ case NVPTX::BI__hmma_m32n8k16_mma_f32f32:
+ return {8, 8, 8, 8, {{MMA_SATF_VARIANTS(m32n8k16, f32_f32)}}};
+ case NVPTX::BI__hmma_m8n32k16_mma_f16f16:
+ return {8, 8, 4, 4, {{MMA_SATF_VARIANTS(m8n32k16, f16_f16)}}};
+ case NVPTX::BI__hmma_m8n32k16_mma_f32f16:
+ return {8, 8, 4, 8, {{MMA_SATF_VARIANTS(m8n32k16, f32_f16)}}};
+ case NVPTX::BI__hmma_m8n32k16_mma_f16f32:
+ return {8, 8, 8, 4, {{MMA_SATF_VARIANTS(m8n32k16, f16_f32)}}};
+ case NVPTX::BI__hmma_m8n32k16_mma_f32f32:
+ return {8, 8, 8, 8, {{MMA_SATF_VARIANTS(m8n32k16, f32_f32)}}};
- // Integer MMA
- case NVPTX::BI__imma_m16n16k16_mma_s8:
- return {2, 2, 8, 8, MMA_VARIANTS(m16n16k16, s8)};
- case NVPTX::BI__imma_m16n16k16_mma_u8:
- return {2, 2, 8, 8, MMA_VARIANTS(m16n16k16, u8)};
- case NVPTX::BI__imma_m32n8k16_mma_s8:
- return {4, 1, 8, 8, MMA_VARIANTS(m32n8k16, s8)};
- case NVPTX::BI__imma_m32n8k16_mma_u8:
- return {4, 1, 8, 8, MMA_VARIANTS(m32n8k16, u8)};
- case NVPTX::BI__imma_m8n32k16_mma_s8:
- return {1, 4, 8, 8, MMA_VARIANTS(m8n32k16, s8)};
- case NVPTX::BI__imma_m8n32k16_mma_u8:
- return {1, 4, 8, 8, MMA_VARIANTS(m8n32k16, u8)};
+ // Integer MMA
+ case NVPTX::BI__imma_m16n16k16_mma_s8:
+ return {2, 2, 8, 8, {{MMA_SATF_VARIANTS(m16n16k16, s8)}}};
+ case NVPTX::BI__imma_m16n16k16_mma_u8:
+ return {2, 2, 8, 8, {{MMA_SATF_VARIANTS(m16n16k16, u8)}}};
+ case NVPTX::BI__imma_m32n8k16_mma_s8:
+ return {4, 1, 8, 8, {{MMA_SATF_VARIANTS(m32n8k16, s8)}}};
+ case NVPTX::BI__imma_m32n8k16_mma_u8:
+ return {4, 1, 8, 8, {{MMA_SATF_VARIANTS(m32n8k16, u8)}}};
+ case NVPTX::BI__imma_m8n32k16_mma_s8:
+ return {1, 4, 8, 8, {{MMA_SATF_VARIANTS(m8n32k16, s8)}}};
+ case NVPTX::BI__imma_m8n32k16_mma_u8:
+ return {1, 4, 8, 8, {{MMA_SATF_VARIANTS(m8n32k16, u8)}}};
- // Sub-integer MMA
- case NVPTX::BI__imma_m8n8k32_mma_s4:
- return {1, 1, 2, 2, MMA_VARIANTS_I4(m8n8k32, s4)};
- case NVPTX::BI__imma_m8n8k32_mma_u4:
- return {1, 1, 2, 2, MMA_VARIANTS_I4(m8n8k32, u4)};
- case NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1:
- return {1, 1, 2, 2, MMA_VARIANTS_B1(m8n8k128, b1)};
- default:
- llvm_unreachable("Unexpected builtin ID.");
- }
+ // Sub-integer MMA
+ case NVPTX::BI__imma_m8n8k32_mma_s4:
+ return {1, 1, 2, 2, {{MMA_VARIANTS_I4(m8n8k32, s4)}}};
+ case NVPTX::BI__imma_m8n8k32_mma_u4:
+ return {1, 1, 2, 2, {{MMA_VARIANTS_I4(m8n8k32, u4)}}};
+ case NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1:
+ return {1, 1, 2, 2, {{MMA_VARIANTS_B1_XOR(m8n8k128, b1)}}};
+ case NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1:
+ return {1, 1, 2, 2, {{MMA_VARIANTS_B1_AND(m8n8k128, b1)}}};
+
+ // Double MMA
+ case NVPTX::BI__dmma_m8n8k4_mma_f64:
+ return {1, 1, 2, 2, {{MMA_VARIANTS(m8n8k4, f64)}}};
+
+ // Alternate FP MMA
+ case NVPTX::BI__mma_bf16_m16n16k16_mma_f32:
+ return {4, 4, 8, 8, {{MMA_VARIANTS(m16n16k16, bf16)}}};
+ case NVPTX::BI__mma_bf16_m8n32k16_mma_f32:
+ return {2, 8, 8, 8, {{MMA_VARIANTS(m8n32k16, bf16)}}};
+ case NVPTX::BI__mma_bf16_m32n8k16_mma_f32:
+ return {8, 2, 8, 8, {{MMA_VARIANTS(m32n8k16, bf16)}}};
+ case NVPTX::BI__mma_tf32_m16n16k8_mma_f32:
+ return {4, 4, 8, 8, {{MMA_VARIANTS(m16n16k8, tf32)}}};
+ default:
+ llvm_unreachable("Unexpected builtin ID.");
+ }
#undef MMA_VARIANTS
+#undef MMA_SATF_VARIANTS
#undef MMA_VARIANTS_I4
-#undef MMA_VARIANTS_B1
+#undef MMA_VARIANTS_B1_AND
+#undef MMA_VARIANTS_B1_XOR
}
} // namespace
@@ -16412,7 +17319,20 @@
case NVPTX::BI__bmma_m8n8k128_ld_a_b1:
case NVPTX::BI__bmma_m8n8k128_ld_b_b1:
case NVPTX::BI__bmma_m8n8k128_ld_c:
- {
+ // Double MMA loads.
+ case NVPTX::BI__dmma_m8n8k4_ld_a:
+ case NVPTX::BI__dmma_m8n8k4_ld_b:
+ case NVPTX::BI__dmma_m8n8k4_ld_c:
+ // Alternate float MMA loads.
+ case NVPTX::BI__mma_bf16_m16n16k16_ld_a:
+ case NVPTX::BI__mma_bf16_m16n16k16_ld_b:
+ case NVPTX::BI__mma_bf16_m8n32k16_ld_a:
+ case NVPTX::BI__mma_bf16_m8n32k16_ld_b:
+ case NVPTX::BI__mma_bf16_m32n8k16_ld_a:
+ case NVPTX::BI__mma_bf16_m32n8k16_ld_b:
+ case NVPTX::BI__mma_tf32_m16n16k8_ld_a:
+ case NVPTX::BI__mma_tf32_m16n16k8_ld_b:
+ case NVPTX::BI__mma_tf32_m16n16k8_ld_c: {
Address Dst = EmitPointerWithAlignment(E->getArg(0));
Value *Src = EmitScalarExpr(E->getArg(1));
Value *Ldm = EmitScalarExpr(E->getArg(2));
@@ -16439,7 +17359,7 @@
Builder.CreateAlignedStore(
Builder.CreateBitCast(Builder.CreateExtractValue(Result, i),
Dst.getElementType()),
- Builder.CreateGEP(Dst.getPointer(),
+ Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(),
llvm::ConstantInt::get(IntTy, i)),
CharUnits::fromQuantity(4));
}
@@ -16457,7 +17377,9 @@
case NVPTX::BI__imma_m32n8k16_st_c_i32:
case NVPTX::BI__imma_m8n32k16_st_c_i32:
case NVPTX::BI__imma_m8n8k32_st_c_i32:
- case NVPTX::BI__bmma_m8n8k128_st_c_i32: {
+ case NVPTX::BI__bmma_m8n8k128_st_c_i32:
+ case NVPTX::BI__dmma_m8n8k4_st_c_f64:
+ case NVPTX::BI__mma_m16n16k8_st_c_f32: {
Value *Dst = EmitScalarExpr(E->getArg(0));
Address Src = EmitPointerWithAlignment(E->getArg(1));
Value *Ldm = EmitScalarExpr(E->getArg(2));
@@ -16476,7 +17398,9 @@
SmallVector<Value *, 10> Values = {Dst};
for (unsigned i = 0; i < II.NumResults; ++i) {
Value *V = Builder.CreateAlignedLoad(
- Builder.CreateGEP(Src.getPointer(), llvm::ConstantInt::get(IntTy, i)),
+ Src.getElementType(),
+ Builder.CreateGEP(Src.getElementType(), Src.getPointer(),
+ llvm::ConstantInt::get(IntTy, i)),
CharUnits::fromQuantity(4));
Values.push_back(Builder.CreateBitCast(V, ParamType));
}
@@ -16507,7 +17431,13 @@
case NVPTX::BI__imma_m8n32k16_mma_u8:
case NVPTX::BI__imma_m8n8k32_mma_s4:
case NVPTX::BI__imma_m8n8k32_mma_u4:
- case NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1: {
+ case NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1:
+ case NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1:
+ case NVPTX::BI__dmma_m8n8k4_mma_f64:
+ case NVPTX::BI__mma_bf16_m16n16k16_mma_f32:
+ case NVPTX::BI__mma_bf16_m8n32k16_mma_f32:
+ case NVPTX::BI__mma_bf16_m32n8k16_mma_f32:
+ case NVPTX::BI__mma_tf32_m16n16k8_mma_f32: {
Address Dst = EmitPointerWithAlignment(E->getArg(0));
Address SrcA = EmitPointerWithAlignment(E->getArg(1));
Address SrcB = EmitPointerWithAlignment(E->getArg(2));
@@ -16520,7 +17450,8 @@
if (Layout < 0 || Layout > 3)
return nullptr;
llvm::APSInt SatfArg;
- if (BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1)
+ if (BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1 ||
+ BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1)
SatfArg = 0; // .b1 does not have satf argument.
else if (Optional<llvm::APSInt> OptSatfArg =
E->getArg(5)->getIntegerConstantExpr(getContext()))
@@ -16539,7 +17470,8 @@
// Load A
for (unsigned i = 0; i < MI.NumEltsA; ++i) {
Value *V = Builder.CreateAlignedLoad(
- Builder.CreateGEP(SrcA.getPointer(),
+ SrcA.getElementType(),
+ Builder.CreateGEP(SrcA.getElementType(), SrcA.getPointer(),
llvm::ConstantInt::get(IntTy, i)),
CharUnits::fromQuantity(4));
Values.push_back(Builder.CreateBitCast(V, AType));
@@ -16548,7 +17480,8 @@
llvm::Type *BType = Intrinsic->getFunctionType()->getParamType(MI.NumEltsA);
for (unsigned i = 0; i < MI.NumEltsB; ++i) {
Value *V = Builder.CreateAlignedLoad(
- Builder.CreateGEP(SrcB.getPointer(),
+ SrcB.getElementType(),
+ Builder.CreateGEP(SrcB.getElementType(), SrcB.getPointer(),
llvm::ConstantInt::get(IntTy, i)),
CharUnits::fromQuantity(4));
Values.push_back(Builder.CreateBitCast(V, BType));
@@ -16558,7 +17491,8 @@
Intrinsic->getFunctionType()->getParamType(MI.NumEltsA + MI.NumEltsB);
for (unsigned i = 0; i < MI.NumEltsC; ++i) {
Value *V = Builder.CreateAlignedLoad(
- Builder.CreateGEP(SrcC.getPointer(),
+ SrcC.getElementType(),
+ Builder.CreateGEP(SrcC.getElementType(), SrcC.getPointer(),
llvm::ConstantInt::get(IntTy, i)),
CharUnits::fromQuantity(4));
Values.push_back(Builder.CreateBitCast(V, CType));
@@ -16568,7 +17502,8 @@
for (unsigned i = 0; i < MI.NumEltsD; ++i)
Builder.CreateAlignedStore(
Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType),
- Builder.CreateGEP(Dst.getPointer(), llvm::ConstantInt::get(IntTy, i)),
+ Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(),
+ llvm::ConstantInt::get(IntTy, i)),
CharUnits::fromQuantity(4));
return Result;
}
@@ -16652,7 +17587,7 @@
// can use an inbounds GEP to enable better optimization.
Value *Base = EmitCastToVoidPtr(Args.Src);
if (getLangOpts().isSignedOverflowDefined())
- Result = Builder.CreateGEP(Base, Difference, "aligned_result");
+ Result = Builder.CreateGEP(Int8Ty, Base, Difference, "aligned_result");
else
Result = EmitCheckedInBoundsGEP(Base, Difference,
/*SignedIndices=*/true,
@@ -16791,22 +17726,6 @@
CGM.getIntrinsic(Intrinsic::maximum, ConvertType(E->getType()));
return Builder.CreateCall(Callee, {LHS, RHS});
}
- case WebAssembly::BI__builtin_wasm_pmin_f32x4:
- case WebAssembly::BI__builtin_wasm_pmin_f64x2: {
- Value *LHS = EmitScalarExpr(E->getArg(0));
- Value *RHS = EmitScalarExpr(E->getArg(1));
- Function *Callee =
- CGM.getIntrinsic(Intrinsic::wasm_pmin, ConvertType(E->getType()));
- return Builder.CreateCall(Callee, {LHS, RHS});
- }
- case WebAssembly::BI__builtin_wasm_pmax_f32x4:
- case WebAssembly::BI__builtin_wasm_pmax_f64x2: {
- Value *LHS = EmitScalarExpr(E->getArg(0));
- Value *RHS = EmitScalarExpr(E->getArg(1));
- Function *Callee =
- CGM.getIntrinsic(Intrinsic::wasm_pmax, ConvertType(E->getType()));
- return Builder.CreateCall(Callee, {LHS, RHS});
- }
case WebAssembly::BI__builtin_wasm_ceil_f32x4:
case WebAssembly::BI__builtin_wasm_floor_f32x4:
case WebAssembly::BI__builtin_wasm_trunc_f32x4:
@@ -16840,69 +17759,12 @@
Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType()));
return Builder.CreateCall(Callee, Value);
}
- case WebAssembly::BI__builtin_wasm_swizzle_v8x16: {
+ case WebAssembly::BI__builtin_wasm_swizzle_i8x16: {
Value *Src = EmitScalarExpr(E->getArg(0));
Value *Indices = EmitScalarExpr(E->getArg(1));
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_swizzle);
return Builder.CreateCall(Callee, {Src, Indices});
}
- case WebAssembly::BI__builtin_wasm_extract_lane_s_i8x16:
- case WebAssembly::BI__builtin_wasm_extract_lane_u_i8x16:
- case WebAssembly::BI__builtin_wasm_extract_lane_s_i16x8:
- case WebAssembly::BI__builtin_wasm_extract_lane_u_i16x8:
- case WebAssembly::BI__builtin_wasm_extract_lane_i32x4:
- case WebAssembly::BI__builtin_wasm_extract_lane_i64x2:
- case WebAssembly::BI__builtin_wasm_extract_lane_f32x4:
- case WebAssembly::BI__builtin_wasm_extract_lane_f64x2: {
- llvm::APSInt LaneConst =
- *E->getArg(1)->getIntegerConstantExpr(getContext());
- Value *Vec = EmitScalarExpr(E->getArg(0));
- Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst);
- Value *Extract = Builder.CreateExtractElement(Vec, Lane);
- switch (BuiltinID) {
- case WebAssembly::BI__builtin_wasm_extract_lane_s_i8x16:
- case WebAssembly::BI__builtin_wasm_extract_lane_s_i16x8:
- return Builder.CreateSExt(Extract, ConvertType(E->getType()));
- case WebAssembly::BI__builtin_wasm_extract_lane_u_i8x16:
- case WebAssembly::BI__builtin_wasm_extract_lane_u_i16x8:
- return Builder.CreateZExt(Extract, ConvertType(E->getType()));
- case WebAssembly::BI__builtin_wasm_extract_lane_i32x4:
- case WebAssembly::BI__builtin_wasm_extract_lane_i64x2:
- case WebAssembly::BI__builtin_wasm_extract_lane_f32x4:
- case WebAssembly::BI__builtin_wasm_extract_lane_f64x2:
- return Extract;
- default:
- llvm_unreachable("unexpected builtin ID");
- }
- }
- case WebAssembly::BI__builtin_wasm_replace_lane_i8x16:
- case WebAssembly::BI__builtin_wasm_replace_lane_i16x8:
- case WebAssembly::BI__builtin_wasm_replace_lane_i32x4:
- case WebAssembly::BI__builtin_wasm_replace_lane_i64x2:
- case WebAssembly::BI__builtin_wasm_replace_lane_f32x4:
- case WebAssembly::BI__builtin_wasm_replace_lane_f64x2: {
- llvm::APSInt LaneConst =
- *E->getArg(1)->getIntegerConstantExpr(getContext());
- Value *Vec = EmitScalarExpr(E->getArg(0));
- Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst);
- Value *Val = EmitScalarExpr(E->getArg(2));
- switch (BuiltinID) {
- case WebAssembly::BI__builtin_wasm_replace_lane_i8x16:
- case WebAssembly::BI__builtin_wasm_replace_lane_i16x8: {
- llvm::Type *ElemType =
- cast<llvm::VectorType>(ConvertType(E->getType()))->getElementType();
- Value *Trunc = Builder.CreateTrunc(Val, ElemType);
- return Builder.CreateInsertElement(Vec, Trunc, Lane);
- }
- case WebAssembly::BI__builtin_wasm_replace_lane_i32x4:
- case WebAssembly::BI__builtin_wasm_replace_lane_i64x2:
- case WebAssembly::BI__builtin_wasm_replace_lane_f32x4:
- case WebAssembly::BI__builtin_wasm_replace_lane_f64x2:
- return Builder.CreateInsertElement(Vec, Val, Lane);
- default:
- llvm_unreachable("unexpected builtin ID");
- }
- }
case WebAssembly::BI__builtin_wasm_add_sat_s_i8x16:
case WebAssembly::BI__builtin_wasm_add_sat_u_i8x16:
case WebAssembly::BI__builtin_wasm_add_sat_s_i16x8:
@@ -16939,7 +17801,8 @@
}
case WebAssembly::BI__builtin_wasm_abs_i8x16:
case WebAssembly::BI__builtin_wasm_abs_i16x8:
- case WebAssembly::BI__builtin_wasm_abs_i32x4: {
+ case WebAssembly::BI__builtin_wasm_abs_i32x4:
+ case WebAssembly::BI__builtin_wasm_abs_i64x2: {
Value *Vec = EmitScalarExpr(E->getArg(0));
Value *Neg = Builder.CreateNeg(Vec, "neg");
Constant *Zero = llvm::Constant::getNullValue(Vec->getType());
@@ -17001,49 +17864,6 @@
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_q15mulr_sat_signed);
return Builder.CreateCall(Callee, {LHS, RHS});
}
- case WebAssembly::BI__builtin_wasm_extmul_low_i8x16_s_i16x8:
- case WebAssembly::BI__builtin_wasm_extmul_high_i8x16_s_i16x8:
- case WebAssembly::BI__builtin_wasm_extmul_low_i8x16_u_i16x8:
- case WebAssembly::BI__builtin_wasm_extmul_high_i8x16_u_i16x8:
- case WebAssembly::BI__builtin_wasm_extmul_low_i16x8_s_i32x4:
- case WebAssembly::BI__builtin_wasm_extmul_high_i16x8_s_i32x4:
- case WebAssembly::BI__builtin_wasm_extmul_low_i16x8_u_i32x4:
- case WebAssembly::BI__builtin_wasm_extmul_high_i16x8_u_i32x4:
- case WebAssembly::BI__builtin_wasm_extmul_low_i32x4_s_i64x2:
- case WebAssembly::BI__builtin_wasm_extmul_high_i32x4_s_i64x2:
- case WebAssembly::BI__builtin_wasm_extmul_low_i32x4_u_i64x2:
- case WebAssembly::BI__builtin_wasm_extmul_high_i32x4_u_i64x2: {
- Value *LHS = EmitScalarExpr(E->getArg(0));
- Value *RHS = EmitScalarExpr(E->getArg(1));
- unsigned IntNo;
- switch (BuiltinID) {
- case WebAssembly::BI__builtin_wasm_extmul_low_i8x16_s_i16x8:
- case WebAssembly::BI__builtin_wasm_extmul_low_i16x8_s_i32x4:
- case WebAssembly::BI__builtin_wasm_extmul_low_i32x4_s_i64x2:
- IntNo = Intrinsic::wasm_extmul_low_signed;
- break;
- case WebAssembly::BI__builtin_wasm_extmul_low_i8x16_u_i16x8:
- case WebAssembly::BI__builtin_wasm_extmul_low_i16x8_u_i32x4:
- case WebAssembly::BI__builtin_wasm_extmul_low_i32x4_u_i64x2:
- IntNo = Intrinsic::wasm_extmul_low_unsigned;
- break;
- case WebAssembly::BI__builtin_wasm_extmul_high_i8x16_s_i16x8:
- case WebAssembly::BI__builtin_wasm_extmul_high_i16x8_s_i32x4:
- case WebAssembly::BI__builtin_wasm_extmul_high_i32x4_s_i64x2:
- IntNo = Intrinsic::wasm_extmul_high_signed;
- break;
- case WebAssembly::BI__builtin_wasm_extmul_high_i8x16_u_i16x8:
- case WebAssembly::BI__builtin_wasm_extmul_high_i16x8_u_i32x4:
- case WebAssembly::BI__builtin_wasm_extmul_high_i32x4_u_i64x2:
- IntNo = Intrinsic::wasm_extmul_high_unsigned;
- break;
- default:
- llvm_unreachable("unexptected builtin ID");
- }
-
- Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType()));
- return Builder.CreateCall(Callee, {LHS, RHS});
- }
case WebAssembly::BI__builtin_wasm_extadd_pairwise_i8x16_s_i16x8:
case WebAssembly::BI__builtin_wasm_extadd_pairwise_i8x16_u_i16x8:
case WebAssembly::BI__builtin_wasm_extadd_pairwise_i16x8_s_i32x4:
@@ -17082,23 +17902,18 @@
}
case WebAssembly::BI__builtin_wasm_popcnt_i8x16: {
Value *Vec = EmitScalarExpr(E->getArg(0));
- Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_popcnt);
+ Function *Callee =
+ CGM.getIntrinsic(Intrinsic::ctpop, ConvertType(E->getType()));
return Builder.CreateCall(Callee, {Vec});
}
- case WebAssembly::BI__builtin_wasm_any_true_i8x16:
- case WebAssembly::BI__builtin_wasm_any_true_i16x8:
- case WebAssembly::BI__builtin_wasm_any_true_i32x4:
- case WebAssembly::BI__builtin_wasm_any_true_i64x2:
+ case WebAssembly::BI__builtin_wasm_any_true_v128:
case WebAssembly::BI__builtin_wasm_all_true_i8x16:
case WebAssembly::BI__builtin_wasm_all_true_i16x8:
case WebAssembly::BI__builtin_wasm_all_true_i32x4:
case WebAssembly::BI__builtin_wasm_all_true_i64x2: {
unsigned IntNo;
switch (BuiltinID) {
- case WebAssembly::BI__builtin_wasm_any_true_i8x16:
- case WebAssembly::BI__builtin_wasm_any_true_i16x8:
- case WebAssembly::BI__builtin_wasm_any_true_i32x4:
- case WebAssembly::BI__builtin_wasm_any_true_i64x2:
+ case WebAssembly::BI__builtin_wasm_any_true_v128:
IntNo = Intrinsic::wasm_anytrue;
break;
case WebAssembly::BI__builtin_wasm_all_true_i8x16:
@@ -17169,6 +17984,8 @@
case WebAssembly::BI__builtin_wasm_trunc_sat_zero_u_f64x2_i32x4:
IntNo = Intrinsic::fptoui_sat;
break;
+ default:
+ llvm_unreachable("unexpected builtin ID");
}
llvm::Type *SrcT = Vec->getType();
llvm::Type *TruncT =
@@ -17181,73 +17998,7 @@
Builder.getInt32(2), Builder.getInt32(3)});
return Builder.CreateShuffleVector(Trunc, Splat, ConcatMask);
}
- case WebAssembly::BI__builtin_wasm_demote_zero_f64x2_f32x4: {
- Value *Vec = EmitScalarExpr(E->getArg(0));
- Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_demote_zero);
- return Builder.CreateCall(Callee, Vec);
- }
- case WebAssembly::BI__builtin_wasm_promote_low_f32x4_f64x2: {
- Value *Vec = EmitScalarExpr(E->getArg(0));
- Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_promote_low);
- return Builder.CreateCall(Callee, Vec);
- }
- case WebAssembly::BI__builtin_wasm_load32_zero: {
- Value *Ptr = EmitScalarExpr(E->getArg(0));
- Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_load32_zero);
- return Builder.CreateCall(Callee, {Ptr});
- }
- case WebAssembly::BI__builtin_wasm_load64_zero: {
- Value *Ptr = EmitScalarExpr(E->getArg(0));
- Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_load64_zero);
- return Builder.CreateCall(Callee, {Ptr});
- }
- case WebAssembly::BI__builtin_wasm_load8_lane:
- case WebAssembly::BI__builtin_wasm_load16_lane:
- case WebAssembly::BI__builtin_wasm_load32_lane:
- case WebAssembly::BI__builtin_wasm_load64_lane:
- case WebAssembly::BI__builtin_wasm_store8_lane:
- case WebAssembly::BI__builtin_wasm_store16_lane:
- case WebAssembly::BI__builtin_wasm_store32_lane:
- case WebAssembly::BI__builtin_wasm_store64_lane: {
- Value *Ptr = EmitScalarExpr(E->getArg(0));
- Value *Vec = EmitScalarExpr(E->getArg(1));
- Optional<llvm::APSInt> LaneIdxConst =
- E->getArg(2)->getIntegerConstantExpr(getContext());
- assert(LaneIdxConst && "Constant arg isn't actually constant?");
- Value *LaneIdx = llvm::ConstantInt::get(getLLVMContext(), *LaneIdxConst);
- unsigned IntNo;
- switch (BuiltinID) {
- case WebAssembly::BI__builtin_wasm_load8_lane:
- IntNo = Intrinsic::wasm_load8_lane;
- break;
- case WebAssembly::BI__builtin_wasm_load16_lane:
- IntNo = Intrinsic::wasm_load16_lane;
- break;
- case WebAssembly::BI__builtin_wasm_load32_lane:
- IntNo = Intrinsic::wasm_load32_lane;
- break;
- case WebAssembly::BI__builtin_wasm_load64_lane:
- IntNo = Intrinsic::wasm_load64_lane;
- break;
- case WebAssembly::BI__builtin_wasm_store8_lane:
- IntNo = Intrinsic::wasm_store8_lane;
- break;
- case WebAssembly::BI__builtin_wasm_store16_lane:
- IntNo = Intrinsic::wasm_store16_lane;
- break;
- case WebAssembly::BI__builtin_wasm_store32_lane:
- IntNo = Intrinsic::wasm_store32_lane;
- break;
- case WebAssembly::BI__builtin_wasm_store64_lane:
- IntNo = Intrinsic::wasm_store64_lane;
- break;
- default:
- llvm_unreachable("unexpected builtin ID");
- }
- Function *Callee = CGM.getIntrinsic(IntNo);
- return Builder.CreateCall(Callee, {Ptr, Vec, LaneIdx});
- }
- case WebAssembly::BI__builtin_wasm_shuffle_v8x16: {
+ case WebAssembly::BI__builtin_wasm_shuffle_i8x16: {
Value *Ops[18];
size_t OpIdx = 0;
Ops[OpIdx++] = EmitScalarExpr(E->getArg(0));
@@ -17509,3 +18260,147 @@
return nullptr;
}
+
+Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
+ const CallExpr *E,
+ ReturnValueSlot ReturnValue) {
+ SmallVector<Value *, 4> Ops;
+ llvm::Type *ResultType = ConvertType(E->getType());
+
+ for (unsigned i = 0, e = E->getNumArgs(); i != e; i++)
+ Ops.push_back(EmitScalarExpr(E->getArg(i)));
+
+ Intrinsic::ID ID = Intrinsic::not_intrinsic;
+ unsigned NF = 1;
+
+ // Required for overloaded intrinsics.
+ llvm::SmallVector<llvm::Type *, 2> IntrinsicTypes;
+ switch (BuiltinID) {
+ default: llvm_unreachable("unexpected builtin ID");
+ case RISCV::BI__builtin_riscv_orc_b_32:
+ case RISCV::BI__builtin_riscv_orc_b_64:
+ case RISCV::BI__builtin_riscv_clmul:
+ case RISCV::BI__builtin_riscv_clmulh:
+ case RISCV::BI__builtin_riscv_clmulr:
+ case RISCV::BI__builtin_riscv_bcompress_32:
+ case RISCV::BI__builtin_riscv_bcompress_64:
+ case RISCV::BI__builtin_riscv_bdecompress_32:
+ case RISCV::BI__builtin_riscv_bdecompress_64:
+ case RISCV::BI__builtin_riscv_grev_32:
+ case RISCV::BI__builtin_riscv_grev_64:
+ case RISCV::BI__builtin_riscv_gorc_32:
+ case RISCV::BI__builtin_riscv_gorc_64:
+ case RISCV::BI__builtin_riscv_shfl_32:
+ case RISCV::BI__builtin_riscv_shfl_64:
+ case RISCV::BI__builtin_riscv_unshfl_32:
+ case RISCV::BI__builtin_riscv_unshfl_64:
+ case RISCV::BI__builtin_riscv_xperm_n:
+ case RISCV::BI__builtin_riscv_xperm_b:
+ case RISCV::BI__builtin_riscv_xperm_h:
+ case RISCV::BI__builtin_riscv_xperm_w:
+ case RISCV::BI__builtin_riscv_crc32_b:
+ case RISCV::BI__builtin_riscv_crc32_h:
+ case RISCV::BI__builtin_riscv_crc32_w:
+ case RISCV::BI__builtin_riscv_crc32_d:
+ case RISCV::BI__builtin_riscv_crc32c_b:
+ case RISCV::BI__builtin_riscv_crc32c_h:
+ case RISCV::BI__builtin_riscv_crc32c_w:
+ case RISCV::BI__builtin_riscv_crc32c_d: {
+ switch (BuiltinID) {
+ default: llvm_unreachable("unexpected builtin ID");
+ // Zbb
+ case RISCV::BI__builtin_riscv_orc_b_32:
+ case RISCV::BI__builtin_riscv_orc_b_64:
+ ID = Intrinsic::riscv_orc_b;
+ break;
+
+ // Zbc
+ case RISCV::BI__builtin_riscv_clmul:
+ ID = Intrinsic::riscv_clmul;
+ break;
+ case RISCV::BI__builtin_riscv_clmulh:
+ ID = Intrinsic::riscv_clmulh;
+ break;
+ case RISCV::BI__builtin_riscv_clmulr:
+ ID = Intrinsic::riscv_clmulr;
+ break;
+
+ // Zbe
+ case RISCV::BI__builtin_riscv_bcompress_32:
+ case RISCV::BI__builtin_riscv_bcompress_64:
+ ID = Intrinsic::riscv_bcompress;
+ break;
+ case RISCV::BI__builtin_riscv_bdecompress_32:
+ case RISCV::BI__builtin_riscv_bdecompress_64:
+ ID = Intrinsic::riscv_bdecompress;
+ break;
+
+ // Zbp
+ case RISCV::BI__builtin_riscv_grev_32:
+ case RISCV::BI__builtin_riscv_grev_64:
+ ID = Intrinsic::riscv_grev;
+ break;
+ case RISCV::BI__builtin_riscv_gorc_32:
+ case RISCV::BI__builtin_riscv_gorc_64:
+ ID = Intrinsic::riscv_gorc;
+ break;
+ case RISCV::BI__builtin_riscv_shfl_32:
+ case RISCV::BI__builtin_riscv_shfl_64:
+ ID = Intrinsic::riscv_shfl;
+ break;
+ case RISCV::BI__builtin_riscv_unshfl_32:
+ case RISCV::BI__builtin_riscv_unshfl_64:
+ ID = Intrinsic::riscv_unshfl;
+ break;
+ case RISCV::BI__builtin_riscv_xperm_n:
+ ID = Intrinsic::riscv_xperm_n;
+ break;
+ case RISCV::BI__builtin_riscv_xperm_b:
+ ID = Intrinsic::riscv_xperm_b;
+ break;
+ case RISCV::BI__builtin_riscv_xperm_h:
+ ID = Intrinsic::riscv_xperm_h;
+ break;
+ case RISCV::BI__builtin_riscv_xperm_w:
+ ID = Intrinsic::riscv_xperm_w;
+ break;
+
+ // Zbr
+ case RISCV::BI__builtin_riscv_crc32_b:
+ ID = Intrinsic::riscv_crc32_b;
+ break;
+ case RISCV::BI__builtin_riscv_crc32_h:
+ ID = Intrinsic::riscv_crc32_h;
+ break;
+ case RISCV::BI__builtin_riscv_crc32_w:
+ ID = Intrinsic::riscv_crc32_w;
+ break;
+ case RISCV::BI__builtin_riscv_crc32_d:
+ ID = Intrinsic::riscv_crc32_d;
+ break;
+ case RISCV::BI__builtin_riscv_crc32c_b:
+ ID = Intrinsic::riscv_crc32c_b;
+ break;
+ case RISCV::BI__builtin_riscv_crc32c_h:
+ ID = Intrinsic::riscv_crc32c_h;
+ break;
+ case RISCV::BI__builtin_riscv_crc32c_w:
+ ID = Intrinsic::riscv_crc32c_w;
+ break;
+ case RISCV::BI__builtin_riscv_crc32c_d:
+ ID = Intrinsic::riscv_crc32c_d;
+ break;
+ }
+
+ IntrinsicTypes = {ResultType};
+ break;
+ }
+ // Vector builtins are handled from here.
+#include "clang/Basic/riscv_vector_builtin_cg.inc"
+ }
+
+ assert(ID != Intrinsic::not_intrinsic);
+
+ llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
+ return Builder.CreateCall(F, Ops, "");
+}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp b/src/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp
index e03631a..88030fe 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGCUDANV.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CGCUDARuntime.h"
+#include "CGCXXABI.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/Decl.h"
@@ -42,12 +43,18 @@
llvm::LLVMContext &Context;
/// Convenience reference to the current module
llvm::Module &TheModule;
- /// Keeps track of kernel launch stubs emitted in this module
+ /// Keeps track of kernel launch stubs and handles emitted in this module
struct KernelInfo {
- llvm::Function *Kernel;
+ llvm::Function *Kernel; // stub function to help launch kernel
const Decl *D;
};
llvm::SmallVector<KernelInfo, 16> EmittedKernels;
+ // Map a device stub function to a symbol for identifying kernel in host code.
+ // For CUDA, the symbol for identifying the kernel is the same as the device
+ // stub function. For HIP, they are different.
+ llvm::DenseMap<llvm::Function *, llvm::GlobalValue *> KernelHandles;
+ // Map a kernel handle to the kernel stub.
+ llvm::DenseMap<llvm::GlobalValue *, llvm::Function *> KernelStubs;
struct VarInfo {
llvm::GlobalVariable *Var;
const VarDecl *D;
@@ -120,12 +127,8 @@
void emitDeviceStubBodyNew(CodeGenFunction &CGF, FunctionArgList &Args);
std::string getDeviceSideName(const NamedDecl *ND) override;
-public:
- CGNVCUDARuntime(CodeGenModule &CGM);
-
- void emitDeviceStub(CodeGenFunction &CGF, FunctionArgList &Args) override;
void registerDeviceVar(const VarDecl *VD, llvm::GlobalVariable &Var,
- bool Extern, bool Constant) override {
+ bool Extern, bool Constant) {
DeviceVars.push_back({&Var,
VD,
{DeviceVarFlags::Variable, Extern, Constant,
@@ -133,7 +136,7 @@
/*Normalized*/ false, 0}});
}
void registerDeviceSurf(const VarDecl *VD, llvm::GlobalVariable &Var,
- bool Extern, int Type) override {
+ bool Extern, int Type) {
DeviceVars.push_back({&Var,
VD,
{DeviceVarFlags::Surface, Extern, /*Constant*/ false,
@@ -141,7 +144,7 @@
/*Normalized*/ false, Type}});
}
void registerDeviceTex(const VarDecl *VD, llvm::GlobalVariable &Var,
- bool Extern, int Type, bool Normalized) override {
+ bool Extern, int Type, bool Normalized) {
DeviceVars.push_back({&Var,
VD,
{DeviceVarFlags::Texture, Extern, /*Constant*/ false,
@@ -149,9 +152,29 @@
}
/// Creates module constructor function
- llvm::Function *makeModuleCtorFunction() override;
+ llvm::Function *makeModuleCtorFunction();
/// Creates module destructor function
- llvm::Function *makeModuleDtorFunction() override;
+ llvm::Function *makeModuleDtorFunction();
+ /// Transform managed variables for device compilation.
+ void transformManagedVars();
+
+public:
+ CGNVCUDARuntime(CodeGenModule &CGM);
+
+ llvm::GlobalValue *getKernelHandle(llvm::Function *F, GlobalDecl GD) override;
+ llvm::Function *getKernelStub(llvm::GlobalValue *Handle) override {
+ auto Loc = KernelStubs.find(Handle);
+ assert(Loc != KernelStubs.end());
+ return Loc->second;
+ }
+ void emitDeviceStub(CodeGenFunction &CGF, FunctionArgList &Args) override;
+ void handleVarRegistration(const VarDecl *VD,
+ llvm::GlobalVariable &Var) override;
+ void
+ internalizeDeviceSideVar(const VarDecl *D,
+ llvm::GlobalValue::LinkageTypes &Linkage) override;
+
+ llvm::Function *finalizeModule() override;
};
}
@@ -168,12 +191,27 @@
return ((Twine("__cuda") + Twine(FuncName)).str());
}
+static std::unique_ptr<MangleContext> InitDeviceMC(CodeGenModule &CGM) {
+ // If the host and device have different C++ ABIs, mark it as the device
+ // mangle context so that the mangling needs to retrieve the additional
+ // device lambda mangling number instead of the regular host one.
+ if (CGM.getContext().getAuxTargetInfo() &&
+ CGM.getContext().getTargetInfo().getCXXABI().isMicrosoft() &&
+ CGM.getContext().getAuxTargetInfo()->getCXXABI().isItaniumFamily()) {
+ return std::unique_ptr<MangleContext>(
+ CGM.getContext().createDeviceMangleContext(
+ *CGM.getContext().getAuxTargetInfo()));
+ }
+
+ return std::unique_ptr<MangleContext>(CGM.getContext().createMangleContext(
+ CGM.getContext().getAuxTargetInfo()));
+}
+
CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
: CGCUDARuntime(CGM), Context(CGM.getLLVMContext()),
TheModule(CGM.getModule()),
RelocatableDeviceCode(CGM.getLangOpts().GPURelocatableDeviceCode),
- DeviceMC(CGM.getContext().createMangleContext(
- CGM.getContext().getAuxTargetInfo())) {
+ DeviceMC(InitDeviceMC(CGM)) {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
@@ -184,14 +222,6 @@
CharPtrTy = llvm::PointerType::getUnqual(Types.ConvertType(Ctx.CharTy));
VoidPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.VoidPtrTy));
VoidPtrPtrTy = VoidPtrTy->getPointerTo();
- if (CGM.getContext().getAuxTargetInfo()) {
- // If the host and device have different C++ ABIs, mark it as the device
- // mangle context so that the mangling needs to retrieve the additonal
- // device lambda mangling number instead of the regular host one.
- DeviceMC->setDeviceMangleContext(
- CGM.getContext().getTargetInfo().getCXXABI().isMicrosoft() &&
- CGM.getContext().getAuxTargetInfo()->getCXXABI().isItaniumFamily());
- }
}
llvm::FunctionCallee CGNVCUDARuntime::getSetupArgumentFn() const {
@@ -238,19 +268,39 @@
else
GD = GlobalDecl(ND);
std::string DeviceSideName;
- if (DeviceMC->shouldMangleDeclName(ND)) {
+ MangleContext *MC;
+ if (CGM.getLangOpts().CUDAIsDevice)
+ MC = &CGM.getCXXABI().getMangleContext();
+ else
+ MC = DeviceMC.get();
+ if (MC->shouldMangleDeclName(ND)) {
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
- DeviceMC->mangleName(GD, Out);
+ MC->mangleName(GD, Out);
DeviceSideName = std::string(Out.str());
} else
DeviceSideName = std::string(ND->getIdentifier()->getName());
+
+ // Make unique name for device side static file-scope variable for HIP.
+ if (CGM.getContext().shouldExternalizeStaticVar(ND) &&
+ CGM.getLangOpts().GPURelocatableDeviceCode &&
+ !CGM.getLangOpts().CUID.empty()) {
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ Out << DeviceSideName;
+ CGM.printPostfixForExternalizedStaticVar(Out);
+ DeviceSideName = std::string(Out.str());
+ }
return DeviceSideName;
}
void CGNVCUDARuntime::emitDeviceStub(CodeGenFunction &CGF,
FunctionArgList &Args) {
EmittedKernels.push_back({CGF.CurFn, CGF.CurFuncDecl});
+ if (auto *GV = dyn_cast<llvm::GlobalVariable>(KernelHandles[CGF.CurFn])) {
+ GV->setLinkage(CGF.CurFn->getLinkage());
+ GV->setInitializer(CGF.CurFn);
+ }
if (CudaFeatureEnabled(CGM.getTarget().getSDKVersion(),
CudaFeature::CUDA_USES_NEW_LAUNCH) ||
(CGF.getLangOpts().HIP && CGF.getLangOpts().HIPUseNewLaunchAPI))
@@ -276,7 +326,8 @@
llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer();
llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, VoidPtrTy);
CGF.Builder.CreateDefaultAlignedStore(
- VoidVarPtr, CGF.Builder.CreateConstGEP1_32(KernelArgs.getPointer(), i));
+ VoidVarPtr,
+ CGF.Builder.CreateConstGEP1_32(VoidPtrTy, KernelArgs.getPointer(), i));
}
llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end");
@@ -294,7 +345,7 @@
IdentifierInfo &cudaLaunchKernelII =
CGM.getContext().Idents.get(LaunchKernelName);
FunctionDecl *cudaLaunchKernelFD = nullptr;
- for (const auto &Result : DC->lookup(&cudaLaunchKernelII)) {
+ for (auto *Result : DC->lookup(&cudaLaunchKernelII)) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Result))
cudaLaunchKernelFD = FD;
}
@@ -329,7 +380,8 @@
ShmemSize.getPointer(), Stream.getPointer()});
// Emit the call to cudaLaunch
- llvm::Value *Kernel = CGF.Builder.CreatePointerCast(CGF.CurFn, VoidPtrTy);
+ llvm::Value *Kernel =
+ CGF.Builder.CreatePointerCast(KernelHandles[CGF.CurFn], VoidPtrTy);
CallArgList LaunchKernelArgs;
LaunchKernelArgs.add(RValue::get(Kernel),
cudaLaunchKernelFD->getParamDecl(0)->getType());
@@ -384,7 +436,8 @@
// Emit the call to cudaLaunch
llvm::FunctionCallee cudaLaunchFn = getLaunchFn();
- llvm::Value *Arg = CGF.Builder.CreatePointerCast(CGF.CurFn, CharPtrTy);
+ llvm::Value *Arg =
+ CGF.Builder.CreatePointerCast(KernelHandles[CGF.CurFn], CharPtrTy);
CGF.EmitRuntimeCallOrInvoke(cudaLaunchFn, Arg);
CGF.EmitBranch(EndBlock);
@@ -478,7 +531,7 @@
llvm::Constant *NullPtr = llvm::ConstantPointerNull::get(VoidPtrTy);
llvm::Value *Args[] = {
&GpuBinaryHandlePtr,
- Builder.CreateBitCast(I.Kernel, VoidPtrTy),
+ Builder.CreateBitCast(KernelHandles[I.Kernel], VoidPtrTy),
KernelName,
KernelName,
llvm::ConstantInt::get(IntTy, -1),
@@ -528,6 +581,9 @@
addUnderscoredPrefixToName("RegisterTexture"));
for (auto &&Info : DeviceVars) {
llvm::GlobalVariable *Var = Info.Var;
+ assert((!Var->isDeclaration() || Info.Flags.isManaged()) &&
+ "External variables should not show up here, except HIP managed "
+ "variables");
llvm::Constant *VarName = makeConstantString(getDeviceSideName(Info.D));
switch (Info.Flags.getKind()) {
case DeviceVarFlags::Variable: {
@@ -537,9 +593,16 @@
auto ManagedVar = new llvm::GlobalVariable(
CGM.getModule(), Var->getType(),
/*isConstant=*/false, Var->getLinkage(),
- /*Init=*/llvm::ConstantPointerNull::get(Var->getType()),
- Twine(Var->getName() + ".managed"), /*InsertBefore=*/nullptr,
+ /*Init=*/Var->isDeclaration()
+ ? nullptr
+ : llvm::ConstantPointerNull::get(Var->getType()),
+ /*Name=*/"", /*InsertBefore=*/nullptr,
llvm::GlobalVariable::NotThreadLocal);
+ ManagedVar->setDSOLocal(Var->isDSOLocal());
+ ManagedVar->setVisibility(Var->getVisibility());
+ ManagedVar->setExternallyInitialized(true);
+ ManagedVar->takeName(Var);
+ Var->setName(Twine(ManagedVar->getName() + ".managed"));
replaceManagedVar(Var, ManagedVar);
llvm::Value *Args[] = {
&GpuBinaryHandlePtr,
@@ -548,7 +611,8 @@
VarName,
llvm::ConstantInt::get(VarSizeTy, VarSize),
llvm::ConstantInt::get(IntTy, Var->getAlignment())};
- Builder.CreateCall(RegisterManagedVar, Args);
+ if (!Var->isDeclaration())
+ Builder.CreateCall(RegisterManagedVar, Args);
} else {
llvm::Value *Args[] = {
&GpuBinaryHandlePtr,
@@ -923,3 +987,168 @@
CGCUDARuntime *CodeGen::CreateNVCUDARuntime(CodeGenModule &CGM) {
return new CGNVCUDARuntime(CGM);
}
+
+void CGNVCUDARuntime::internalizeDeviceSideVar(
+ const VarDecl *D, llvm::GlobalValue::LinkageTypes &Linkage) {
+ // For -fno-gpu-rdc, host-side shadows of external declarations of device-side
+ // global variables become internal definitions. These have to be internal in
+ // order to prevent name conflicts with global host variables with the same
+ // name in a different TUs.
+ //
+ // For -fgpu-rdc, the shadow variables should not be internalized because
+ // they may be accessed by different TU.
+ if (CGM.getLangOpts().GPURelocatableDeviceCode)
+ return;
+
+ // __shared__ variables are odd. Shadows do get created, but
+ // they are not registered with the CUDA runtime, so they
+ // can't really be used to access their device-side
+ // counterparts. It's not clear yet whether it's nvcc's bug or
+ // a feature, but we've got to do the same for compatibility.
+ if (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>() ||
+ D->hasAttr<CUDASharedAttr>() ||
+ D->getType()->isCUDADeviceBuiltinSurfaceType() ||
+ D->getType()->isCUDADeviceBuiltinTextureType()) {
+ Linkage = llvm::GlobalValue::InternalLinkage;
+ }
+}
+
+void CGNVCUDARuntime::handleVarRegistration(const VarDecl *D,
+ llvm::GlobalVariable &GV) {
+ if (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>()) {
+ // Shadow variables and their properties must be registered with CUDA
+ // runtime. Skip Extern global variables, which will be registered in
+ // the TU where they are defined.
+ //
+ // Don't register a C++17 inline variable. The local symbol can be
+ // discarded and referencing a discarded local symbol from outside the
+ // comdat (__cuda_register_globals) is disallowed by the ELF spec.
+ //
+ // HIP managed variables need to be always recorded in device and host
+ // compilations for transformation.
+ //
+ // HIP managed variables and variables in CUDADeviceVarODRUsedByHost are
+ // added to llvm.compiler-used, therefore they are safe to be registered.
+ if ((!D->hasExternalStorage() && !D->isInline()) ||
+ CGM.getContext().CUDADeviceVarODRUsedByHost.contains(D) ||
+ D->hasAttr<HIPManagedAttr>()) {
+ registerDeviceVar(D, GV, !D->hasDefinition(),
+ D->hasAttr<CUDAConstantAttr>());
+ }
+ } else if (D->getType()->isCUDADeviceBuiltinSurfaceType() ||
+ D->getType()->isCUDADeviceBuiltinTextureType()) {
+ // Builtin surfaces and textures and their template arguments are
+ // also registered with CUDA runtime.
+ const auto *TD = cast<ClassTemplateSpecializationDecl>(
+ D->getType()->castAs<RecordType>()->getDecl());
+ const TemplateArgumentList &Args = TD->getTemplateArgs();
+ if (TD->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>()) {
+ assert(Args.size() == 2 &&
+ "Unexpected number of template arguments of CUDA device "
+ "builtin surface type.");
+ auto SurfType = Args[1].getAsIntegral();
+ if (!D->hasExternalStorage())
+ registerDeviceSurf(D, GV, !D->hasDefinition(), SurfType.getSExtValue());
+ } else {
+ assert(Args.size() == 3 &&
+ "Unexpected number of template arguments of CUDA device "
+ "builtin texture type.");
+ auto TexType = Args[1].getAsIntegral();
+ auto Normalized = Args[2].getAsIntegral();
+ if (!D->hasExternalStorage())
+ registerDeviceTex(D, GV, !D->hasDefinition(), TexType.getSExtValue(),
+ Normalized.getZExtValue());
+ }
+ }
+}
+
+// Transform managed variables to pointers to managed variables in device code.
+// Each use of the original managed variable is replaced by a load from the
+// transformed managed variable. The transformed managed variable contains
+// the address of managed memory which will be allocated by the runtime.
+void CGNVCUDARuntime::transformManagedVars() {
+ for (auto &&Info : DeviceVars) {
+ llvm::GlobalVariable *Var = Info.Var;
+ if (Info.Flags.getKind() == DeviceVarFlags::Variable &&
+ Info.Flags.isManaged()) {
+ auto ManagedVar = new llvm::GlobalVariable(
+ CGM.getModule(), Var->getType(),
+ /*isConstant=*/false, Var->getLinkage(),
+ /*Init=*/Var->isDeclaration()
+ ? nullptr
+ : llvm::ConstantPointerNull::get(Var->getType()),
+ /*Name=*/"", /*InsertBefore=*/nullptr,
+ llvm::GlobalVariable::NotThreadLocal,
+ CGM.getContext().getTargetAddressSpace(LangAS::cuda_device));
+ ManagedVar->setDSOLocal(Var->isDSOLocal());
+ ManagedVar->setVisibility(Var->getVisibility());
+ ManagedVar->setExternallyInitialized(true);
+ replaceManagedVar(Var, ManagedVar);
+ ManagedVar->takeName(Var);
+ Var->setName(Twine(ManagedVar->getName()) + ".managed");
+ // Keep managed variables even if they are not used in device code since
+ // they need to be allocated by the runtime.
+ if (!Var->isDeclaration()) {
+ assert(!ManagedVar->isDeclaration());
+ CGM.addCompilerUsedGlobal(Var);
+ CGM.addCompilerUsedGlobal(ManagedVar);
+ }
+ }
+ }
+}
+
+// Returns module constructor to be added.
+llvm::Function *CGNVCUDARuntime::finalizeModule() {
+ if (CGM.getLangOpts().CUDAIsDevice) {
+ transformManagedVars();
+
+ // Mark ODR-used device variables as compiler used to prevent it from being
+ // eliminated by optimization. This is necessary for device variables
+ // ODR-used by host functions. Sema correctly marks them as ODR-used no
+ // matter whether they are ODR-used by device or host functions.
+ //
+ // We do not need to do this if the variable has used attribute since it
+ // has already been added.
+ //
+ // Static device variables have been externalized at this point, therefore
+ // variables with LLVM private or internal linkage need not be added.
+ for (auto &&Info : DeviceVars) {
+ auto Kind = Info.Flags.getKind();
+ if (!Info.Var->isDeclaration() &&
+ !llvm::GlobalValue::isLocalLinkage(Info.Var->getLinkage()) &&
+ (Kind == DeviceVarFlags::Variable ||
+ Kind == DeviceVarFlags::Surface ||
+ Kind == DeviceVarFlags::Texture) &&
+ Info.D->isUsed() && !Info.D->hasAttr<UsedAttr>()) {
+ CGM.addCompilerUsedGlobal(Info.Var);
+ }
+ }
+ return nullptr;
+ }
+ return makeModuleCtorFunction();
+}
+
+llvm::GlobalValue *CGNVCUDARuntime::getKernelHandle(llvm::Function *F,
+ GlobalDecl GD) {
+ auto Loc = KernelHandles.find(F);
+ if (Loc != KernelHandles.end())
+ return Loc->second;
+
+ if (!CGM.getLangOpts().HIP) {
+ KernelHandles[F] = F;
+ KernelStubs[F] = F;
+ return F;
+ }
+
+ auto *Var = new llvm::GlobalVariable(
+ TheModule, F->getType(), /*isConstant=*/true, F->getLinkage(),
+ /*Initializer=*/nullptr,
+ CGM.getMangledName(
+ GD.getWithKernelReferenceKind(KernelReferenceKind::Kernel)));
+ Var->setAlignment(CGM.getPointerAlign().getAsAlign());
+ Var->setDSOLocal(F->isDSOLocal());
+ Var->setVisibility(F->getVisibility());
+ KernelHandles[F] = Var;
+ KernelStubs[Var] = F;
+ return Var;
+}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGCUDARuntime.h b/src/llvm-project/clang/lib/CodeGen/CGCUDARuntime.h
index ba3404e..1c119dc 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGCUDARuntime.h
+++ b/src/llvm-project/clang/lib/CodeGen/CGCUDARuntime.h
@@ -15,7 +15,9 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_CGCUDARUNTIME_H
#define LLVM_CLANG_LIB_CODEGEN_CGCUDARUNTIME_H
+#include "clang/AST/GlobalDecl.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/GlobalValue.h"
namespace llvm {
class Function;
@@ -80,24 +82,30 @@
/// Emits a kernel launch stub.
virtual void emitDeviceStub(CodeGenFunction &CGF, FunctionArgList &Args) = 0;
- virtual void registerDeviceVar(const VarDecl *VD, llvm::GlobalVariable &Var,
- bool Extern, bool Constant) = 0;
- virtual void registerDeviceSurf(const VarDecl *VD, llvm::GlobalVariable &Var,
- bool Extern, int Type) = 0;
- virtual void registerDeviceTex(const VarDecl *VD, llvm::GlobalVariable &Var,
- bool Extern, int Type, bool Normalized) = 0;
- /// Constructs and returns a module initialization function or nullptr if it's
- /// not needed. Must be called after all kernels have been emitted.
- virtual llvm::Function *makeModuleCtorFunction() = 0;
+ /// Check whether a variable is a device variable and register it if true.
+ virtual void handleVarRegistration(const VarDecl *VD,
+ llvm::GlobalVariable &Var) = 0;
- /// Returns a module cleanup function or nullptr if it's not needed.
- /// Must be called after ModuleCtorFunction
- virtual llvm::Function *makeModuleDtorFunction() = 0;
+ /// Finalize generated LLVM module. Returns a module constructor function
+ /// to be added or a null pointer.
+ virtual llvm::Function *finalizeModule() = 0;
/// Returns function or variable name on device side even if the current
/// compilation is for host.
virtual std::string getDeviceSideName(const NamedDecl *ND) = 0;
+
+ /// Get kernel handle by stub function.
+ virtual llvm::GlobalValue *getKernelHandle(llvm::Function *Stub,
+ GlobalDecl GD) = 0;
+
+ /// Get kernel stub by kernel handle.
+ virtual llvm::Function *getKernelStub(llvm::GlobalValue *Handle) = 0;
+
+ /// Adjust linkage of shadow variables in host compilation.
+ virtual void
+ internalizeDeviceSideVar(const VarDecl *D,
+ llvm::GlobalValue::LinkageTypes &Linkage) = 0;
};
/// Creates an instance of a CUDA runtime class.
diff --git a/src/llvm-project/clang/lib/CodeGen/CGCXX.cpp b/src/llvm-project/clang/lib/CodeGen/CGCXX.cpp
index a4bd2c6d..86f5481 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGCXX.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGCXX.cpp
@@ -252,8 +252,8 @@
"No kext in Microsoft ABI");
CodeGenModule &CGM = CGF.CGM;
llvm::Value *VTable = CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());
- Ty = Ty->getPointerTo()->getPointerTo();
- VTable = CGF.Builder.CreateBitCast(VTable, Ty);
+ Ty = Ty->getPointerTo();
+ VTable = CGF.Builder.CreateBitCast(VTable, Ty->getPointerTo());
assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
const VTableLayout &VTLayout = CGM.getItaniumVTableContext().getVTableLayout(RD);
@@ -262,9 +262,9 @@
VTableIndex += VTLayout.getVTableOffset(AddressPoint.VTableIndex) +
AddressPoint.AddressPointIndex;
llvm::Value *VFuncPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
+ CGF.Builder.CreateConstInBoundsGEP1_64(Ty, VTable, VTableIndex, "vfnkxt");
llvm::Value *VFunc = CGF.Builder.CreateAlignedLoad(
- VFuncPtr, llvm::Align(CGF.PointerAlignInBytes));
+ Ty, VFuncPtr, llvm::Align(CGF.PointerAlignInBytes));
CGCallee Callee(GD, VFunc);
return Callee;
}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGCall.cpp b/src/llvm-project/clang/lib/CodeGen/CGCall.cpp
index bc7582c..47a4ed3 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGCall.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGCall.cpp
@@ -66,6 +66,7 @@
case CC_PreserveMost: return llvm::CallingConv::PreserveMost;
case CC_PreserveAll: return llvm::CallingConv::PreserveAll;
case CC_Swift: return llvm::CallingConv::Swift;
+ case CC_SwiftAsync: return llvm::CallingConv::SwiftTail;
}
}
@@ -773,7 +774,7 @@
// Force target independent argument handling for the host visible
// kernel functions.
computeSPIRKernelABIInfo(CGM, *FI);
- } else if (info.getCC() == CC_Swift) {
+ } else if (info.getCC() == CC_Swift || info.getCC() == CC_SwiftAsync) {
swiftcall::computeABIInfo(CGM, *FI);
} else {
getABIInfo().computeInfo(*FI);
@@ -1012,8 +1013,8 @@
BaseAddr.getAlignment().alignmentOfArrayElement(EltSize);
for (int i = 0, n = CAE->NumElts; i < n; i++) {
- llvm::Value *EltAddr =
- CGF.Builder.CreateConstGEP2_32(nullptr, BaseAddr.getPointer(), 0, i);
+ llvm::Value *EltAddr = CGF.Builder.CreateConstGEP2_32(
+ BaseAddr.getElementType(), BaseAddr.getPointer(), 0, i);
Fn(Address(EltAddr, EltAlign));
}
}
@@ -1732,6 +1733,18 @@
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
}
+bool CodeGenModule::MayDropFunctionReturn(const ASTContext &Context,
+ QualType ReturnType) {
+ // We can't just discard the return value for a record type with a
+ // complex destructor or a non-trivially copyable type.
+ if (const RecordType *RT =
+ ReturnType.getCanonicalType()->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ return ClassDecl->hasTrivialDestructor();
+ }
+ return ReturnType.isTriviallyCopyableType(Context);
+}
+
void CodeGenModule::getDefaultFunctionAttributes(StringRef Name,
bool HasOptnone,
bool AttrOnCallSite,
@@ -1753,8 +1766,7 @@
if (AttrOnCallSite) {
// Attributes that should go on the call site only.
- if (!CodeGenOpts.SimplifyLibCalls ||
- CodeGenOpts.isNoBuiltinFunc(Name.data()))
+ if (!CodeGenOpts.SimplifyLibCalls || LangOpts.isNoBuiltinFunc(Name))
FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
if (!CodeGenOpts.TrapFuncName.empty())
FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName);
@@ -1773,8 +1785,8 @@
}
FuncAttrs.addAttribute("frame-pointer", FpKind);
- FuncAttrs.addAttribute("less-precise-fpmad",
- llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
+ if (CodeGenOpts.LessPreciseFPMAD)
+ FuncAttrs.addAttribute("less-precise-fpmad", "true");
if (CodeGenOpts.NullPointerIsValid)
FuncAttrs.addAttribute(llvm::Attribute::NullPointerIsValid);
@@ -1788,9 +1800,8 @@
CodeGenOpts.FP32DenormalMode.str());
}
- FuncAttrs.addAttribute("no-trapping-math",
- llvm::toStringRef(LangOpts.getFPExceptionMode() ==
- LangOptions::FPE_Ignore));
+ if (LangOpts.getFPExceptionMode() == LangOptions::FPE_Ignore)
+ FuncAttrs.addAttribute("no-trapping-math", "true");
// Strict (compliant) code is the default, so only add this attribute to
// indicate that we are trying to workaround a problem case.
@@ -1799,18 +1810,18 @@
// TODO: Are these all needed?
// unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags.
- FuncAttrs.addAttribute("no-infs-fp-math",
- llvm::toStringRef(LangOpts.NoHonorInfs));
- FuncAttrs.addAttribute("no-nans-fp-math",
- llvm::toStringRef(LangOpts.NoHonorNaNs));
- FuncAttrs.addAttribute("unsafe-fp-math",
- llvm::toStringRef(LangOpts.UnsafeFPMath));
- FuncAttrs.addAttribute("use-soft-float",
- llvm::toStringRef(CodeGenOpts.SoftFloat));
+ if (LangOpts.NoHonorInfs)
+ FuncAttrs.addAttribute("no-infs-fp-math", "true");
+ if (LangOpts.NoHonorNaNs)
+ FuncAttrs.addAttribute("no-nans-fp-math", "true");
+ if (LangOpts.UnsafeFPMath)
+ FuncAttrs.addAttribute("unsafe-fp-math", "true");
+ if (CodeGenOpts.SoftFloat)
+ FuncAttrs.addAttribute("use-soft-float", "true");
FuncAttrs.addAttribute("stack-protector-buffer-size",
llvm::utostr(CodeGenOpts.SSPBufferSize));
- FuncAttrs.addAttribute("no-signed-zeros-fp-math",
- llvm::toStringRef(LangOpts.NoSignedZero));
+ if (LangOpts.NoSignedZero)
+ FuncAttrs.addAttribute("no-signed-zeros-fp-math", "true");
// TODO: Reciprocal estimate codegen options should apply to instructions?
const std::vector<std::string> &Recips = CodeGenOpts.Reciprocals;
@@ -1906,6 +1917,55 @@
llvm::for_each(NBA->builtinNames(), AddNoBuiltinAttr);
}
+static bool DetermineNoUndef(QualType QTy, CodeGenTypes &Types,
+ const llvm::DataLayout &DL, const ABIArgInfo &AI,
+ bool CheckCoerce = true) {
+ llvm::Type *Ty = Types.ConvertTypeForMem(QTy);
+ if (AI.getKind() == ABIArgInfo::Indirect)
+ return true;
+ if (AI.getKind() == ABIArgInfo::Extend)
+ return true;
+ if (!DL.typeSizeEqualsStoreSize(Ty))
+ // TODO: This will result in a modest amount of values not marked noundef
+ // when they could be. We care about values that *invisibly* contain undef
+ // bits from the perspective of LLVM IR.
+ return false;
+ if (CheckCoerce && AI.canHaveCoerceToType()) {
+ llvm::Type *CoerceTy = AI.getCoerceToType();
+ if (llvm::TypeSize::isKnownGT(DL.getTypeSizeInBits(CoerceTy),
+ DL.getTypeSizeInBits(Ty)))
+ // If we're coercing to a type with a greater size than the canonical one,
+ // we're introducing new undef bits.
+ // Coercing to a type of smaller or equal size is ok, as we know that
+ // there's no internal padding (typeSizeEqualsStoreSize).
+ return false;
+ }
+ if (QTy->isExtIntType())
+ return true;
+ if (QTy->isReferenceType())
+ return true;
+ if (QTy->isNullPtrType())
+ return false;
+ if (QTy->isMemberPointerType())
+ // TODO: Some member pointers are `noundef`, but it depends on the ABI. For
+ // now, never mark them.
+ return false;
+ if (QTy->isScalarType()) {
+ if (const ComplexType *Complex = dyn_cast<ComplexType>(QTy))
+ return DetermineNoUndef(Complex->getElementType(), Types, DL, AI, false);
+ return true;
+ }
+ if (const VectorType *Vector = dyn_cast<VectorType>(QTy))
+ return DetermineNoUndef(Vector->getElementType(), Types, DL, AI, false);
+ if (const MatrixType *Matrix = dyn_cast<MatrixType>(QTy))
+ return DetermineNoUndef(Matrix->getElementType(), Types, DL, AI, false);
+ if (const ArrayType *Array = dyn_cast<ArrayType>(QTy))
+ return DetermineNoUndef(Array->getElementType(), Types, DL, AI, false);
+
+ // TODO: Some structs may be `noundef`, in specific situations.
+ return false;
+}
+
/// Construct the IR attribute list of a function or call.
///
/// When adding an attribute, please consider where it should be handled:
@@ -1923,9 +1983,12 @@
/// attributes that restrict how the frontend generates code must be
/// added here rather than getDefaultFunctionAttributes.
///
-void CodeGenModule::ConstructAttributeList(
- StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo,
- llvm::AttributeList &AttrList, unsigned &CallingConv, bool AttrOnCallSite) {
+void CodeGenModule::ConstructAttributeList(StringRef Name,
+ const CGFunctionInfo &FI,
+ CGCalleeInfo CalleeInfo,
+ llvm::AttributeList &AttrList,
+ unsigned &CallingConv,
+ bool AttrOnCallSite, bool IsThunk) {
llvm::AttrBuilder FuncAttrs;
llvm::AttrBuilder RetAttrs;
@@ -1989,6 +2052,24 @@
// allows it to work on indirect virtual function calls.
if (AttrOnCallSite && TargetDecl->hasAttr<NoMergeAttr>())
FuncAttrs.addAttribute(llvm::Attribute::NoMerge);
+
+ // Add known guaranteed alignment for allocation functions.
+ if (unsigned BuiltinID = Fn->getBuiltinID()) {
+ switch (BuiltinID) {
+ case Builtin::BIaligned_alloc:
+ case Builtin::BIcalloc:
+ case Builtin::BImalloc:
+ case Builtin::BImemalign:
+ case Builtin::BIrealloc:
+ case Builtin::BIstrdup:
+ case Builtin::BIstrndup:
+ RetAttrs.addAlignmentAttr(Context.getTargetInfo().getNewAlign() /
+ Context.getTargetInfo().getCharWidth());
+ break;
+ default:
+ break;
+ }
+ }
}
// 'const', 'pure' and 'noalias' attributed functions are also nounwind.
@@ -2090,6 +2171,17 @@
}
}
+ // Add "sample-profile-suffix-elision-policy" attribute for internal linkage
+ // functions with -funique-internal-linkage-names.
+ if (TargetDecl && CodeGenOpts.UniqueInternalLinkageNames) {
+ if (isa<FunctionDecl>(TargetDecl)) {
+ if (this->getFunctionLinkage(CalleeInfo.getCalleeDecl()) ==
+ llvm::GlobalValue::InternalLinkage)
+ FuncAttrs.addAttribute("sample-profile-suffix-elision-policy",
+ "selected");
+ }
+ }
+
// Collect non-call-site function IR attributes from declaration-specific
// information.
if (!AttrOnCallSite) {
@@ -2117,8 +2209,8 @@
return false;
};
- FuncAttrs.addAttribute("disable-tail-calls",
- llvm::toStringRef(shouldDisableTailCalls()));
+ if (shouldDisableTailCalls())
+ FuncAttrs.addAttribute("disable-tail-calls", "true");
// CPU/feature overrides. addDefaultFunctionDefinitionAttributes
// handles these separately to set them based on the global defaults.
@@ -2130,6 +2222,34 @@
QualType RetTy = FI.getReturnType();
const ABIArgInfo &RetAI = FI.getReturnInfo();
+ const llvm::DataLayout &DL = getDataLayout();
+
+ // C++ explicitly makes returning undefined values UB. C's rule only applies
+ // to used values, so we never mark them noundef for now.
+ bool HasStrictReturn = getLangOpts().CPlusPlus;
+ if (TargetDecl) {
+ if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(TargetDecl))
+ HasStrictReturn &= !FDecl->isExternC();
+ else if (const VarDecl *VDecl = dyn_cast<VarDecl>(TargetDecl))
+ // Function pointer
+ HasStrictReturn &= !VDecl->isExternC();
+ }
+
+ // We don't want to be too aggressive with the return checking, unless
+ // it's explicit in the code opts or we're using an appropriate sanitizer.
+ // Try to respect what the programmer intended.
+ HasStrictReturn &= getCodeGenOpts().StrictReturn ||
+ !MayDropFunctionReturn(getContext(), RetTy) ||
+ getLangOpts().Sanitize.has(SanitizerKind::Memory) ||
+ getLangOpts().Sanitize.has(SanitizerKind::Return);
+
+ // Determine if the return type could be partially undef
+ if (CodeGenOpts.EnableNoundefAttrs && HasStrictReturn) {
+ if (!RetTy->isVoidType() && RetAI.getKind() != ABIArgInfo::Indirect &&
+ DetermineNoUndef(RetTy, getTypes(), DL, RetAI))
+ RetAttrs.addAttribute(llvm::Attribute::NoUndef);
+ }
+
switch (RetAI.getKind()) {
case ABIArgInfo::Extend:
if (RetAI.isSignExt())
@@ -2160,18 +2280,21 @@
llvm_unreachable("Invalid ABI kind for return argument");
}
- if (const auto *RefTy = RetTy->getAs<ReferenceType>()) {
- QualType PTy = RefTy->getPointeeType();
- if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
- RetAttrs.addDereferenceableAttr(
- getMinimumObjectSize(PTy).getQuantity());
- if (getContext().getTargetAddressSpace(PTy) == 0 &&
- !CodeGenOpts.NullPointerIsValid)
- RetAttrs.addAttribute(llvm::Attribute::NonNull);
- if (PTy->isObjectType()) {
- llvm::Align Alignment =
- getNaturalPointeeTypeAlignment(RetTy).getAsAlign();
- RetAttrs.addAlignmentAttr(Alignment);
+ if (!IsThunk) {
+ // FIXME: fix this properly, https://reviews.llvm.org/D100388
+ if (const auto *RefTy = RetTy->getAs<ReferenceType>()) {
+ QualType PTy = RefTy->getPointeeType();
+ if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
+ RetAttrs.addDereferenceableAttr(
+ getMinimumObjectSize(PTy).getQuantity());
+ if (getContext().getTargetAddressSpace(PTy) == 0 &&
+ !CodeGenOpts.NullPointerIsValid)
+ RetAttrs.addAttribute(llvm::Attribute::NonNull);
+ if (PTy->isObjectType()) {
+ llvm::Align Alignment =
+ getNaturalPointeeTypeAlignment(RetTy).getAsAlign();
+ RetAttrs.addAlignmentAttr(Alignment);
+ }
}
}
@@ -2193,27 +2316,29 @@
// Attach attributes to inalloca argument.
if (IRFunctionArgs.hasInallocaArg()) {
llvm::AttrBuilder Attrs;
- Attrs.addAttribute(llvm::Attribute::InAlloca);
+ Attrs.addInAllocaAttr(FI.getArgStruct());
ArgAttrs[IRFunctionArgs.getInallocaArgNo()] =
llvm::AttributeSet::get(getLLVMContext(), Attrs);
}
- // Apply `nonnull` and `dereferencable(N)` to the `this` argument.
+ // Apply `nonnull`, `dereferencable(N)` and `align N` to the `this` argument,
+ // unless this is a thunk function.
+ // FIXME: fix this properly, https://reviews.llvm.org/D100388
if (FI.isInstanceMethod() && !IRFunctionArgs.hasInallocaArg() &&
- !FI.arg_begin()->type->isVoidPointerType()) {
+ !FI.arg_begin()->type->isVoidPointerType() && !IsThunk) {
auto IRArgs = IRFunctionArgs.getIRArgs(0);
assert(IRArgs.second == 1 && "Expected only a single `this` pointer.");
llvm::AttrBuilder Attrs;
+ QualType ThisTy =
+ FI.arg_begin()->type.castAs<PointerType>()->getPointeeType();
+
if (!CodeGenOpts.NullPointerIsValid &&
getContext().getTargetAddressSpace(FI.arg_begin()->type) == 0) {
Attrs.addAttribute(llvm::Attribute::NonNull);
- Attrs.addDereferenceableAttr(
- getMinimumObjectSize(
- FI.arg_begin()->type.castAs<PointerType>()->getPointeeType())
- .getQuantity());
+ Attrs.addDereferenceableAttr(getMinimumObjectSize(ThisTy).getQuantity());
} else {
// FIXME dereferenceable should be correct here, regardless of
// NullPointerIsValid. However, dereferenceable currently does not always
@@ -2225,6 +2350,12 @@
.getQuantity());
}
+ llvm::Align Alignment =
+ getNaturalTypeAlignment(ThisTy, /*BaseInfo=*/nullptr,
+ /*TBAAInfo=*/nullptr, /*forPointeeType=*/true)
+ .getAsAlign();
+ Attrs.addAlignmentAttr(Alignment);
+
ArgAttrs[IRArgs.first] = llvm::AttributeSet::get(getLLVMContext(), Attrs);
}
@@ -2246,6 +2377,11 @@
}
}
+ // Decide whether the argument we're handling could be partially undef
+ bool ArgNoUndef = DetermineNoUndef(ParamType, getTypes(), DL, AI);
+ if (CodeGenOpts.EnableNoundefAttrs && ArgNoUndef)
+ Attrs.addAttribute(llvm::Attribute::NoUndef);
+
// 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
// have the corresponding parameter variable. It doesn't make
// sense to do it here because parameters are so messed up.
@@ -2261,6 +2397,7 @@
Attrs.addAttribute(llvm::Attribute::Nest);
else if (AI.getInReg())
Attrs.addAttribute(llvm::Attribute::InReg);
+ Attrs.addStackAlignmentAttr(llvm::MaybeAlign(AI.getDirectAlign()));
break;
case ABIArgInfo::Indirect: {
@@ -2370,6 +2507,10 @@
case ParameterABI::SwiftContext:
Attrs.addAttribute(llvm::Attribute::SwiftSelf);
break;
+
+ case ParameterABI::SwiftAsyncContext:
+ Attrs.addAttribute(llvm::Attribute::SwiftAsync);
+ break;
}
if (FI.getExtParameterInfo(ArgNo).isNoEscape())
@@ -3297,8 +3438,11 @@
--EI;
llvm::Value *ArgStruct = &*EI;
llvm::Value *SRet = Builder.CreateStructGEP(
- nullptr, ArgStruct, RetAI.getInAllocaFieldIndex());
- RV = Builder.CreateAlignedLoad(SRet, getPointerAlign(), "sret");
+ EI->getType()->getPointerElementType(), ArgStruct,
+ RetAI.getInAllocaFieldIndex());
+ llvm::Type *Ty =
+ cast<llvm::GetElementPtrInst>(SRet)->getResultElementType();
+ RV = Builder.CreateAlignedLoad(Ty, SRet, getPointerAlign(), "sret");
}
break;
@@ -3575,7 +3719,7 @@
}
// Deactivate the cleanup for the callee-destructed param that was pushed.
- if (hasAggregateEvaluationKind(type) && !CurFuncIsThunk &&
+ if (type->isRecordType() && !CurFuncIsThunk &&
type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee() &&
param->needsDestruction(getContext())) {
EHScopeStack::stable_iterator cleanup =
@@ -3886,11 +4030,11 @@
// later, so we can't check it directly.
static bool hasInAllocaArgs(CodeGenModule &CGM, CallingConv ExplicitCC,
ArrayRef<QualType> ArgTypes) {
- // The Swift calling convention doesn't go through the target-specific
- // argument classification, so it never uses inalloca.
+ // The Swift calling conventions don't go through the target-specific
+ // argument classification, they never use inalloca.
// TODO: Consider limiting inalloca use to only calling conventions supported
// by MSVC.
- if (ExplicitCC == CC_Swift)
+ if (ExplicitCC == CC_Swift || ExplicitCC == CC_SwiftAsync)
return false;
if (!CGM.getTarget().getCXXABI().isMicrosoft())
return false;
@@ -4146,7 +4290,7 @@
// In the Microsoft C++ ABI, aggregate arguments are destructed by the callee.
// However, we still have to push an EH-only cleanup in case we unwind before
// we make it to the call.
- if (HasAggregateEvalKind &&
+ if (type->isRecordType() &&
type->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
// If we're using inalloca, use the argument memory. Otherwise, use a
// temporary.
@@ -4343,7 +4487,8 @@
void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old,
llvm::Value *New) {
- DeferredReplacements.push_back(std::make_pair(Old, New));
+ DeferredReplacements.push_back(
+ std::make_pair(llvm::WeakTrackingVH(Old), New));
}
namespace {
@@ -4454,7 +4599,7 @@
const CGCallee &Callee,
ReturnValueSlot ReturnValue,
const CallArgList &CallArgs,
- llvm::CallBase **callOrInvoke,
+ llvm::CallBase **callOrInvoke, bool IsMustTail,
SourceLocation Loc) {
// FIXME: We no longer need the types from CallArgs; lift up and simplify.
@@ -4541,7 +4686,7 @@
} else {
SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca);
if (HaveInsertPoint() && ReturnValue.isUnused()) {
- uint64_t size =
+ llvm::TypeSize size =
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy));
UnusedReturnSizePtr = EmitLifetimeStart(size, SRetAlloca.getPointer());
}
@@ -4702,7 +4847,7 @@
IRCallArgs[FirstIRArg] = AI.getPointer();
// Emit lifetime markers for the temporary alloca.
- uint64_t ByvalTempElementSize =
+ llvm::TypeSize ByvalTempElementSize =
CGM.getDataLayout().getTypeAllocSize(AI.getElementType());
llvm::Value *LifetimeSize =
EmitLifetimeStart(ByvalTempElementSize, AI.getPointer());
@@ -5016,7 +5161,8 @@
llvm::AttributeList Attrs;
CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo,
Callee.getAbstractInfo(), Attrs, CallingConv,
- /*AttrOnCallSite=*/true);
+ /*AttrOnCallSite=*/true,
+ /*IsThunk=*/false);
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl))
if (FD->hasAttr<StrictFPAttr>())
@@ -5147,10 +5293,12 @@
if (CGM.getLangOpts().ObjCAutoRefCount)
AddObjCARCExceptionMetadata(CI);
- // Suppress tail calls if requested.
+ // Set tail call kind if necessary.
if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
+ else if (IsMustTail)
+ Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
}
// Add metadata for calls to MSAllocator functions
@@ -5202,6 +5350,24 @@
return GetUndefRValue(RetTy);
}
+ // If this is a musttail call, return immediately. We do not branch to the
+ // epilogue in this case.
+ if (IsMustTail) {
+ for (auto it = EHStack.find(CurrentCleanupScopeDepth); it != EHStack.end();
+ ++it) {
+ EHCleanupScope *Cleanup = dyn_cast<EHCleanupScope>(&*it);
+ if (!(Cleanup && Cleanup->getCleanup()->isRedundantBeforeReturn()))
+ CGM.ErrorUnsupported(MustTailCall, "tail call skipping over cleanups");
+ }
+ if (CI->getType()->isVoidTy())
+ Builder.CreateRetVoid();
+ else
+ Builder.CreateRet(CI);
+ Builder.ClearInsertionPoint();
+ EnsureInsertPoint();
+ return GetUndefRValue(RetTy);
+ }
+
// Perform the swifterror writeback.
if (swiftErrorTemp.isValid()) {
llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp);
diff --git a/src/llvm-project/clang/lib/CodeGen/CGClass.cpp b/src/llvm-project/clang/lib/CodeGen/CGClass.cpp
index ba221db..9895a23 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGClass.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGClass.cpp
@@ -272,7 +272,7 @@
llvm::Value *ptr = addr.getPointer();
unsigned AddrSpace = ptr->getType()->getPointerAddressSpace();
ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8Ty->getPointerTo(AddrSpace));
- ptr = CGF.Builder.CreateInBoundsGEP(ptr, baseOffset, "add.ptr");
+ ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr");
// If we have a virtual component, the alignment of the result will
// be relative only to the known alignment of that vbase.
@@ -434,8 +434,8 @@
// Apply the offset.
llvm::Value *Value = Builder.CreateBitCast(BaseAddr.getPointer(), Int8PtrTy);
- Value = Builder.CreateInBoundsGEP(Value, Builder.CreateNeg(NonVirtualOffset),
- "sub.ptr");
+ Value = Builder.CreateInBoundsGEP(
+ Int8Ty, Value, Builder.CreateNeg(NonVirtualOffset), "sub.ptr");
// Just cast.
Value = Builder.CreateBitCast(Value, DerivedPtrTy);
@@ -467,8 +467,6 @@
const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent();
const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();
- llvm::Value *VTT;
-
uint64_t SubVTTIndex;
if (Delegating) {
@@ -494,15 +492,14 @@
if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
// A VTT parameter was passed to the constructor, use it.
- VTT = LoadCXXVTT();
- VTT = Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex);
+ llvm::Value *VTT = LoadCXXVTT();
+ return Builder.CreateConstInBoundsGEP1_64(VoidPtrTy, VTT, SubVTTIndex);
} else {
// We're the complete constructor, so get the VTT by name.
- VTT = CGM.getVTables().GetAddrOfVTT(RD);
- VTT = Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex);
+ llvm::GlobalValue *VTT = CGM.getVTables().GetAddrOfVTT(RD);
+ return Builder.CreateConstInBoundsGEP2_64(
+ VTT->getValueType(), VTT, 0, SubVTTIndex);
}
-
- return VTT;
}
namespace {
@@ -1744,6 +1741,7 @@
llvm::ConstantInt::get(CGF.SizeTy, PoisonStart.getQuantity());
llvm::Value *OffsetPtr = CGF.Builder.CreateGEP(
+ CGF.Int8Ty,
CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.Int8PtrTy),
OffsetSizePtr);
@@ -1963,9 +1961,10 @@
}
// Find the end of the array.
+ llvm::Type *elementType = arrayBase.getElementType();
llvm::Value *arrayBegin = arrayBase.getPointer();
- llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(arrayBegin, numElements,
- "arrayctor.end");
+ llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(
+ elementType, arrayBegin, numElements, "arrayctor.end");
// Enter the loop, setting up a phi for the current location to initialize.
llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
@@ -2023,9 +2022,8 @@
}
// Go to the next element.
- llvm::Value *next =
- Builder.CreateInBoundsGEP(cur, llvm::ConstantInt::get(SizeTy, 1),
- "arrayctor.next");
+ llvm::Value *next = Builder.CreateInBoundsGEP(
+ elementType, cur, llvm::ConstantInt::get(SizeTy, 1), "arrayctor.next");
cur->addIncoming(next, Builder.GetInsertBlock());
// Check whether that's the end of the loop.
@@ -2182,7 +2180,7 @@
const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(
Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs);
CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type));
- EmitCall(Info, Callee, ReturnValueSlot(), Args, nullptr, Loc);
+ EmitCall(Info, Callee, ReturnValueSlot(), Args, nullptr, false, Loc);
// Generate vtable assumptions if we're constructing a complete object
// with a vtable. We don't do this for base subobjects for two reasons:
@@ -2518,8 +2516,10 @@
llvm::FunctionType::get(CGM.Int32Ty, /*isVarArg=*/true)
->getPointerTo(ProgAS)
->getPointerTo(GlobalsAS);
+ // vtable field is is derived from `this` pointer, therefore it should be in
+ // default address space.
VTableField = Builder.CreatePointerBitCastOrAddrSpaceCast(
- VTableField, VTablePtrTy->getPointerTo(GlobalsAS));
+ VTableField, VTablePtrTy->getPointerTo());
VTableAddressPoint = Builder.CreatePointerBitCastOrAddrSpaceCast(
VTableAddressPoint, VTablePtrTy);
@@ -2776,7 +2776,7 @@
}
std::string TypeName = RD->getQualifiedNameAsString();
- if (getContext().getSanitizerBlacklist().isBlacklistedType(M, TypeName))
+ if (getContext().getNoSanitizeList().containsType(M, TypeName))
return;
SanitizerScope SanScope(this);
@@ -2829,8 +2829,8 @@
return false;
std::string TypeName = RD->getQualifiedNameAsString();
- return !getContext().getSanitizerBlacklist().isBlacklistedType(
- SanitizerKind::CFIVCall, TypeName);
+ return !getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
+ TypeName);
}
llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
@@ -2852,8 +2852,8 @@
std::string TypeName = RD->getQualifiedNameAsString();
if (SanOpts.has(SanitizerKind::CFIVCall) &&
- !getContext().getSanitizerBlacklist().isBlacklistedType(
- SanitizerKind::CFIVCall, TypeName)) {
+ !getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
+ TypeName)) {
EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIVCall),
SanitizerHandler::CFICheckFail, {}, {});
}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGCleanup.cpp b/src/llvm-project/clang/lib/CodeGen/CGCleanup.cpp
index ad543ef..b9364fc 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGCleanup.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGCleanup.cpp
@@ -194,6 +194,11 @@
if (IsLifetimeMarker)
Scope->setLifetimeMarker();
+ // With Windows -EHa, Invoke llvm.seh.scope.begin() for EHCleanup
+ if (CGF->getLangOpts().EHAsynch && IsEHCleanup && !IsLifetimeMarker &&
+ CGF->getTarget().getCXXABI().isMicrosoft())
+ CGF->EmitSehCppScopeBegin();
+
return Scope->getCleanupBuffer();
}
@@ -759,14 +764,31 @@
if (Scope.isEHCleanup())
cleanupFlags.setIsEHCleanupKind();
+ // Under -EHa, invoke seh.scope.end() to mark scope end before dtor
+ bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker();
+ const EHPersonality &Personality = EHPersonality::get(*this);
if (!RequiresNormalCleanup) {
+ // Mark CPP scope end for passed-by-value Arg temp
+ // per Windows ABI which is "normally" Cleanup in callee
+ if (IsEHa && getInvokeDest()) {
+ if (Personality.isMSVCXXPersonality())
+ EmitSehCppScopeEnd();
+ }
destroyOptimisticNormalEntry(*this, Scope);
EHStack.popCleanup();
} else {
// If we have a fallthrough and no other need for the cleanup,
// emit it directly.
- if (HasFallthrough && !HasPrebranchedFallthrough &&
- !HasFixups && !HasExistingBranches) {
+ if (HasFallthrough && !HasPrebranchedFallthrough && !HasFixups &&
+ !HasExistingBranches) {
+
+ // mark SEH scope end for fall-through flow
+ if (IsEHa && getInvokeDest()) {
+ if (Personality.isMSVCXXPersonality())
+ EmitSehCppScopeEnd();
+ else
+ EmitSehTryScopeEnd();
+ }
destroyOptimisticNormalEntry(*this, Scope);
EHStack.popCleanup();
@@ -801,6 +823,14 @@
// should already be branched to it.
EmitBlock(NormalEntry);
+ // intercept normal cleanup to mark SEH scope end
+ if (IsEHa) {
+ if (Personality.isMSVCXXPersonality())
+ EmitSehCppScopeEnd();
+ else
+ EmitSehTryScopeEnd();
+ }
+
// III. Figure out where we're going and build the cleanup
// epilogue.
@@ -1248,11 +1278,17 @@
// to the current RunCleanupsScope.
if (C == EHStack.stable_begin() &&
CurrentCleanupScopeDepth.strictlyEncloses(C)) {
- // If it's a normal cleanup, we need to pretend that the
- // fallthrough is unreachable.
- CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
- PopCleanupBlock();
- Builder.restoreIP(SavedIP);
+ // Per comment below, checking EHAsynch is not really necessary
+ // it's there to assure zero-impact w/o EHAsynch option
+ if (!Scope.isNormalCleanup() && getLangOpts().EHAsynch) {
+ PopCleanupBlock();
+ } else {
+ // If it's a normal cleanup, we need to pretend that the
+ // fallthrough is unreachable.
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+ PopCleanupBlock();
+ Builder.restoreIP(SavedIP);
+ }
return;
}
@@ -1276,3 +1312,59 @@
pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject,
/*useEHCleanup*/ true);
}
+
+// Need to set "funclet" in OperandBundle properly for noThrow
+// intrinsic (see CGCall.cpp)
+static void EmitSehScope(CodeGenFunction &CGF,
+ llvm::FunctionCallee &SehCppScope) {
+ llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
+ assert(CGF.Builder.GetInsertBlock() && InvokeDest);
+ llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
+ SmallVector<llvm::OperandBundleDef, 1> BundleList =
+ CGF.getBundlesForFunclet(SehCppScope.getCallee());
+ if (CGF.CurrentFuncletPad)
+ BundleList.emplace_back("funclet", CGF.CurrentFuncletPad);
+ CGF.Builder.CreateInvoke(SehCppScope, Cont, InvokeDest, None, BundleList);
+ CGF.EmitBlock(Cont);
+}
+
+// Invoke a llvm.seh.scope.begin at the beginning of a CPP scope for -EHa
+void CodeGenFunction::EmitSehCppScopeBegin() {
+ assert(getLangOpts().EHAsynch);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ llvm::FunctionCallee SehCppScope =
+ CGM.CreateRuntimeFunction(FTy, "llvm.seh.scope.begin");
+ EmitSehScope(*this, SehCppScope);
+}
+
+// Invoke a llvm.seh.scope.end at the end of a CPP scope for -EHa
+// llvm.seh.scope.end is emitted before popCleanup, so it's "invoked"
+void CodeGenFunction::EmitSehCppScopeEnd() {
+ assert(getLangOpts().EHAsynch);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ llvm::FunctionCallee SehCppScope =
+ CGM.CreateRuntimeFunction(FTy, "llvm.seh.scope.end");
+ EmitSehScope(*this, SehCppScope);
+}
+
+// Invoke a llvm.seh.try.begin at the beginning of a SEH scope for -EHa
+void CodeGenFunction::EmitSehTryScopeBegin() {
+ assert(getLangOpts().EHAsynch);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ llvm::FunctionCallee SehCppScope =
+ CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin");
+ EmitSehScope(*this, SehCppScope);
+}
+
+// Invoke a llvm.seh.try.end at the end of a SEH scope for -EHa
+void CodeGenFunction::EmitSehTryScopeEnd() {
+ assert(getLangOpts().EHAsynch);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ llvm::FunctionCallee SehCppScope =
+ CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
+ EmitSehScope(*this, SehCppScope);
+}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGCoroutine.cpp b/src/llvm-project/clang/lib/CodeGen/CGCoroutine.cpp
index 5c57ad0..ca071d3 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGCoroutine.cpp
@@ -556,6 +556,8 @@
{Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
createCoroData(*this, CurCoro, CoroId);
CurCoro.Data->SuspendBB = RetBB;
+ assert(ShouldEmitLifetimeMarkers &&
+ "Must emit lifetime intrinsics for coroutines");
// Backend is allowed to elide memory allocations, to help it, emit
// auto mem = coro.alloc() ? 0 : ... allocation code ...;
@@ -600,10 +602,21 @@
CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
{
+ CGDebugInfo *DI = getDebugInfo();
ParamReferenceReplacerRAII ParamReplacer(LocalDeclMap);
CodeGenFunction::RunCleanupsScope ResumeScope(*this);
EHStack.pushCleanup<CallCoroDelete>(NormalAndEHCleanup, S.getDeallocate());
+ // Create mapping between parameters and copy-params for coroutine function.
+ auto ParamMoves = S.getParamMoves();
+ assert(
+ (ParamMoves.size() == 0 || (ParamMoves.size() == FnArgs.size())) &&
+ "ParamMoves and FnArgs should be the same size for coroutine function");
+ if (ParamMoves.size() == FnArgs.size() && DI)
+ for (const auto Pair : llvm::zip(FnArgs, ParamMoves))
+ DI->getCoroutineParameterMappings().insert(
+ {std::get<0>(Pair), std::get<1>(Pair)});
+
// Create parameter copies. We do it before creating a promise, since an
// evolution of coroutine TS may allow promise constructor to observe
// parameter copies.
diff --git a/src/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp b/src/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp
index 99944af..81c910f 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -249,26 +249,7 @@
}
StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
- assert(FD && "Invalid FunctionDecl!");
- IdentifierInfo *FII = FD->getIdentifier();
- FunctionTemplateSpecializationInfo *Info =
- FD->getTemplateSpecializationInfo();
-
- if (!Info && FII)
- return FII->getName();
-
- SmallString<128> NS;
- llvm::raw_svector_ostream OS(NS);
- FD->printName(OS);
-
- // Add any template specialization args.
- if (Info) {
- const TemplateArgumentList *TArgs = Info->TemplateArguments;
- printTemplateArgumentList(OS, TArgs->asArray(), getPrintingPolicy());
- }
-
- // Copy this name on the side and use its reference.
- return internString(OS.str());
+ return internString(GetName(FD));
}
StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
@@ -301,15 +282,8 @@
StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
if (isa<ClassTemplateSpecializationDecl>(RD)) {
- SmallString<128> Name;
- llvm::raw_svector_ostream OS(Name);
- PrintingPolicy PP = getPrintingPolicy();
- PP.PrintCanonicalTypes = true;
- RD->getNameForDiagnostic(OS, PP,
- /*Qualified*/ false);
-
// Copy this name on the side and use its reference.
- return internString(Name);
+ return internString(GetName(RD));
}
// quick optimization to avoid having to intern strings that are already
@@ -317,8 +291,9 @@
if (const IdentifierInfo *II = RD->getIdentifier())
return II->getName();
- // The CodeView printer in LLVM wants to see the names of unnamed types: it is
- // used to reconstruct the fully qualified type names.
+ // The CodeView printer in LLVM wants to see the names of unnamed types
+ // because they need to have a unique identifier.
+ // These names are used to reconstruct the fully qualified type names.
if (CGM.getCodeGenOpts().EmitCodeView) {
if (const TypedefNameDecl *D = RD->getTypedefNameForAnonDecl()) {
assert(RD->getDeclContext() == D->getDeclContext() &&
@@ -342,6 +317,12 @@
// associate typedef mangled in if they have one.
Name = TND->getName();
+ // Give lambdas a display name based on their name mangling.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ if (CXXRD->isLambda())
+ return internString(
+ CGM.getCXXABI().getMangleContext().getLambdaString(CXXRD));
+
if (!Name.empty()) {
SmallString<256> UnnamedType("<unnamed-type-");
UnnamedType += Name;
@@ -560,14 +541,19 @@
if (LO.CPlusPlus) {
if (LO.ObjC)
LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
- else if (LO.CPlusPlus14)
+ else if (LO.CPlusPlus14 && (!CGM.getCodeGenOpts().DebugStrictDwarf ||
+ CGM.getCodeGenOpts().DwarfVersion >= 5))
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_14;
- else if (LO.CPlusPlus11)
+ else if (LO.CPlusPlus11 && (!CGM.getCodeGenOpts().DebugStrictDwarf ||
+ CGM.getCodeGenOpts().DwarfVersion >= 5))
LangTag = llvm::dwarf::DW_LANG_C_plus_plus_11;
else
LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
} else if (LO.ObjC) {
LangTag = llvm::dwarf::DW_LANG_ObjC;
+ } else if (LO.OpenCL && (!CGM.getCodeGenOpts().DebugStrictDwarf ||
+ CGM.getCodeGenOpts().DwarfVersion >= 5)) {
+ LangTag = llvm::dwarf::DW_LANG_OpenCL;
} else if (LO.RenderScript) {
LangTag = llvm::dwarf::DW_LANG_GOOGLE_RenderScript;
} else if (LO.C99) {
@@ -752,6 +738,59 @@
#include "clang/Basic/PPCTypes.def"
return CreateType(cast<const BuiltinType>(CGM.getContext().IntTy));
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
+ {
+ ASTContext::BuiltinVectorTypeInfo Info =
+ CGM.getContext().getBuiltinVectorTypeInfo(BT);
+
+ unsigned ElementCount = Info.EC.getKnownMinValue();
+ unsigned SEW = CGM.getContext().getTypeSize(Info.ElementType);
+
+ bool Fractional = false;
+ unsigned LMUL;
+ unsigned FixedSize = ElementCount * SEW;
+ if (Info.ElementType == CGM.getContext().BoolTy) {
+ // Mask type only occupies one vector register.
+ LMUL = 1;
+ } else if (FixedSize < 64) {
+ // In RVV scalable vector types, we encode 64 bits in the fixed part.
+ Fractional = true;
+ LMUL = 64 / FixedSize;
+ } else {
+ LMUL = FixedSize / 64;
+ }
+
+ // Element count = (VLENB / SEW) x LMUL
+ SmallVector<int64_t, 9> Expr(
+ // The DW_OP_bregx operation has two operands: a register which is
+ // specified by an unsigned LEB128 number, followed by a signed LEB128
+ // offset.
+ {llvm::dwarf::DW_OP_bregx, // Read the contents of a register.
+ 4096 + 0xC22, // RISC-V VLENB CSR register.
+ 0, // Offset for DW_OP_bregx. It is dummy here.
+ llvm::dwarf::DW_OP_constu,
+ SEW / 8, // SEW is in bits.
+ llvm::dwarf::DW_OP_div, llvm::dwarf::DW_OP_constu, LMUL});
+ if (Fractional)
+ Expr.push_back(llvm::dwarf::DW_OP_div);
+ else
+ Expr.push_back(llvm::dwarf::DW_OP_mul);
+
+ auto *LowerBound =
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
+ llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0));
+ auto *UpperBound = DBuilder.createExpression(Expr);
+ llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange(
+ /*count*/ nullptr, LowerBound, UpperBound, /*stride*/ nullptr);
+ llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
+ llvm::DIType *ElemTy =
+ getOrCreateType(Info.ElementType, TheCU->getFile());
+
+ auto Align = getTypeAlignIfRequired(BT, CGM.getContext());
+ return DBuilder.createVectorType(/*Size=*/0, Align, ElemTy,
+ SubscriptArray);
+ }
case BuiltinType::UChar:
case BuiltinType::Char_U:
Encoding = llvm::dwarf::DW_ATE_unsigned_char;
@@ -1248,6 +1287,9 @@
return llvm::dwarf::DW_CC_LLVM_OpenCLKernel;
case CC_Swift:
return llvm::dwarf::DW_CC_LLVM_Swift;
+ case CC_SwiftAsync:
+ // [FIXME: swiftasynccc] Update to SwiftAsync once LLVM support lands.
+ return llvm::dwarf::DW_CC_LLVM_Swift;
case CC_PreserveMost:
return llvm::dwarf::DW_CC_LLVM_PreserveMost;
case CC_PreserveAll:
@@ -1722,6 +1764,8 @@
Flags |= llvm::DINode::FlagLValueReference;
if (Method->getRefQualifier() == RQ_RValue)
Flags |= llvm::DINode::FlagRValueReference;
+ if (!Method->isExternallyVisible())
+ SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
if (CGM.getLangOpts().Optimize)
SPFlags |= llvm::DISubprogram::SPFlagOptimized;
@@ -2323,7 +2367,8 @@
if (DebugKind == codegenoptions::DebugLineTablesOnly)
return true;
- if (DebugKind > codegenoptions::LimitedDebugInfo)
+ if (DebugKind > codegenoptions::LimitedDebugInfo ||
+ RD->hasAttr<StandaloneDebugAttr>())
return false;
if (!LangOpts.CPlusPlus)
@@ -2677,16 +2722,26 @@
EltTys.push_back(PropertyNode);
};
{
- llvm::SmallPtrSet<const IdentifierInfo *, 16> PropertySet;
+ // Use 'char' for the isClassProperty bit as DenseSet requires space for
+ // empty/tombstone keys in the data type (and bool is too small for that).
+ typedef std::pair<char, const IdentifierInfo *> IsClassAndIdent;
+ /// List of already emitted properties. Two distinct class and instance
+ /// properties can share the same identifier (but not two instance
+ /// properties or two class properties).
+ llvm::DenseSet<IsClassAndIdent> PropertySet;
+ /// Returns the IsClassAndIdent key for the given property.
+ auto GetIsClassAndIdent = [](const ObjCPropertyDecl *PD) {
+ return std::make_pair(PD->isClassProperty(), PD->getIdentifier());
+ };
for (const ObjCCategoryDecl *ClassExt : ID->known_extensions())
for (auto *PD : ClassExt->properties()) {
- PropertySet.insert(PD->getIdentifier());
+ PropertySet.insert(GetIsClassAndIdent(PD));
AddProperty(PD);
}
for (const auto *PD : ID->properties()) {
// Don't emit duplicate metadata for properties that were already in a
// class extension.
- if (!PropertySet.insert(PD->getIdentifier()).second)
+ if (!PropertySet.insert(GetIsClassAndIdent(PD)).second)
continue;
AddProperty(PD);
}
@@ -2915,8 +2970,13 @@
llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty,
llvm::DIFile *Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type, Ty,
- Ty->getPointeeType(), Unit);
+ llvm::dwarf::Tag Tag = llvm::dwarf::DW_TAG_rvalue_reference_type;
+ // DW_TAG_rvalue_reference_type was introduced in DWARF 4.
+ if (CGM.getCodeGenOpts().DebugStrictDwarf &&
+ CGM.getCodeGenOpts().DwarfVersion < 4)
+ Tag = llvm::dwarf::DW_TAG_reference_type;
+
+ return CreatePointerLikeType(Tag, Ty, Ty->getPointeeType(), Unit);
}
llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
@@ -3024,15 +3084,11 @@
SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
- // Create elements for each enumerator.
SmallVector<llvm::Metadata *, 16> Enumerators;
ED = ED->getDefinition();
- bool IsSigned = ED->getIntegerType()->isSignedIntegerType();
for (const auto *Enum : ED->enumerators()) {
- const auto &InitVal = Enum->getInitVal();
- auto Value = IsSigned ? InitVal.getSExtValue() : InitVal.getZExtValue();
Enumerators.push_back(
- DBuilder.createEnumerator(Enum->getName(), Value, !IsSigned));
+ DBuilder.createEnumerator(Enum->getName(), Enum->getInitVal()));
}
// Return a CompositeType for the enum itself.
@@ -3459,19 +3515,20 @@
llvm::DIScope *&FDContext,
llvm::DINodeArray &TParamsArray,
llvm::DINode::DIFlags &Flags) {
- const auto *FD = cast<FunctionDecl>(GD.getDecl());
+ const auto *FD = cast<FunctionDecl>(GD.getCanonicalDecl().getDecl());
Name = getFunctionName(FD);
// Use mangled name as linkage name for C/C++ functions.
- if (FD->hasPrototype()) {
+ if (FD->getType()->getAs<FunctionProtoType>())
LinkageName = CGM.getMangledName(GD);
+ if (FD->hasPrototype())
Flags |= llvm::DINode::FlagPrototyped;
- }
// No need to replicate the linkage name if it isn't different from the
// subprogram name, no need to have it at all unless coverage is enabled or
// debug is set to more than just line tables or extra debug info is needed.
if (LinkageName == Name || (!CGM.getCodeGenOpts().EmitGcovArcs &&
!CGM.getCodeGenOpts().EmitGcovNotes &&
!CGM.getCodeGenOpts().DebugInfoForProfiling &&
+ !CGM.getCodeGenOpts().PseudoProbeForProfiling &&
DebugKind <= codegenoptions::DebugLineTablesOnly))
LinkageName = StringRef();
@@ -3915,12 +3972,7 @@
return;
llvm::TimeTraceScope TimeScope("DebugFunction", [&]() {
- std::string Name;
- llvm::raw_string_ostream OS(Name);
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- ND->getNameForDiagnostic(OS, getPrintingPolicy(),
- /*Qualified=*/true);
- return Name;
+ return GetName(D, true);
});
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
@@ -3984,9 +4036,9 @@
if (CalleeDecl->getBuiltinID() != 0 || CalleeDecl->hasAttr<NoDebugAttr>() ||
getCallSiteRelatedAttrs() == llvm::DINode::FlagZero)
return;
- if (const auto *Id = CalleeDecl->getIdentifier())
- if (Id->isReservedName())
- return;
+ if (CalleeDecl->isReserved(CGM.getLangOpts()) !=
+ ReservedIdentifierStatus::NotReserved)
+ return;
// If there is no DISubprogram attached to the function being called,
// create the one describing the function in order to have complete
@@ -4229,7 +4281,9 @@
auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
StringRef Name = VD->getName();
if (!Name.empty()) {
- if (VD->hasAttr<BlocksAttr>()) {
+ // __block vars are stored on the heap if they are captured by a block that
+ // can escape the local scope.
+ if (VD->isEscapingByref()) {
// Here, we need an offset *into* the alloca.
CharUnits offset = CharUnits::fromQuantity(32);
Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
@@ -4290,13 +4344,53 @@
}
// Create the descriptor for the variable.
- auto *D = ArgNo ? DBuilder.createParameterVariable(
- Scope, Name, *ArgNo, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags)
- : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize,
- Flags, Align);
+ llvm::DILocalVariable *D = nullptr;
+ if (ArgNo) {
+ D = DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags);
+ } else {
+ // For normal local variable, we will try to find out whether 'VD' is the
+ // copy parameter of coroutine.
+ // If yes, we are going to use DIVariable of the origin parameter instead
+ // of creating the new one.
+ // If no, it might be a normal alloc, we just create a new one for it.
+ // Check whether the VD is move parameters.
+ auto RemapCoroArgToLocalVar = [&]() -> llvm::DILocalVariable * {
+ // The scope of parameter and move-parameter should be distinct
+ // DISubprogram.
+ if (!isa<llvm::DISubprogram>(Scope) || !Scope->isDistinct())
+ return nullptr;
+
+ auto Iter = llvm::find_if(CoroutineParameterMappings, [&](auto &Pair) {
+ Stmt *StmtPtr = const_cast<Stmt *>(Pair.second);
+ if (DeclStmt *DeclStmtPtr = dyn_cast<DeclStmt>(StmtPtr)) {
+ DeclGroupRef DeclGroup = DeclStmtPtr->getDeclGroup();
+ Decl *Decl = DeclGroup.getSingleDecl();
+ if (VD == dyn_cast_or_null<VarDecl>(Decl))
+ return true;
+ }
+ return false;
+ });
+
+ if (Iter != CoroutineParameterMappings.end()) {
+ ParmVarDecl *PD = const_cast<ParmVarDecl *>(Iter->first);
+ auto Iter2 = llvm::find_if(ParamDbgMappings, [&](auto &DbgPair) {
+ return DbgPair.first == PD && DbgPair.second->getScope() == Scope;
+ });
+ if (Iter2 != ParamDbgMappings.end())
+ return const_cast<llvm::DILocalVariable *>(Iter2->second);
+ }
+ return nullptr;
+ };
+
+ // If we couldn't find a move param DIVariable, create a new one.
+ D = RemapCoroArgToLocalVar();
+ // Or we will create a new DIVariable for this Decl if D dose not exists.
+ if (!D)
+ D = DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags, Align);
+ }
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
llvm::DILocation::get(CGM.getLLVMContext(), Line,
@@ -4421,11 +4515,11 @@
DBuilder.insertDeclare(Storage, D, Expr, DL, Builder.GetInsertBlock());
}
-void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
- unsigned ArgNo,
- CGBuilderTy &Builder) {
+llvm::DILocalVariable *
+CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
+ unsigned ArgNo, CGBuilderTy &Builder) {
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
- EmitDeclare(VD, AI, ArgNo, Builder);
+ return EmitDeclare(VD, AI, ArgNo, Builder);
}
namespace {
@@ -4646,6 +4740,18 @@
return GVE;
}
+std::string CGDebugInfo::GetName(const Decl *D, bool Qualified) const {
+ std::string Name;
+ llvm::raw_string_ostream OS(Name);
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ PrintingPolicy PP = getPrintingPolicy();
+ PP.PrintCanonicalTypes = true;
+ PP.SuppressInlineNamespace = false;
+ ND->getNameForDiagnostic(OS, PP, Qualified);
+ }
+ return Name;
+}
+
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
@@ -4653,11 +4759,7 @@
return;
llvm::TimeTraceScope TimeScope("DebugGlobalVariable", [&]() {
- std::string Name;
- llvm::raw_string_ostream OS(Name);
- D->getNameForDiagnostic(OS, getPrintingPolicy(),
- /*Qualified=*/true);
- return Name;
+ return GetName(D, true);
});
// If we already created a DIGlobalVariable for this declaration, just attach
@@ -4721,11 +4823,7 @@
if (VD->hasAttr<NoDebugAttr>())
return;
llvm::TimeTraceScope TimeScope("DebugConstGlobalVariable", [&]() {
- std::string Name;
- llvm::raw_string_ostream OS(Name);
- VD->getNameForDiagnostic(OS, getPrintingPolicy(),
- /*Qualified=*/true);
- return Name;
+ return GetName(VD, true);
});
auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
@@ -4846,24 +4944,7 @@
}
}
-void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
- if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
- return;
- assert(UD.shadow_size() &&
- "We shouldn't be codegening an invalid UsingDecl containing no decls");
- // Emitting one decl is sufficient - debuggers can detect that this is an
- // overloaded name & provide lookup for all the overloads.
- const UsingShadowDecl &USD = **UD.shadow_begin();
-
- // FIXME: Skip functions with undeduced auto return type for now since we
- // don't currently have the plumbing for separate declarations & definitions
- // of free functions and mismatched types (auto in the declaration, concrete
- // return type in the definition)
- if (const auto *FD = dyn_cast<FunctionDecl>(USD.getUnderlyingDecl()))
- if (const auto *AT =
- FD->getType()->castAs<FunctionProtoType>()->getContainedAutoType())
- if (AT->getDeducedType().isNull())
- return;
+void CGDebugInfo::EmitUsingShadowDecl(const UsingShadowDecl &USD) {
if (llvm::DINode *Target =
getDeclarationOrDefinition(USD.getUnderlyingDecl())) {
auto Loc = USD.getLocation();
@@ -4873,6 +4954,42 @@
}
}
+void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
+ if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
+ return;
+ assert(UD.shadow_size() &&
+ "We shouldn't be codegening an invalid UsingDecl containing no decls");
+
+ for (const auto *USD : UD.shadows()) {
+ // FIXME: Skip functions with undeduced auto return type for now since we
+ // don't currently have the plumbing for separate declarations & definitions
+ // of free functions and mismatched types (auto in the declaration, concrete
+ // return type in the definition)
+ if (const auto *FD = dyn_cast<FunctionDecl>(USD->getUnderlyingDecl()))
+ if (const auto *AT = FD->getType()
+ ->castAs<FunctionProtoType>()
+ ->getContainedAutoType())
+ if (AT->getDeducedType().isNull())
+ continue;
+
+ EmitUsingShadowDecl(*USD);
+ // Emitting one decl is sufficient - debuggers can detect that this is an
+ // overloaded name & provide lookup for all the overloads.
+ break;
+ }
+}
+
+void CGDebugInfo::EmitUsingEnumDecl(const UsingEnumDecl &UD) {
+ if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
+ return;
+ assert(UD.shadow_size() &&
+ "We shouldn't be codegening an invalid UsingEnumDecl"
+ " containing no decls");
+
+ for (const auto *USD : UD.shadows())
+ EmitUsingShadowDecl(*USD);
+}
+
void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) {
if (CGM.getCodeGenOpts().getDebuggerTuning() != llvm::DebuggerKind::LLDB)
return;
diff --git a/src/llvm-project/clang/lib/CodeGen/CGDebugInfo.h b/src/llvm-project/clang/lib/CodeGen/CGDebugInfo.h
index afd5b50..b01165f 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGDebugInfo.h
+++ b/src/llvm-project/clang/lib/CodeGen/CGDebugInfo.h
@@ -161,6 +161,15 @@
llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIDerivedType>>
StaticDataMemberCache;
+ using ParamDecl2StmtTy = llvm::DenseMap<const ParmVarDecl *, const Stmt *>;
+ using Param2DILocTy =
+ llvm::DenseMap<const ParmVarDecl *, llvm::DILocalVariable *>;
+
+ /// The key is coroutine real parameters, value is coroutine move parameters.
+ ParamDecl2StmtTy CoroutineParameterMappings;
+ /// The key is coroutine real parameters, value is DIVariable in LLVM IR.
+ Param2DILocTy ParamDbgMappings;
+
/// Helper functions for getOrCreateType.
/// @{
/// Currently the checksum of an interface includes the number of
@@ -463,8 +472,10 @@
/// Emit call to \c llvm.dbg.declare for an argument variable
/// declaration.
- void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
- unsigned ArgNo, CGBuilderTy &Builder);
+ llvm::DILocalVariable *EmitDeclareOfArgVariable(const VarDecl *Decl,
+ llvm::Value *AI,
+ unsigned ArgNo,
+ CGBuilderTy &Builder);
/// Emit call to \c llvm.dbg.declare for the block-literal argument
/// to a block invocation function.
@@ -491,9 +502,15 @@
/// Emit the type even if it might not be used.
void EmitAndRetainType(QualType Ty);
+ /// Emit a shadow decl brought in by a using or using-enum
+ void EmitUsingShadowDecl(const UsingShadowDecl &USD);
+
/// Emit C++ using declaration.
void EmitUsingDecl(const UsingDecl &UD);
+ /// Emit C++ using-enum declaration.
+ void EmitUsingEnumDecl(const UsingEnumDecl &UD);
+
/// Emit an @import declaration.
void EmitImportDecl(const ImportDecl &ID);
@@ -533,6 +550,11 @@
SourceLocation LineLoc,
SourceLocation FileLoc);
+ Param2DILocTy &getParamDbgMappings() { return ParamDbgMappings; }
+ ParamDecl2StmtTy &getCoroutineParameterMappings() {
+ return CoroutineParameterMappings;
+ }
+
private:
/// Emit call to llvm.dbg.declare for a variable declaration.
/// Returns a pointer to the DILocalVariable associated with the
@@ -549,6 +571,8 @@
llvm::DIType *WrappedType;
};
+ std::string GetName(const Decl*, bool Qualified = false) const;
+
/// Build up structure info for the byref. See \a BuildByRefType.
BlockByRefType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *OffSet);
diff --git a/src/llvm-project/clang/lib/CodeGen/CGDecl.cpp b/src/llvm-project/clang/lib/CodeGen/CGDecl.cpp
index a01638f..5b3d39f 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGDecl.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGDecl.cpp
@@ -99,6 +99,7 @@
case Decl::ConstructorUsingShadow:
case Decl::ObjCTypeParam:
case Decl::Binding:
+ case Decl::UnresolvedUsingIfExists:
llvm_unreachable("Declaration should not be in declstmts!");
case Decl::Record: // struct/union/class X;
case Decl::CXXRecord: // struct/union/class X; [C++]
@@ -137,6 +138,10 @@
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitUsingDecl(cast<UsingDecl>(D));
return;
+ case Decl::UsingEnum: // using enum X; [C++]
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitUsingEnumDecl(cast<UsingEnumDecl>(D));
+ return;
case Decl::UsingPack:
for (auto *Using : cast<UsingPackDecl>(D).expansions())
EmitDecl(*Using);
@@ -441,8 +446,10 @@
if (const SectionAttr *SA = D.getAttr<SectionAttr>())
var->setSection(SA->getName());
- if (D.hasAttr<UsedAttr>())
+ if (D.hasAttr<RetainAttr>())
CGM.addUsedGlobal(var);
+ else if (D.hasAttr<UsedAttr>())
+ CGM.addUsedOrCompilerUsedGlobal(var);
// We may have to cast the constant because of the initializer
// mismatch above.
@@ -548,6 +555,7 @@
struct CallStackRestore final : EHScopeStack::Cleanup {
Address Stack;
CallStackRestore(Address Stack) : Stack(Stack) {}
+ bool isRedundantBeforeReturn() override { return true; }
void Emit(CodeGenFunction &CGF, Flags flags) override {
llvm::Value *V = CGF.Builder.CreateLoad(Stack);
llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
@@ -706,10 +714,10 @@
}
// If it was an l-value, use objc_copyWeak.
- if (srcExpr->getValueKind() == VK_LValue) {
+ if (srcExpr->isLValue()) {
CGF.EmitARCCopyWeak(destLV.getAddress(CGF), srcAddr);
} else {
- assert(srcExpr->getValueKind() == VK_XValue);
+ assert(srcExpr->isXValue());
CGF.EmitARCMoveWeak(destLV.getAddress(CGF), srcAddr);
}
return true;
@@ -769,9 +777,10 @@
// If we're emitting a value with lifetime, we have to do the
// initialization *before* we leave the cleanup scopes.
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(init))
- init = EWC->getSubExpr();
- CodeGenFunction::RunCleanupsScope Scope(*this);
+ if (auto *EWC = dyn_cast<ExprWithCleanups>(init)) {
+ CodeGenFunction::RunCleanupsScope Scope(*this);
+ return EmitScalarInit(EWC->getSubExpr(), D, lvalue, capturedByInit);
+ }
// We have to maintain the illusion that the variable is
// zero-initialized. If the variable might be accessed in its
@@ -1119,7 +1128,7 @@
bool isConstant = true;
llvm::GlobalVariable *InsertBefore = nullptr;
unsigned AS =
- getContext().getTargetAddressSpace(getStringLiteralAddressSpace());
+ getContext().getTargetAddressSpace(GetGlobalConstantAddressSpace());
std::string Name;
if (D.hasGlobalStorage())
Name = getMangledName(&D).str() + ".const";
@@ -1313,7 +1322,7 @@
/// Emit a lifetime.begin marker if some criteria are satisfied.
/// \return a pointer to the temporary size Value if a marker was emitted, null
/// otherwise
-llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
+llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size,
llvm::Value *Addr) {
if (!ShouldEmitLifetimeMarkers)
return nullptr;
@@ -1321,7 +1330,8 @@
assert(Addr->getType()->getPointerAddressSpace() ==
CGM.getDataLayout().getAllocaAddrSpace() &&
"Pointer should be in alloca address space");
- llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
+ llvm::Value *SizeV = llvm::ConstantInt::get(
+ Int64Ty, Size.isScalable() ? -1 : Size.getFixedValue());
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
llvm::CallInst *C =
Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
@@ -1544,12 +1554,9 @@
// is rare.
if (!Bypasses.IsBypassed(&D) &&
!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) {
- llvm::TypeSize size =
- CGM.getDataLayout().getTypeAllocSize(allocaTy);
+ llvm::TypeSize Size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
emission.SizeForLifetimeMarkers =
- size.isScalable() ? EmitLifetimeStart(-1, AllocaAddr.getPointer())
- : EmitLifetimeStart(size.getFixedSize(),
- AllocaAddr.getPointer());
+ EmitLifetimeStart(Size, AllocaAddr.getPointer());
}
} else {
assert(!emission.useLifetimeMarkers());
@@ -1765,8 +1772,8 @@
llvm::Value *BaseSizeInChars =
llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity());
Address Begin = Builder.CreateElementBitCast(Loc, Int8Ty, "vla.begin");
- llvm::Value *End =
- Builder.CreateInBoundsGEP(Begin.getPointer(), SizeVal, "vla.end");
+ llvm::Value *End = Builder.CreateInBoundsGEP(
+ Begin.getElementType(), Begin.getPointer(), SizeVal, "vla.end");
llvm::BasicBlock *OriginBB = Builder.GetInsertBlock();
EmitBlock(LoopBB);
llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur");
@@ -2194,7 +2201,8 @@
}
llvm::Value *begin = addr.getPointer();
- llvm::Value *end = Builder.CreateInBoundsGEP(begin, length);
+ llvm::Value *end =
+ Builder.CreateInBoundsGEP(addr.getElementType(), begin, length);
emitArrayDestroy(begin, end, type, elementAlign, destroyer,
checkZeroLength, useEHCleanupForArray);
}
@@ -2238,8 +2246,9 @@
// Shift the address back by one element.
llvm::Value *negativeOne = llvm::ConstantInt::get(SizeTy, -1, true);
- llvm::Value *element = Builder.CreateInBoundsGEP(elementPast, negativeOne,
- "arraydestroy.element");
+ llvm::Value *element = Builder.CreateInBoundsGEP(
+ elementPast->getType()->getPointerElementType(), elementPast, negativeOne,
+ "arraydestroy.element");
if (useEHCleanup)
pushRegularPartialArrayCleanup(begin, element, elementType, elementAlign,
@@ -2279,8 +2288,11 @@
llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
SmallVector<llvm::Value*,4> gepIndices(arrayDepth+1, zero);
- begin = CGF.Builder.CreateInBoundsGEP(begin, gepIndices, "pad.arraybegin");
- end = CGF.Builder.CreateInBoundsGEP(end, gepIndices, "pad.arrayend");
+ llvm::Type *elemTy = begin->getType()->getPointerElementType();
+ begin = CGF.Builder.CreateInBoundsGEP(
+ elemTy, begin, gepIndices, "pad.arraybegin");
+ end = CGF.Builder.CreateInBoundsGEP(
+ elemTy, end, gepIndices, "pad.arrayend");
}
// Destroy the array. We don't ever need an EH cleanup because we
@@ -2468,7 +2480,7 @@
// Push a destructor cleanup for this parameter if the ABI requires it.
// Don't push a cleanup in a thunk for a method that will also emit a
// cleanup.
- if (hasAggregateEvaluationKind(Ty) && !CurFuncIsThunk &&
+ if (Ty->isRecordType() && !CurFuncIsThunk &&
Ty->castAs<RecordType>()->getDecl()->isParamDestroyedInCallee()) {
if (QualType::DestructionKind DtorKind =
D.needsDestruction(getContext())) {
@@ -2566,7 +2578,10 @@
// Emit debug info for param declarations in non-thunk functions.
if (CGDebugInfo *DI = getDebugInfo()) {
if (CGM.getCodeGenOpts().hasReducedDebugInfo() && !CurFuncIsThunk) {
- DI->EmitDeclareOfArgVariable(&D, DeclPtr.getPointer(), ArgNo, Builder);
+ llvm::DILocalVariable *DILocalVar = DI->EmitDeclareOfArgVariable(
+ &D, DeclPtr.getPointer(), ArgNo, Builder);
+ if (const auto *Var = dyn_cast_or_null<ParmVarDecl>(&D))
+ DI->getParamDbgMappings().insert({Var, DILocalVar});
}
}
@@ -2605,3 +2620,57 @@
void CodeGenModule::EmitOMPRequiresDecl(const OMPRequiresDecl *D) {
getOpenMPRuntime().processRequiresDirective(D);
}
+
+void CodeGenModule::EmitOMPAllocateDecl(const OMPAllocateDecl *D) {
+ for (const Expr *E : D->varlists()) {
+ const auto *DE = cast<DeclRefExpr>(E);
+ const auto *VD = cast<VarDecl>(DE->getDecl());
+
+ // Skip all but globals.
+ if (!VD->hasGlobalStorage())
+ continue;
+
+ // Check if the global has been materialized yet or not. If not, we are done
+ // as any later generation will utilize the OMPAllocateDeclAttr. However, if
+ // we already emitted the global we might have done so before the
+ // OMPAllocateDeclAttr was attached, leading to the wrong address space
+ // (potentially). While not pretty, common practise is to remove the old IR
+ // global and generate a new one, so we do that here too. Uses are replaced
+ // properly.
+ StringRef MangledName = getMangledName(VD);
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (!Entry)
+ continue;
+
+ // We can also keep the existing global if the address space is what we
+ // expect it to be, if not, it is replaced.
+ QualType ASTTy = VD->getType();
+ clang::LangAS GVAS = GetGlobalVarAddressSpace(VD);
+ auto TargetAS = getContext().getTargetAddressSpace(GVAS);
+ if (Entry->getType()->getAddressSpace() == TargetAS)
+ continue;
+
+ // Make a new global with the correct type / address space.
+ llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
+ llvm::PointerType *PTy = llvm::PointerType::get(Ty, TargetAS);
+
+ // Replace all uses of the old global with a cast. Since we mutate the type
+ // in place we neeed an intermediate that takes the spot of the old entry
+ // until we can create the cast.
+ llvm::GlobalVariable *DummyGV = new llvm::GlobalVariable(
+ getModule(), Entry->getValueType(), false,
+ llvm::GlobalValue::CommonLinkage, nullptr, "dummy", nullptr,
+ llvm::GlobalVariable::NotThreadLocal, Entry->getAddressSpace());
+ Entry->replaceAllUsesWith(DummyGV);
+
+ Entry->mutateType(PTy);
+ llvm::Constant *NewPtrForOldDecl =
+ llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
+ Entry, DummyGV->getType());
+
+ // Now we have a casted version of the changed global, the dummy can be
+ // replaced and deleted.
+ DummyGV->replaceAllUsesWith(NewPtrForOldDecl);
+ DummyGV->eraseFromParent();
+ }
+}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp b/src/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp
index 3dbf4cc..553fede 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -262,6 +262,58 @@
return fn;
}
+/// Create a stub function, suitable for being passed to __pt_atexit_np,
+/// which passes the given address to the given destructor function.
+llvm::Function *CodeGenFunction::createTLSAtExitStub(
+ const VarDecl &D, llvm::FunctionCallee Dtor, llvm::Constant *Addr,
+ llvm::FunctionCallee &AtExit) {
+ SmallString<256> FnName;
+ {
+ llvm::raw_svector_ostream Out(FnName);
+ CGM.getCXXABI().getMangleContext().mangleDynamicAtExitDestructor(&D, Out);
+ }
+
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeLLVMFunctionInfo(
+ getContext().IntTy, /*instanceMethod=*/false, /*chainCall=*/false,
+ {getContext().IntTy}, FunctionType::ExtInfo(), {}, RequiredArgs::All);
+
+ // Get the stub function type, int(*)(int,...).
+ llvm::FunctionType *StubTy =
+ llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy}, true);
+
+ llvm::Function *DtorStub = CGM.CreateGlobalInitOrCleanUpFunction(
+ StubTy, FnName.str(), FI, D.getLocation());
+
+ CodeGenFunction CGF(CGM);
+
+ FunctionArgList Args;
+ ImplicitParamDecl IPD(CGM.getContext(), CGM.getContext().IntTy,
+ ImplicitParamDecl::Other);
+ Args.push_back(&IPD);
+ QualType ResTy = CGM.getContext().IntTy;
+
+ CGF.StartFunction(GlobalDecl(&D, DynamicInitKind::AtExit), ResTy, DtorStub,
+ FI, Args, D.getLocation(), D.getInit()->getExprLoc());
+
+ // Emit an artificial location for this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(CGF);
+
+ llvm::CallInst *call = CGF.Builder.CreateCall(Dtor, Addr);
+
+ // Make sure the call and the callee agree on calling convention.
+ if (auto *DtorFn = dyn_cast<llvm::Function>(
+ Dtor.getCallee()->stripPointerCastsAndAliases()))
+ call->setCallingConv(DtorFn->getCallingConv());
+
+ // Return 0 from function
+ CGF.Builder.CreateStore(llvm::Constant::getNullValue(CGM.IntTy),
+ CGF.ReturnValue);
+
+ CGF.FinishFunction();
+
+ return DtorStub;
+}
+
/// Register a global destructor using the C atexit runtime function.
void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
llvm::FunctionCallee dtor,
@@ -388,43 +440,43 @@
Fn->setDoesNotThrow();
if (getLangOpts().Sanitize.has(SanitizerKind::Address) &&
- !isInSanitizerBlacklist(SanitizerKind::Address, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::Address, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
if (getLangOpts().Sanitize.has(SanitizerKind::KernelAddress) &&
- !isInSanitizerBlacklist(SanitizerKind::KernelAddress, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::KernelAddress, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeAddress);
if (getLangOpts().Sanitize.has(SanitizerKind::HWAddress) &&
- !isInSanitizerBlacklist(SanitizerKind::HWAddress, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::HWAddress, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
if (getLangOpts().Sanitize.has(SanitizerKind::KernelHWAddress) &&
- !isInSanitizerBlacklist(SanitizerKind::KernelHWAddress, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::KernelHWAddress, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress);
if (getLangOpts().Sanitize.has(SanitizerKind::MemTag) &&
- !isInSanitizerBlacklist(SanitizerKind::MemTag, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::MemTag, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeMemTag);
if (getLangOpts().Sanitize.has(SanitizerKind::Thread) &&
- !isInSanitizerBlacklist(SanitizerKind::Thread, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);
if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&
- !isInSanitizerBlacklist(SanitizerKind::Memory, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
if (getLangOpts().Sanitize.has(SanitizerKind::KernelMemory) &&
- !isInSanitizerBlacklist(SanitizerKind::KernelMemory, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::KernelMemory, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
if (getLangOpts().Sanitize.has(SanitizerKind::SafeStack) &&
- !isInSanitizerBlacklist(SanitizerKind::SafeStack, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::SafeStack, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SafeStack);
if (getLangOpts().Sanitize.has(SanitizerKind::ShadowCallStack) &&
- !isInSanitizerBlacklist(SanitizerKind::ShadowCallStack, Fn, Loc))
+ !isInNoSanitizeList(SanitizerKind::ShadowCallStack, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::ShadowCallStack);
return Fn;
@@ -499,10 +551,12 @@
} else if (PerformInit && ISA) {
EmitPointerToInitFunc(D, Addr, Fn, ISA);
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
- OrderGlobalInits Key(IPA->getPriority(), PrioritizedCXXGlobalInits.size());
+ OrderGlobalInitsOrStermFinalizers Key(IPA->getPriority(),
+ PrioritizedCXXGlobalInits.size());
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
} else if (isTemplateInstantiation(D->getTemplateSpecializationKind()) ||
- getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR) {
+ getContext().GetGVALinkageForVariable(D) == GVA_DiscardableODR ||
+ D->hasAttr<SelectAnyAttr>()) {
// C++ [basic.start.init]p2:
// Definitions of explicitly specialized class template static data
// members have ordered initialization. Other class template static data
@@ -515,17 +569,18 @@
// group with the global being initialized. On most platforms, this is a
// minor startup time optimization. In the MS C++ ABI, there are no guard
// variables, so this COMDAT key is required for correctness.
- AddGlobalCtor(Fn, 65535, COMDATKey);
- if (getTarget().getCXXABI().isMicrosoft() && COMDATKey) {
- // In The MS C++, MS add template static data member in the linker
- // drective.
- addUsedGlobal(COMDATKey);
- }
- } else if (D->hasAttr<SelectAnyAttr>()) {
+ //
// SelectAny globals will be comdat-folded. Put the initializer into a
// COMDAT group associated with the global, so the initializers get folded
// too.
+
AddGlobalCtor(Fn, 65535, COMDATKey);
+ if (COMDATKey && (getTriple().isOSBinFormatELF() ||
+ getTarget().getCXXABI().isMicrosoft())) {
+ // When COMDAT is used on ELF or in the MS C++ ABI, the key must be in
+ // llvm.used to prevent linker GC.
+ addUsedGlobal(COMDATKey);
+ }
} else {
I = DelayedCXXInitPosition.find(D); // Re-do lookup in case of re-hash.
if (I == DelayedCXXInitPosition.end()) {
@@ -566,6 +621,17 @@
return FileName;
}
+static std::string getPrioritySuffix(unsigned int Priority) {
+ assert(Priority <= 65535 && "Priority should always be <= 65535.");
+
+ // Compute the function suffix from priority. Prepend with zeroes to make
+ // sure the function names are also ordered as priorities.
+ std::string PrioritySuffix = llvm::utostr(Priority);
+ PrioritySuffix = std::string(6 - PrioritySuffix.size(), '0') + PrioritySuffix;
+
+ return PrioritySuffix;
+}
+
void
CodeGenModule::EmitCXXGlobalInitFunc() {
while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
@@ -577,12 +643,8 @@
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
- const bool UseSinitAndSterm = getCXXABI().useSinitAndSterm();
// Create our global prioritized initialization function.
if (!PrioritizedCXXGlobalInits.empty()) {
- assert(!UseSinitAndSterm && "Prioritized sinit and sterm functions are not"
- " supported yet.");
-
SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
PrioritizedCXXGlobalInits.end());
@@ -596,14 +658,10 @@
PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
LocalCXXGlobalInits.clear();
- unsigned Priority = I->first.priority;
- // Compute the function suffix from priority. Prepend with zeroes to make
- // sure the function names are also ordered as priorities.
- std::string PrioritySuffix = llvm::utostr(Priority);
- // Priority is always <= 65535 (enforced by sema).
- PrioritySuffix = std::string(6-PrioritySuffix.size(), '0')+PrioritySuffix;
+
+ unsigned int Priority = I->first.priority;
llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
- FTy, "_GLOBAL__I_" + PrioritySuffix, FI);
+ FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI);
for (; I < PrioE; ++I)
LocalCXXGlobalInits.push_back(I->second);
@@ -614,7 +672,7 @@
PrioritizedCXXGlobalInits.clear();
}
- if (UseSinitAndSterm && CXXGlobalInits.empty())
+ if (getCXXABI().useSinitAndSterm() && CXXGlobalInits.empty())
return;
// Include the filename in the symbol name. Including "sub_" matches gcc
@@ -640,7 +698,9 @@
Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
}
- if (getLangOpts().HIP) {
+ assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
+ getLangOpts().GPUAllowDeviceInit);
+ if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
Fn->addFnAttr("device-init");
}
@@ -649,12 +709,50 @@
}
void CodeGenModule::EmitCXXGlobalCleanUpFunc() {
- if (CXXGlobalDtorsOrStermFinalizers.empty())
+ if (CXXGlobalDtorsOrStermFinalizers.empty() &&
+ PrioritizedCXXStermFinalizers.empty())
return;
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
+ // Create our global prioritized cleanup function.
+ if (!PrioritizedCXXStermFinalizers.empty()) {
+ SmallVector<CXXGlobalDtorsOrStermFinalizer_t, 8> LocalCXXStermFinalizers;
+ llvm::array_pod_sort(PrioritizedCXXStermFinalizers.begin(),
+ PrioritizedCXXStermFinalizers.end());
+ // Iterate over "chunks" of dtors with same priority and emit each chunk
+ // into separate function. Note - everything is sorted first by priority,
+ // second - by lex order, so we emit dtor functions in proper order.
+ for (SmallVectorImpl<StermFinalizerData>::iterator
+ I = PrioritizedCXXStermFinalizers.begin(),
+ E = PrioritizedCXXStermFinalizers.end();
+ I != E;) {
+ SmallVectorImpl<StermFinalizerData>::iterator PrioE =
+ std::upper_bound(I + 1, E, *I, StermFinalizerPriorityCmp());
+
+ LocalCXXStermFinalizers.clear();
+
+ unsigned int Priority = I->first.priority;
+ llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
+ FTy, "_GLOBAL__a_" + getPrioritySuffix(Priority), FI);
+
+ for (; I < PrioE; ++I) {
+ llvm::FunctionCallee DtorFn = I->second;
+ LocalCXXStermFinalizers.emplace_back(DtorFn.getFunctionType(),
+ DtorFn.getCallee(), nullptr);
+ }
+
+ CodeGenFunction(*this).GenerateCXXGlobalCleanUpFunc(
+ Fn, LocalCXXStermFinalizers);
+ AddGlobalDtor(Fn, Priority);
+ }
+ PrioritizedCXXStermFinalizers.clear();
+ }
+
+ if (CXXGlobalDtorsOrStermFinalizers.empty())
+ return;
+
// Create our global cleanup function.
llvm::Function *Fn =
CreateGlobalInitOrCleanUpFunction(FTy, "_GLOBAL__D_a", FI);
@@ -761,8 +859,9 @@
void CodeGenFunction::GenerateCXXGlobalCleanUpFunc(
llvm::Function *Fn,
- const std::vector<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
- llvm::Constant *>> &DtorsOrStermFinalizers) {
+ ArrayRef<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
+ llvm::Constant *>>
+ DtorsOrStermFinalizers) {
{
auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
diff --git a/src/llvm-project/clang/lib/CodeGen/CGException.cpp b/src/llvm-project/clang/lib/CodeGen/CGException.cpp
index 7a64963..9f65e9e 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGException.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGException.cpp
@@ -39,6 +39,18 @@
return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
}
+static llvm::FunctionCallee getSehTryBeginFn(CodeGenModule &CGM) {
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.begin");
+}
+
+static llvm::FunctionCallee getSehTryEndFn(CodeGenModule &CGM) {
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ return CGM.CreateRuntimeFunction(FTy, "llvm.seh.try.end");
+}
+
static llvm::FunctionCallee getUnexpectedFn(CodeGenModule &CGM) {
// void __cxa_call_unexpected(void *thrown_exception);
@@ -467,15 +479,16 @@
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) {
// noexcept functions are simple terminate scopes.
- EHStack.pushTerminate();
+ if (!getLangOpts().EHAsynch) // -EHa: HW exception still can occur
+ EHStack.pushTerminate();
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
// TODO: Revisit exception specifications for the MS ABI. There is a way to
// encode these in an object file but MSVC doesn't do anything with it.
if (getTarget().getCXXABI().isMicrosoft())
return;
- // In wasm we currently treat 'throw()' in the same way as 'noexcept'. In
+ // In Wasm EH we currently treat 'throw()' in the same way as 'noexcept'. In
// case of throw with types, we ignore it and print a warning for now.
- // TODO Correctly handle exception specification in wasm
+ // TODO Correctly handle exception specification in Wasm EH
if (CGM.getLangOpts().hasWasmExceptions()) {
if (EST == EST_DynamicNone)
EHStack.pushTerminate();
@@ -485,6 +498,19 @@
<< FD->getExceptionSpecSourceRange();
return;
}
+ // Currently Emscripten EH only handles 'throw()' but not 'throw' with
+ // types. 'throw()' handling will be done in JS glue code so we don't need
+ // to do anything in that case. Just print a warning message in case of
+ // throw with types.
+ // TODO Correctly handle exception specification in Emscripten EH
+ if (getTarget().getCXXABI() == TargetCXXABI::WebAssembly &&
+ CGM.getLangOpts().getExceptionHandling() ==
+ LangOptions::ExceptionHandlingKind::None &&
+ EST == EST_Dynamic)
+ CGM.getDiags().Report(D->getLocation(),
+ diag::warn_wasm_dynamic_exception_spec_ignored)
+ << FD->getExceptionSpecSourceRange();
+
unsigned NumExceptions = Proto->getNumExceptions();
EHFilterScope *Filter = EHStack.pushFilter(NumExceptions);
@@ -544,7 +570,7 @@
if (!FD) {
// Check if CapturedDecl is nothrow and pop terminate scope for it.
if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) {
- if (CD->isNothrow())
+ if (CD->isNothrow() && !EHStack.empty())
EHStack.popTerminate();
}
return;
@@ -554,7 +580,8 @@
return;
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
- if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot) {
+ if (isNoexceptExceptionSpec(EST) && Proto->canThrow() == CT_Cannot &&
+ !EHStack.empty() /* possible empty when under async exceptions */) {
EHStack.popTerminate();
} else if (EST == EST_Dynamic || EST == EST_DynamicNone) {
// TODO: Revisit exception specifications for the MS ABI. There is a way to
@@ -610,6 +637,10 @@
} else {
// No exception decl indicates '...', a catch-all.
CatchScope->setHandler(I, CGM.getCXXABI().getCatchAllTypeInfo(), Handler);
+ // Under async exceptions, catch(...) need to catch HW exception too
+ // Mark scope with SehTryBegin as a SEH __try scope
+ if (getLangOpts().EHAsynch)
+ EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM));
}
}
}
@@ -724,7 +755,7 @@
// If exceptions are disabled/ignored and SEH is not in use, then there is no
// invoke destination. SEH "works" even if exceptions are off. In practice,
// this means that C++ destructors and other EH cleanups don't run, which is
- // consistent with MSVC's behavior.
+ // consistent with MSVC's behavior, except in the presence of -EHa
const LangOptions &LO = CGM.getLangOpts();
if (!LO.Exceptions || LO.IgnoreExceptions) {
if (!LO.Borland && !LO.MicrosoftExt)
@@ -1343,7 +1374,8 @@
CGF.EmitBlock(RethrowBB);
if (SavedExnVar) {
CGF.EmitRuntimeCallOrInvoke(RethrowFn,
- CGF.Builder.CreateAlignedLoad(SavedExnVar, CGF.getPointerAlign()));
+ CGF.Builder.CreateAlignedLoad(CGF.Int8PtrTy, SavedExnVar,
+ CGF.getPointerAlign()));
} else {
CGF.EmitRuntimeCallOrInvoke(RethrowFn);
}
@@ -1552,17 +1584,8 @@
CurrentFuncletPad = Builder.CreateCleanupPad(ParentPad);
// Emit the __std_terminate call.
- llvm::Value *Exn = nullptr;
- // In case of wasm personality, we need to pass the exception value to
- // __clang_call_terminate function.
- if (getLangOpts().CPlusPlus &&
- EHPersonality::get(*this).isWasmPersonality()) {
- llvm::Function *GetExnFn =
- CGM.getIntrinsic(llvm::Intrinsic::wasm_get_exception);
- Exn = Builder.CreateCall(GetExnFn, CurrentFuncletPad);
- }
llvm::CallInst *terminateCall =
- CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
+ CGM.getCXXABI().emitTerminateForUnexpectedException(*this, nullptr);
terminateCall->setDoesNotReturn();
Builder.CreateUnreachable();
@@ -1614,7 +1637,23 @@
JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
SEHTryEpilogueStack.push_back(&TryExit);
+
+ llvm::BasicBlock *TryBB = nullptr;
+ // IsEHa: emit an invoke to _seh_try_begin() runtime for -EHa
+ if (getLangOpts().EHAsynch) {
+ EmitRuntimeCallOrInvoke(getSehTryBeginFn(CGM));
+ if (SEHTryEpilogueStack.size() == 1) // outermost only
+ TryBB = Builder.GetInsertBlock();
+ }
+
EmitStmt(S.getTryBlock());
+
+ // Volatilize all blocks in Try, till current insert point
+ if (TryBB) {
+ llvm::SmallPtrSet<llvm::BasicBlock *, 10> Visited;
+ VolatilizeTryBlocks(TryBB, Visited);
+ }
+
SEHTryEpilogueStack.pop_back();
if (!TryExit.getBlock()->use_empty())
@@ -1625,6 +1664,35 @@
ExitSEHTryStmt(S);
}
+// Recursively walk through blocks in a _try
+// and make all memory instructions volatile
+void CodeGenFunction::VolatilizeTryBlocks(
+ llvm::BasicBlock *BB, llvm::SmallPtrSet<llvm::BasicBlock *, 10> &V) {
+ if (BB == SEHTryEpilogueStack.back()->getBlock() /* end of Try */ ||
+ !V.insert(BB).second /* already visited */ ||
+ !BB->getParent() /* not emitted */ || BB->empty())
+ return;
+
+ if (!BB->isEHPad()) {
+ for (llvm::BasicBlock::iterator J = BB->begin(), JE = BB->end(); J != JE;
+ ++J) {
+ if (auto LI = dyn_cast<llvm::LoadInst>(J)) {
+ LI->setVolatile(true);
+ } else if (auto SI = dyn_cast<llvm::StoreInst>(J)) {
+ SI->setVolatile(true);
+ } else if (auto* MCI = dyn_cast<llvm::MemIntrinsic>(J)) {
+ MCI->setVolatile(llvm::ConstantInt::get(Builder.getInt1Ty(), 1));
+ }
+ }
+ }
+ const llvm::Instruction *TI = BB->getTerminator();
+ if (TI) {
+ unsigned N = TI->getNumSuccessors();
+ for (unsigned I = 0; I < N; I++)
+ VolatilizeTryBlocks(TI->getSuccessor(I), V);
+ }
+}
+
namespace {
struct PerformSEHFinally final : EHScopeStack::Cleanup {
llvm::Function *OutlinedFinally;
@@ -1702,10 +1770,8 @@
void VisitDeclRefExpr(const DeclRefExpr *E) {
// If this is already a capture, just make sure we capture 'this'.
- if (E->refersToEnclosingVariableOrCapture()) {
+ if (E->refersToEnclosingVariableOrCapture())
Captures.insert(ParentThis);
- return;
- }
const auto *D = dyn_cast<VarDecl>(E->getDecl());
if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage())
@@ -1865,11 +1931,6 @@
// Create llvm.localrecover calls for all captures.
for (const VarDecl *VD : Finder.Captures) {
- if (isa<ImplicitParamDecl>(VD)) {
- CGM.ErrorUnsupported(VD, "'this' captured by SEH");
- CXXThisValue = llvm::UndefValue::get(ConvertTypeForMem(VD->getType()));
- continue;
- }
if (VD->getType()->isVariablyModifiedType()) {
CGM.ErrorUnsupported(VD, "VLA captured by SEH");
continue;
@@ -1877,6 +1938,12 @@
assert((isa<ImplicitParamDecl>(VD) || VD->isLocalVarDeclOrParm()) &&
"captured non-local variable");
+ auto L = ParentCGF.LambdaCaptureFields.find(VD);
+ if (L != ParentCGF.LambdaCaptureFields.end()) {
+ LambdaCaptureFields[VD] = L->second;
+ continue;
+ }
+
// If this decl hasn't been declared yet, it will be declared in the
// OutlinedStmt.
auto I = ParentCGF.LocalDeclMap.find(VD);
@@ -1884,8 +1951,30 @@
continue;
Address ParentVar = I->second;
- setAddrOfLocalVar(
- VD, recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP));
+ Address Recovered =
+ recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP);
+ setAddrOfLocalVar(VD, Recovered);
+
+ if (isa<ImplicitParamDecl>(VD)) {
+ CXXABIThisAlignment = ParentCGF.CXXABIThisAlignment;
+ CXXThisAlignment = ParentCGF.CXXThisAlignment;
+ CXXABIThisValue = Builder.CreateLoad(Recovered, "this");
+ if (ParentCGF.LambdaThisCaptureField) {
+ LambdaThisCaptureField = ParentCGF.LambdaThisCaptureField;
+ // We are in a lambda function where "this" is captured so the
+ // CXXThisValue need to be loaded from the lambda capture
+ LValue ThisFieldLValue =
+ EmitLValueForLambdaField(LambdaThisCaptureField);
+ if (!LambdaThisCaptureField->getType()->isPointerType()) {
+ CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer();
+ } else {
+ CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation())
+ .getScalarVal();
+ }
+ } else {
+ CXXThisValue = CXXABIThisValue;
+ }
+ }
}
if (Finder.SEHCodeSlot.isValid()) {
@@ -2025,8 +2114,8 @@
llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy);
llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo());
llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0);
- Rec = Builder.CreateAlignedLoad(Rec, getPointerAlign());
- llvm::Value *Code = Builder.CreateAlignedLoad(Rec, getIntAlign());
+ Rec = Builder.CreateAlignedLoad(RecordTy, Rec, getPointerAlign());
+ llvm::Value *Code = Builder.CreateAlignedLoad(Int32Ty, Rec, getIntAlign());
assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
Builder.CreateStore(Code, SEHCodeSlotStack.back());
}
@@ -2105,6 +2194,12 @@
return;
}
+ // IsEHa: emit an invoke _seh_try_end() to mark end of FT flow
+ if (getLangOpts().EHAsynch && Builder.GetInsertBlock()) {
+ llvm::FunctionCallee SehTryEnd = getSehTryEndFn(CGM);
+ EmitRuntimeCallOrInvoke(SehTryEnd);
+ }
+
// Otherwise, we must have an __except block.
const SEHExceptStmt *Except = S.getExceptHandler();
assert(Except && "__try must have __finally xor __except");
diff --git a/src/llvm-project/clang/lib/CodeGen/CGExpr.cpp b/src/llvm-project/clang/lib/CodeGen/CGExpr.cpp
index a3f9044..bf514aa 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGExpr.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGExpr.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGCall.h"
#include "CGCleanup.h"
@@ -37,6 +38,7 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Transforms/Utils/SanitizerStats.h"
#include <string>
@@ -198,7 +200,7 @@
/// EmitIgnoredExpr - Emit code to compute the specified expression,
/// ignoring the result.
void CodeGenFunction::EmitIgnoredExpr(const Expr *E) {
- if (E->isRValue())
+ if (E->isPRValue())
return (void) EmitAnyExpr(E, AggValueSlot::ignored(), true);
// Just emit it as an l-value and drop the result.
@@ -402,24 +404,22 @@
(Ty->isArrayType() || Ty->isRecordType()) &&
CGF.CGM.isTypeConstant(Ty, true))
if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) {
- if (auto AddrSpace = CGF.getTarget().getConstantAddressSpace()) {
- auto AS = AddrSpace.getValue();
- auto *GV = new llvm::GlobalVariable(
- CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
- llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp", nullptr,
- llvm::GlobalValue::NotThreadLocal,
- CGF.getContext().getTargetAddressSpace(AS));
- CharUnits alignment = CGF.getContext().getTypeAlignInChars(Ty);
- GV->setAlignment(alignment.getAsAlign());
- llvm::Constant *C = GV;
- if (AS != LangAS::Default)
- C = TCG.performAddrSpaceCast(
- CGF.CGM, GV, AS, LangAS::Default,
- GV->getValueType()->getPointerTo(
- CGF.getContext().getTargetAddressSpace(LangAS::Default)));
- // FIXME: Should we put the new global into a COMDAT?
- return Address(C, alignment);
- }
+ auto AS = CGF.CGM.GetGlobalConstantAddressSpace();
+ auto *GV = new llvm::GlobalVariable(
+ CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage, Init, ".ref.tmp", nullptr,
+ llvm::GlobalValue::NotThreadLocal,
+ CGF.getContext().getTargetAddressSpace(AS));
+ CharUnits alignment = CGF.getContext().getTypeAlignInChars(Ty);
+ GV->setAlignment(alignment.getAsAlign());
+ llvm::Constant *C = GV;
+ if (AS != LangAS::Default)
+ C = TCG.performAddrSpaceCast(
+ CGF.CGM, GV, AS, LangAS::Default,
+ GV->getValueType()->getPointerTo(
+ CGF.getContext().getTargetAddressSpace(LangAS::Default)));
+ // FIXME: Should we put the new global into a COMDAT?
+ return Address(C, alignment);
}
return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca);
}
@@ -826,9 +826,9 @@
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty.getUnqualifiedType(),
Out);
- // Blacklist based on the mangled type.
- if (!CGM.getContext().getSanitizerBlacklist().isBlacklistedType(
- SanitizerKind::Vptr, Out.str())) {
+ // Contained in NoSanitizeList based on the mangled type.
+ if (!CGM.getContext().getNoSanitizeList().containsType(SanitizerKind::Vptr,
+ Out.str())) {
llvm::hash_code TypeHash = hash_value(Out.str());
// Load the vptr, and compute hash_16_bytes(TypeHash, vptr).
@@ -850,9 +850,9 @@
llvm::ConstantInt::get(IntPtrTy,
CacheSize-1));
llvm::Value *Indices[] = { Builder.getInt32(0), Slot };
- llvm::Value *CacheVal =
- Builder.CreateAlignedLoad(Builder.CreateInBoundsGEP(Cache, Indices),
- getPointerAlign());
+ llvm::Value *CacheVal = Builder.CreateAlignedLoad(
+ IntPtrTy, Builder.CreateInBoundsGEP(HashTable, Cache, Indices),
+ getPointerAlign());
// If the hash isn't in the cache, call a runtime handler to perform the
// hard work of checking whether the vptr is for an object of the right
@@ -2832,8 +2832,21 @@
return LV;
}
- if (const auto *FD = dyn_cast<FunctionDecl>(ND))
- return EmitFunctionDeclLValue(*this, E, FD);
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
+ LValue LV = EmitFunctionDeclLValue(*this, E, FD);
+
+ // Emit debuginfo for the function declaration if the target wants to.
+ if (getContext().getTargetInfo().allowDebugInfoForExternalRef()) {
+ if (CGDebugInfo *DI = CGM.getModuleDebugInfo()) {
+ auto *Fn =
+ cast<llvm::Function>(LV.getPointer(*this)->stripPointerCasts());
+ if (!Fn->getSubprogram())
+ DI->EmitFunctionDecl(FD, FD->getLocation(), T, Fn);
+ }
+ }
+
+ return LV;
+ }
// FIXME: While we're emitting a binding from an enclosing scope, all other
// DeclRefExprs we see should be implicitly treated as if they also refer to
@@ -3382,14 +3395,14 @@
llvm::FunctionType::get(VoidTy, {VoidPtrTy, VoidPtrTy}, false),
llvm::GlobalValue::WeakODRLinkage, "__cfi_check_fail", &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
F->setVisibility(llvm::GlobalValue::HiddenVisibility);
StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args,
SourceLocation());
- // This function should not be affected by blacklist. This function does
+ // This function is not affected by NoSanitizeList. This function does
// not have a source location, but "src:*" would still apply. Revert any
// changes to SanOpts made in StartFunction.
SanOpts = CGM.getLangOpts().Sanitize;
@@ -3567,6 +3580,7 @@
}
static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF,
+ llvm::Type *elemType,
llvm::Value *ptr,
ArrayRef<llvm::Value*> indices,
bool inbounds,
@@ -3578,7 +3592,7 @@
CodeGenFunction::NotSubtraction, loc,
name);
} else {
- return CGF.Builder.CreateGEP(ptr, indices, name);
+ return CGF.Builder.CreateGEP(elemType, ptr, indices, name);
}
}
@@ -3672,8 +3686,8 @@
if (!LastIndex ||
(!CGF.IsInPreservedAIRegion && !IsPreserveAIArrayBase(CGF, Base))) {
eltPtr = emitArraySubscriptGEP(
- CGF, addr.getPointer(), indices, inbounds, signedIndices,
- loc, name);
+ CGF, addr.getElementType(), addr.getPointer(), indices, inbounds,
+ signedIndices, loc, name);
} else {
// Remember the original array subscript for bpf target
unsigned idx = LastIndex->getZExtValue();
@@ -3798,8 +3812,8 @@
CharUnits EltAlign =
getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize);
llvm::Value *EltPtr =
- emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false,
- SignedIndices, E->getExprLoc());
+ emitArraySubscriptGEP(*this, Addr.getElementType(), Addr.getPointer(),
+ ScaledIdx, false, SignedIndices, E->getExprLoc());
Addr = Address(EltPtr, EltAlign);
// Cast back.
@@ -4171,8 +4185,10 @@
/// Given that we are currently emitting a lambda, emit an l-value for
/// one of its members.
LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) {
- assert(cast<CXXMethodDecl>(CurCodeDecl)->getParent()->isLambda());
- assert(cast<CXXMethodDecl>(CurCodeDecl)->getParent() == Field->getParent());
+ if (CurCodeDecl) {
+ assert(cast<CXXMethodDecl>(CurCodeDecl)->getParent()->isLambda());
+ assert(cast<CXXMethodDecl>(CurCodeDecl)->getParent() == Field->getParent());
+ }
QualType LambdaTagType =
getContext().getTagDeclType(Field->getParent());
LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue, LambdaTagType);
@@ -4643,6 +4659,7 @@
case CK_FixedPointToBoolean:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
case CK_Dependent:
@@ -4871,8 +4888,12 @@
return CGCallee::forBuiltin(builtinID, FD);
}
- llvm::Constant *calleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
- return CGCallee::forDirect(calleePtr, GD);
+ llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD);
+ if (CGF.CGM.getLangOpts().CUDA && !CGF.CGM.getLangOpts().CUDAIsDevice &&
+ FD->hasAttr<CUDAGlobalAttr>())
+ CalleePtr = CGF.CGM.getCUDARuntime().getKernelStub(
+ cast<llvm::GlobalValue>(CalleePtr->stripPointerCasts()));
+ return CGCallee::forDirect(CalleePtr, GD);
}
CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
@@ -5123,9 +5144,9 @@
getContext().getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
llvm::Constant *FTRTTIConst =
CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true);
- llvm::Type *PrefixStructTyElems[] = {PrefixSig->getType(), Int32Ty};
+ llvm::Type *PrefixSigType = PrefixSig->getType();
llvm::StructType *PrefixStructTy = llvm::StructType::get(
- CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true);
+ CGM.getLLVMContext(), {PrefixSigType, Int32Ty}, /*isPacked=*/true);
llvm::Value *CalleePtr = Callee.getFunctionPointer();
@@ -5134,7 +5155,7 @@
llvm::Value *CalleeSigPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0);
llvm::Value *CalleeSig =
- Builder.CreateAlignedLoad(CalleeSigPtr, getIntAlign());
+ Builder.CreateAlignedLoad(PrefixSigType, CalleeSigPtr, getIntAlign());
llvm::Value *CalleeSigMatch = Builder.CreateICmpEQ(CalleeSig, PrefixSig);
llvm::BasicBlock *Cont = createBasicBlock("cont");
@@ -5145,7 +5166,7 @@
llvm::Value *CalleeRTTIPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1);
llvm::Value *CalleeRTTIEncoded =
- Builder.CreateAlignedLoad(CalleeRTTIPtr, getPointerAlign());
+ Builder.CreateAlignedLoad(Int32Ty, CalleeRTTIPtr, getPointerAlign());
llvm::Value *CalleeRTTI =
DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded);
llvm::Value *CalleeRTTIMatch =
@@ -5266,9 +5287,21 @@
Callee.setFunctionPointer(CalleePtr);
}
+ // HIP function pointer contains kernel handle when it is used in triple
+ // chevron. The kernel stub needs to be loaded from kernel handle and used
+ // as callee.
+ if (CGM.getLangOpts().HIP && !CGM.getLangOpts().CUDAIsDevice &&
+ isa<CUDAKernelCallExpr>(E) &&
+ (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
+ llvm::Value *Handle = Callee.getFunctionPointer();
+ auto *Cast =
+ Builder.CreateBitCast(Handle, Handle->getType()->getPointerTo());
+ auto *Stub = Builder.CreateLoad(Address(Cast, CGM.getPointerAlign()));
+ Callee.setFunctionPointer(Stub);
+ }
llvm::CallBase *CallOrInvoke = nullptr;
RValue Call = EmitCall(FnInfo, Callee, ReturnValue, Args, &CallOrInvoke,
- E->getExprLoc());
+ E == MustTailCall, E->getExprLoc());
// Generate function declaration DISuprogram in order to be used
// in debug info about call sites.
@@ -5365,7 +5398,7 @@
// directly into the slot.
typedef CodeGenFunction::OpaqueValueMappingData OVMA;
OVMA opaqueData;
- if (ov == resultExpr && ov->isRValue() && !forLValue &&
+ if (ov == resultExpr && ov->isPRValue() && !forLValue &&
CodeGenFunction::hasAggregateEvaluationKind(ov->getType())) {
CGF.EmitAggExpr(ov->getSourceExpr(), slot);
LValue LV = CGF.MakeAddrLValue(slot.getAddress(), ov->getType(),
diff --git a/src/llvm-project/clang/lib/CodeGen/CGExprAgg.cpp b/src/llvm-project/clang/lib/CodeGen/CGExprAgg.cpp
index f3ab915..1e81ad9 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGExprAgg.cpp
@@ -276,7 +276,7 @@
RetAddr = Dest.getAddress();
} else {
RetAddr = CGF.CreateMemTemp(RetTy, "tmp", &RetAllocaAddr);
- uint64_t Size =
+ llvm::TypeSize Size =
CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy));
LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAllocaAddr.getPointer());
if (LifetimeSizePtr) {
@@ -417,8 +417,8 @@
LValue Start = CGF.EmitLValueForFieldInitialization(DestLV, *Field);
llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0);
llvm::Value *IdxStart[] = { Zero, Zero };
- llvm::Value *ArrayStart =
- Builder.CreateInBoundsGEP(ArrayPtr.getPointer(), IdxStart, "arraystart");
+ llvm::Value *ArrayStart = Builder.CreateInBoundsGEP(
+ ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxStart, "arraystart");
CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start);
++Field;
@@ -434,8 +434,8 @@
ArrayType->getElementType())) {
// End pointer.
llvm::Value *IdxEnd[] = { Zero, Size };
- llvm::Value *ArrayEnd =
- Builder.CreateInBoundsGEP(ArrayPtr.getPointer(), IdxEnd, "arrayend");
+ llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP(
+ ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxEnd, "arrayend");
CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength);
} else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) {
// Length.
@@ -484,12 +484,14 @@
// down a level.
llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
llvm::Value *indices[] = { zero, zero };
- llvm::Value *begin =
- Builder.CreateInBoundsGEP(DestPtr.getPointer(), indices, "arrayinit.begin");
+ llvm::Value *begin = Builder.CreateInBoundsGEP(
+ DestPtr.getElementType(), DestPtr.getPointer(), indices,
+ "arrayinit.begin");
CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
CharUnits elementAlign =
DestPtr.getAlignment().alignmentOfArrayElement(elementSize);
+ llvm::Type *llvmElementType = begin->getType()->getPointerElementType();
// Consider initializing the array by copying from a global. For this to be
// more efficient than per-element initialization, the size of the elements
@@ -552,7 +554,8 @@
for (uint64_t i = 0; i != NumInitElements; ++i) {
// Advance to the next element.
if (i > 0) {
- element = Builder.CreateInBoundsGEP(element, one, "arrayinit.element");
+ element = Builder.CreateInBoundsGEP(
+ llvmElementType, element, one, "arrayinit.element");
// Tell the cleanup that it needs to destroy up to this
// element. TODO: some of these stores can be trivially
@@ -581,14 +584,15 @@
// Advance to the start of the rest of the array.
if (NumInitElements) {
- element = Builder.CreateInBoundsGEP(element, one, "arrayinit.start");
+ element = Builder.CreateInBoundsGEP(
+ llvmElementType, element, one, "arrayinit.start");
if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit);
}
// Compute the end of the array.
- llvm::Value *end = Builder.CreateInBoundsGEP(begin,
- llvm::ConstantInt::get(CGF.SizeTy, NumArrayElements),
- "arrayinit.end");
+ llvm::Value *end = Builder.CreateInBoundsGEP(
+ llvmElementType, begin,
+ llvm::ConstantInt::get(CGF.SizeTy, NumArrayElements), "arrayinit.end");
llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body");
@@ -616,8 +620,8 @@
}
// Move on to the next element.
- llvm::Value *nextElement =
- Builder.CreateInBoundsGEP(currentElement, one, "arrayinit.next");
+ llvm::Value *nextElement = Builder.CreateInBoundsGEP(
+ llvmElementType, currentElement, one, "arrayinit.next");
// Tell the EH cleanup that we finished with the last element.
if (endOfInit.isValid()) Builder.CreateStore(nextElement, endOfInit);
@@ -901,6 +905,7 @@
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLOpaqueType:
+ case CK_MatrixCast:
case CK_IntToOCLSampler:
case CK_FloatingToFixedPoint:
@@ -1422,6 +1427,7 @@
case CK_PointerToIntegral:
// Language extensions.
case CK_VectorSplat:
+ case CK_MatrixCast:
case CK_NonAtomicToAtomic:
case CK_AtomicToNonAtomic:
return true;
@@ -1777,8 +1783,9 @@
// destPtr is an array*. Construct an elementType* by drilling down a level.
llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
llvm::Value *indices[] = {zero, zero};
- llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getPointer(), indices,
- "arrayinit.begin");
+ llvm::Value *begin = Builder.CreateInBoundsGEP(
+ destPtr.getElementType(), destPtr.getPointer(), indices,
+ "arrayinit.begin");
// Prepare to special-case multidimensional array initialization: we avoid
// emitting multiple destructor loops in that case.
@@ -1800,7 +1807,8 @@
llvm::PHINode *index =
Builder.CreatePHI(zero->getType(), 2, "arrayinit.index");
index->addIncoming(zero, entryBB);
- llvm::Value *element = Builder.CreateInBoundsGEP(begin, index);
+ llvm::Value *element = Builder.CreateInBoundsGEP(
+ begin->getType()->getPointerElementType(), begin, index);
// Prepare for a cleanup.
QualType::DestructionKind dtorKind = elementType.isDestructedType();
diff --git a/src/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp b/src/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp
index e1907a6..96cf977 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGExprCXX.cpp
@@ -87,6 +87,7 @@
auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(
Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize);
return EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr,
+ CE && CE == MustTailCall,
CE ? CE->getExprLoc() : SourceLocation());
}
@@ -112,7 +113,7 @@
commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam,
ImplicitParamTy, CE, Args, nullptr);
return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee,
- ReturnValueSlot(), Args, nullptr,
+ ReturnValueSlot(), Args, nullptr, CE && CE == MustTailCall,
CE ? CE->getExprLoc() : SourceLocation{});
}
@@ -472,7 +473,8 @@
EmitCallArgs(Args, FPT, E->arguments());
return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required,
/*PrefixSize=*/0),
- Callee, ReturnValue, Args, nullptr, E->getExprLoc());
+ Callee, ReturnValue, Args, nullptr, E == MustTailCall,
+ E->getExprLoc());
}
RValue
@@ -1048,7 +1050,8 @@
cast<ConstantArrayType>(ILE->getType()->getAsArrayTypeUnsafe())
->getSize().getZExtValue();
CurPtr =
- Address(Builder.CreateInBoundsGEP(CurPtr.getPointer(),
+ Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(),
+ CurPtr.getPointer(),
Builder.getSize(InitListElements),
"string.init.end"),
CurPtr.getAlignment().alignmentAtOffset(InitListElements *
@@ -1107,7 +1110,8 @@
StoreAnyExprIntoOneUnit(*this, ILE->getInit(i),
ILE->getInit(i)->getType(), CurPtr,
AggValueSlot::DoesNotOverlap);
- CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getPointer(),
+ CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(),
+ CurPtr.getPointer(),
Builder.getSize(1),
"array.exp.next"),
StartAlign.alignmentAtOffset((i + 1) * ElementSize));
@@ -1226,7 +1230,8 @@
// Find the end of the array, hoisted out of the loop.
llvm::Value *EndPtr =
- Builder.CreateInBoundsGEP(BeginPtr.getPointer(), NumElements, "array.end");
+ Builder.CreateInBoundsGEP(BeginPtr.getElementType(), BeginPtr.getPointer(),
+ NumElements, "array.end");
// If the number of elements isn't constant, we have to now check if there is
// anything left to initialize.
@@ -2034,8 +2039,8 @@
deletedPtr.getAlignment().alignmentOfArrayElement(elementSize);
llvm::Value *arrayBegin = deletedPtr.getPointer();
- llvm::Value *arrayEnd =
- CGF.Builder.CreateInBoundsGEP(arrayBegin, numElements, "delete.end");
+ llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP(
+ deletedPtr.getElementType(), arrayBegin, numElements, "delete.end");
// Note that it is legal to allocate a zero-length array, and we
// can never fold the check away because the length should always
@@ -2098,7 +2103,8 @@
GEP.push_back(Zero);
}
- Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getPointer(), GEP, "del.first"),
+ Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getElementType(),
+ Ptr.getPointer(), GEP, "del.first"),
Ptr.getAlignment());
}
diff --git a/src/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp b/src/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
index 6b6b901..5409e82 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
@@ -533,6 +533,7 @@
case CK_FixedPointToBoolean:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
llvm_unreachable("invalid cast kind for complex value");
case CK_FloatingRealToComplex:
diff --git a/src/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp b/src/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp
index 497f9c0..7340241 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1170,6 +1170,7 @@
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
case CK_ZeroToOCLOpaqueType:
+ case CK_MatrixCast:
return nullptr;
}
llvm_unreachable("Invalid CastKind");
diff --git a/src/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp b/src/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp
index 6f7e826..418f23b 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGExprScalar.cpp
@@ -348,6 +348,9 @@
EmitImplicitIntegerSignChangeChecks(
SanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {}
};
+ Value *EmitScalarCast(Value *Src, QualType SrcType, QualType DstType,
+ llvm::Type *SrcTy, llvm::Type *DstTy,
+ ScalarConversionOpts Opts);
Value *
EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy,
SourceLocation Loc,
@@ -483,6 +486,8 @@
return CGF.EmitPseudoObjectRValue(E).getScalarVal();
}
+ Value *VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *E);
+
Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) {
if (E->isGLValue())
return EmitLoadOfLValue(CGF.getOrCreateOpaqueLValueMapping(E),
@@ -729,6 +734,7 @@
BO->getLHS()->getType().getCanonicalType());
auto *RHSMatTy = dyn_cast<ConstantMatrixType>(
BO->getRHS()->getType().getCanonicalType());
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Ops.FPFeatures);
if (LHSMatTy && RHSMatTy)
return MB.CreateMatrixMultiply(Ops.LHS, Ops.RHS, LHSMatTy->getNumRows(),
LHSMatTy->getNumColumns(),
@@ -1191,6 +1197,54 @@
{Src, Dst});
}
+Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType,
+ QualType DstType, llvm::Type *SrcTy,
+ llvm::Type *DstTy,
+ ScalarConversionOpts Opts) {
+ // The Element types determine the type of cast to perform.
+ llvm::Type *SrcElementTy;
+ llvm::Type *DstElementTy;
+ QualType SrcElementType;
+ QualType DstElementType;
+ if (SrcType->isMatrixType() && DstType->isMatrixType()) {
+ SrcElementTy = cast<llvm::VectorType>(SrcTy)->getElementType();
+ DstElementTy = cast<llvm::VectorType>(DstTy)->getElementType();
+ SrcElementType = SrcType->castAs<MatrixType>()->getElementType();
+ DstElementType = DstType->castAs<MatrixType>()->getElementType();
+ } else {
+ assert(!SrcType->isMatrixType() && !DstType->isMatrixType() &&
+ "cannot cast between matrix and non-matrix types");
+ SrcElementTy = SrcTy;
+ DstElementTy = DstTy;
+ SrcElementType = SrcType;
+ DstElementType = DstType;
+ }
+
+ if (isa<llvm::IntegerType>(SrcElementTy)) {
+ bool InputSigned = SrcElementType->isSignedIntegerOrEnumerationType();
+ if (SrcElementType->isBooleanType() && Opts.TreatBooleanAsSigned) {
+ InputSigned = true;
+ }
+
+ if (isa<llvm::IntegerType>(DstElementTy))
+ return Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
+ if (InputSigned)
+ return Builder.CreateSIToFP(Src, DstTy, "conv");
+ return Builder.CreateUIToFP(Src, DstTy, "conv");
+ }
+
+ if (isa<llvm::IntegerType>(DstElementTy)) {
+ assert(SrcElementTy->isFloatingPointTy() && "Unknown real conversion");
+ if (DstElementType->isSignedIntegerOrEnumerationType())
+ return Builder.CreateFPToSI(Src, DstTy, "conv");
+ return Builder.CreateFPToUI(Src, DstTy, "conv");
+ }
+
+ if (DstElementTy->getTypeID() < SrcElementTy->getTypeID())
+ return Builder.CreateFPTrunc(Src, DstTy, "conv");
+ return Builder.CreateFPExt(Src, DstTy, "conv");
+}
+
/// Emit a conversion from the specified type to the specified destination type,
/// both of which are LLVM scalar types.
Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
@@ -1318,6 +1372,9 @@
return Builder.CreateVectorSplat(NumElements, Src, "splat");
}
+ if (SrcType->isMatrixType() && DstType->isMatrixType())
+ return EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
+
if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) {
// Allow bitcast from vector to integer/fp of the same size.
unsigned SrcSize = SrcTy->getPrimitiveSizeInBits();
@@ -1384,31 +1441,7 @@
DstTy = CGF.FloatTy;
}
- if (isa<llvm::IntegerType>(SrcTy)) {
- bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
- if (SrcType->isBooleanType() && Opts.TreatBooleanAsSigned) {
- InputSigned = true;
- }
- if (isa<llvm::IntegerType>(DstTy))
- Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv");
- else if (InputSigned)
- Res = Builder.CreateSIToFP(Src, DstTy, "conv");
- else
- Res = Builder.CreateUIToFP(Src, DstTy, "conv");
- } else if (isa<llvm::IntegerType>(DstTy)) {
- assert(SrcTy->isFloatingPointTy() && "Unknown real conversion");
- if (DstType->isSignedIntegerOrEnumerationType())
- Res = Builder.CreateFPToSI(Src, DstTy, "conv");
- else
- Res = Builder.CreateFPToUI(Src, DstTy, "conv");
- } else {
- assert(SrcTy->isFloatingPointTy() && DstTy->isFloatingPointTy() &&
- "Unknown real conversion");
- if (DstTy->getTypeID() < SrcTy->getTypeID())
- Res = Builder.CreateFPTrunc(Src, DstTy, "conv");
- else
- Res = Builder.CreateFPExt(Src, DstTy, "conv");
- }
+ Res = EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts);
if (DstTy != ResTy) {
if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
@@ -1550,6 +1583,25 @@
return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
}
+Value *
+ScalarExprEmitter::VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *E) {
+ ASTContext &Context = CGF.getContext();
+ llvm::Optional<LangAS> GlobalAS =
+ Context.getTargetInfo().getConstantAddressSpace();
+ llvm::Constant *GlobalConstStr = Builder.CreateGlobalStringPtr(
+ E->ComputeName(Context), "__usn_str",
+ static_cast<unsigned>(GlobalAS.getValueOr(LangAS::Default)));
+
+ unsigned ExprAS = Context.getTargetAddressSpace(E->getType());
+
+ if (GlobalConstStr->getType()->getPointerAddressSpace() == ExprAS)
+ return GlobalConstStr;
+
+ llvm::Type *EltTy = GlobalConstStr->getType()->getPointerElementType();
+ llvm::PointerType *NewPtrTy = llvm::PointerType::get(EltTy, ExprAS);
+ return Builder.CreateAddrSpaceCast(GlobalConstStr, NewPtrTy, "usn_addr_cast");
+}
+
Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
// Vector Mask Case
if (E->getNumSubExprs() == 2) {
@@ -1729,7 +1781,7 @@
llvm::MatrixBuilder<CGBuilderTy> MB(Builder);
return MB.CreateExtractElement(
Matrix, RowIdx, ColumnIdx,
- E->getBase()->getType()->getAs<ConstantMatrixType>()->getNumRows());
+ E->getBase()->getType()->castAs<ConstantMatrixType>()->getNumRows());
}
static int getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx,
@@ -1913,7 +1965,7 @@
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(CE)) {
// And that glvalue casts are never null.
- if (ICE->getValueKind() != VK_RValue)
+ if (ICE->isGLValue())
return false;
}
@@ -2043,24 +2095,11 @@
isa<llvm::ScalableVectorType>(DstTy)) ||
(isa<llvm::ScalableVectorType>(SrcTy) &&
isa<llvm::FixedVectorType>(DstTy))) {
- if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
- // Call expressions can't have a scalar return unless the return type
- // is a reference type so an lvalue can't be emitted. Create a temp
- // alloca to store the call, bitcast the address then load.
- QualType RetTy = CE->getCallReturnType(CGF.getContext());
- Address Addr =
- CGF.CreateDefaultAlignTempAlloca(SrcTy, "saved-call-rvalue");
- LValue LV = CGF.MakeAddrLValue(Addr, RetTy);
- CGF.EmitStoreOfScalar(Src, LV);
- Addr = Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(DestTy),
- "castFixedSve");
- LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
- DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
- return EmitLoadOfLValue(DestLV, CE->getExprLoc());
- }
-
- Address Addr = EmitLValue(E).getAddress(CGF);
- Addr = Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(DestTy));
+ Address Addr = CGF.CreateDefaultAlignTempAlloca(SrcTy, "saved-value");
+ LValue LV = CGF.MakeAddrLValue(Addr, E->getType());
+ CGF.EmitStoreOfScalar(Src, LV);
+ Addr = Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(DestTy),
+ "castFixedSve");
LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
return EmitLoadOfLValue(DestLV, CE->getExprLoc());
@@ -2230,6 +2269,10 @@
CGF.EmitIgnoredExpr(E);
return nullptr;
}
+ case CK_MatrixCast: {
+ return EmitScalarConversion(Visit(E), E->getType(), DestTy,
+ CE->getExprLoc());
+ }
case CK_VectorSplat: {
llvm::Type *DstTy = ConvertType(DestTy);
Value *Elt = Visit(const_cast<Expr*>(E));
@@ -2545,7 +2588,8 @@
llvm::Value *numElts = CGF.getVLASize(vla).NumElts;
if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize");
if (CGF.getLangOpts().isSignedOverflowDefined())
- value = Builder.CreateGEP(value, numElts, "vla.inc");
+ value = Builder.CreateGEP(value->getType()->getPointerElementType(),
+ value, numElts, "vla.inc");
else
value = CGF.EmitCheckedInBoundsGEP(
value, numElts, /*SignedIndices=*/false, isSubtraction,
@@ -2557,7 +2601,7 @@
value = CGF.EmitCastToVoidPtr(value);
if (CGF.getLangOpts().isSignedOverflowDefined())
- value = Builder.CreateGEP(value, amt, "incdec.funcptr");
+ value = Builder.CreateGEP(CGF.Int8Ty, value, amt, "incdec.funcptr");
else
value = CGF.EmitCheckedInBoundsGEP(value, amt, /*SignedIndices=*/false,
isSubtraction, E->getExprLoc(),
@@ -2568,7 +2612,8 @@
} else {
llvm::Value *amt = Builder.getInt32(amount);
if (CGF.getLangOpts().isSignedOverflowDefined())
- value = Builder.CreateGEP(value, amt, "incdec.ptr");
+ value = Builder.CreateGEP(value->getType()->getPointerElementType(),
+ value, amt, "incdec.ptr");
else
value = CGF.EmitCheckedInBoundsGEP(value, amt, /*SignedIndices=*/false,
isSubtraction, E->getExprLoc(),
@@ -2677,7 +2722,7 @@
llvm::ConstantInt::get(CGF.SizeTy, size.getQuantity());
if (CGF.getLangOpts().isSignedOverflowDefined())
- value = Builder.CreateGEP(value, sizeValue, "incdec.objptr");
+ value = Builder.CreateGEP(CGF.Int8Ty, value, sizeValue, "incdec.objptr");
else
value = CGF.EmitCheckedInBoundsGEP(value, sizeValue,
/*SignedIndices=*/false, isSubtraction,
@@ -3125,7 +3170,7 @@
llvm::Value *IntMin =
Builder.getInt(llvm::APInt::getSignedMinValue(Ty->getBitWidth()));
- llvm::Value *NegOne = llvm::ConstantInt::get(Ty, -1ULL);
+ llvm::Value *NegOne = llvm::Constant::getAllOnesValue(Ty);
llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
@@ -3157,12 +3202,30 @@
}
}
+ if (Ops.Ty->isConstantMatrixType()) {
+ llvm::MatrixBuilder<CGBuilderTy> MB(Builder);
+ // We need to check the types of the operands of the operator to get the
+ // correct matrix dimensions.
+ auto *BO = cast<BinaryOperator>(Ops.E);
+ (void)BO;
+ assert(
+ isa<ConstantMatrixType>(BO->getLHS()->getType().getCanonicalType()) &&
+ "first operand must be a matrix");
+ assert(BO->getRHS()->getType().getCanonicalType()->isArithmeticType() &&
+ "second operand must be an arithmetic type");
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Ops.FPFeatures);
+ return MB.CreateScalarDiv(Ops.LHS, Ops.RHS,
+ Ops.Ty->hasUnsignedIntegerRepresentation());
+ }
+
if (Ops.LHS->getType()->isFPOrFPVectorTy()) {
llvm::Value *Val;
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Ops.FPFeatures);
Val = Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
- if (CGF.getLangOpts().OpenCL &&
- !CGF.CGM.getCodeGenOpts().CorrectlyRoundedDivSqrt) {
+ if ((CGF.getLangOpts().OpenCL &&
+ !CGF.CGM.getCodeGenOpts().OpenCLCorrectlyRoundedDivSqrt) ||
+ (CGF.getLangOpts().HIP && CGF.getLangOpts().CUDAIsDevice &&
+ !CGF.CGM.getCodeGenOpts().HIPCorrectlyRoundedDivSqrt)) {
// OpenCL v1.1 s7.4: minimum accuracy of single precision / is 2.5ulp
// OpenCL v1.2 s5.6.4.2: The -cl-fp32-correctly-rounded-divide-sqrt
// build option allows an application to specify that single precision
@@ -3384,7 +3447,7 @@
index = CGF.Builder.CreateMul(index, objectSize);
Value *result = CGF.Builder.CreateBitCast(pointer, CGF.VoidPtrTy);
- result = CGF.Builder.CreateGEP(result, index, "add.ptr");
+ result = CGF.Builder.CreateGEP(CGF.Int8Ty, result, index, "add.ptr");
return CGF.Builder.CreateBitCast(result, pointer->getType());
}
@@ -3400,7 +3463,9 @@
// multiply. We suppress this if overflow is not undefined behavior.
if (CGF.getLangOpts().isSignedOverflowDefined()) {
index = CGF.Builder.CreateMul(index, numElements, "vla.index");
- pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr");
+ pointer = CGF.Builder.CreateGEP(
+ pointer->getType()->getPointerElementType(), pointer, index,
+ "add.ptr");
} else {
index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index");
pointer =
@@ -3415,12 +3480,13 @@
// future proof.
if (elementType->isVoidType() || elementType->isFunctionType()) {
Value *result = CGF.EmitCastToVoidPtr(pointer);
- result = CGF.Builder.CreateGEP(result, index, "add.ptr");
+ result = CGF.Builder.CreateGEP(CGF.Int8Ty, result, index, "add.ptr");
return CGF.Builder.CreateBitCast(result, pointer->getType());
}
if (CGF.getLangOpts().isSignedOverflowDefined())
- return CGF.Builder.CreateGEP(pointer, index, "add.ptr");
+ return CGF.Builder.CreateGEP(
+ pointer->getType()->getPointerElementType(), pointer, index, "add.ptr");
return CGF.EmitCheckedInBoundsGEP(pointer, index, isSigned, isSubtraction,
op.E->getExprLoc(), "add.ptr");
@@ -3532,6 +3598,7 @@
if (op.Ty->isConstantMatrixType()) {
llvm::MatrixBuilder<CGBuilderTy> MB(Builder);
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, op.FPFeatures);
return MB.CreateAdd(op.LHS, op.RHS);
}
@@ -3681,6 +3748,7 @@
if (op.Ty->isConstantMatrixType()) {
llvm::MatrixBuilder<CGBuilderTy> MB(Builder);
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, op.FPFeatures);
return MB.CreateSub(op.LHS, op.RHS);
}
@@ -4778,7 +4846,7 @@
Expr *BaseExpr = E->getBase();
Address Addr = Address::invalid();
- if (BaseExpr->isRValue()) {
+ if (BaseExpr->isPRValue()) {
Addr = Address(EmitScalarExpr(BaseExpr), getPointerAlign());
} else {
Addr = EmitLValue(BaseExpr).getAddress(*this);
@@ -4950,14 +5018,14 @@
CodeGenFunction::EmitCheckedInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList,
bool SignedIndices, bool IsSubtraction,
SourceLocation Loc, const Twine &Name) {
- Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name);
+ llvm::Type *PtrTy = Ptr->getType();
+ Value *GEPVal = Builder.CreateInBoundsGEP(
+ PtrTy->getPointerElementType(), Ptr, IdxList, Name);
// If the pointer overflow sanitizer isn't enabled, do nothing.
if (!SanOpts.has(SanitizerKind::PointerOverflow))
return GEPVal;
- llvm::Type *PtrTy = Ptr->getType();
-
// Perform nullptr-and-offset check unless the nullptr is defined.
bool PerformNullCheck = !NullPointerIsDefined(
Builder.GetInsertBlock()->getParent(), PtrTy->getPointerAddressSpace());
diff --git a/src/llvm-project/clang/lib/CodeGen/CGLoopInfo.cpp b/src/llvm-project/clang/lib/CodeGen/CGLoopInfo.cpp
index 8ba4059..12a6cd8 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -250,12 +250,10 @@
Args.push_back(nullptr);
Args.append(LoopProperties.begin(), LoopProperties.end());
- // Setting vectorize.predicate
+ // Setting vectorize.predicate when it has been specified and vectorization
+ // has not been disabled.
bool IsVectorPredicateEnabled = false;
- if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified &&
- Attrs.VectorizeEnable != LoopAttributes::Disable &&
- Attrs.VectorizeWidth < 1) {
-
+ if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified) {
IsVectorPredicateEnabled =
(Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
@@ -303,7 +301,8 @@
// explicitly requested fixed-width vectorization, i.e.
// vectorize.scalable.enable is false.
if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
- IsVectorPredicateEnabled || Attrs.VectorizeWidth > 1 ||
+ (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||
+ Attrs.VectorizeWidth > 1 ||
Attrs.VectorizeScalable == LoopAttributes::Enable ||
(Attrs.VectorizeScalable == LoopAttributes::Disable &&
Attrs.VectorizeWidth != 1)) {
diff --git a/src/llvm-project/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/src/llvm-project/clang/lib/CodeGen/CGNonTrivialStruct.cpp
index d134be8..ad505fc 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGNonTrivialStruct.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGNonTrivialStruct.cpp
@@ -368,7 +368,7 @@
CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts);
Address BC = CGF.Builder.CreateBitCast(DstAddr, CGF.CGM.Int8PtrTy);
llvm::Value *DstArrayEnd =
- CGF.Builder.CreateInBoundsGEP(BC.getPointer(), SizeInBytes);
+ CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, BC.getPointer(), SizeInBytes);
DstArrayEnd = CGF.Builder.CreateBitCast(DstArrayEnd, CGF.CGM.Int8PtrPtrTy,
"dstarray.end");
llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock();
@@ -470,16 +470,12 @@
llvm::Function::Create(FuncTy, llvm::GlobalValue::LinkOnceODRLinkage,
FuncName, &CGM.getModule());
F->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
- IdentifierInfo *II = &Ctx.Idents.get(FuncName);
- FunctionDecl *FD = FunctionDecl::Create(
- Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
- II, Ctx.getFunctionType(Ctx.VoidTy, llvm::None, {}), nullptr,
- SC_PrivateExtern, false, false);
CodeGenFunction NewCGF(CGM);
setCGF(&NewCGF);
- CGF->StartFunction(FD, Ctx.VoidTy, F, FI, Args);
+ CGF->StartFunction(GlobalDecl(), Ctx.VoidTy, F, FI, Args);
+ auto AL = ApplyDebugLocation::CreateArtificial(*CGF);
std::array<Address, N> Addrs =
getParamAddrs<N>(std::make_index_sequence<N>{}, Alignments, Args, CGF);
asDerived().visitStructFields(QT, CharUnits::Zero(), Addrs);
@@ -568,7 +564,7 @@
this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT);
SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
} else {
- llvm::PointerType *Ty = this->CGF->ConvertType(FT)->getPointerTo();
+ llvm::PointerType *Ty = this->CGF->ConvertTypeForMem(FT)->getPointerTo();
Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty);
Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty);
DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
diff --git a/src/llvm-project/clang/lib/CodeGen/CGObjC.cpp b/src/llvm-project/clang/lib/CodeGen/CGObjC.cpp
index 3f930c7..937a0e8 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGObjC.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGObjC.cpp
@@ -23,6 +23,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Analysis/ObjCARCUtil.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
@@ -759,7 +760,7 @@
const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD);
if (OMD->isDirectMethod()) {
Fn->setVisibility(llvm::Function::HiddenVisibility);
- CGM.SetLLVMFunctionAttributes(OMD, FI, Fn);
+ CGM.SetLLVMFunctionAttributes(OMD, FI, Fn, /*IsThunk=*/false);
CGM.SetLLVMFunctionAttributesForDefinition(OMD, Fn);
} else {
CGM.SetInternalFunctionAttributes(OMD, Fn, FI);
@@ -924,10 +925,11 @@
IvarSize = TInfo.Width;
IvarAlignment = TInfo.Align;
- // If we have a copy property, we always have to use getProperty/setProperty.
- // TODO: we could actually use setProperty and an expression for non-atomics.
+ // If we have a copy property, we always have to use setProperty.
+ // If the property is atomic we need to use getProperty, but in
+ // the nonatomic case we can just use expression.
if (IsCopy) {
- Kind = GetSetProperty;
+ Kind = IsAtomic ? GetSetProperty : SetPropertyAndExpressionGet;
return;
}
@@ -1521,7 +1523,7 @@
DeclRefExpr self(getContext(), selfDecl, false, selfDecl->getType(),
VK_LValue, SourceLocation());
ImplicitCastExpr selfLoad(ImplicitCastExpr::OnStack, selfDecl->getType(),
- CK_LValueToRValue, &self, VK_RValue,
+ CK_LValueToRValue, &self, VK_PRValue,
FPOptionsOverride());
ObjCIvarRefExpr ivarRef(ivar, ivar->getType().getNonReferenceType(),
SourceLocation(), SourceLocation(),
@@ -1533,7 +1535,7 @@
SourceLocation());
ImplicitCastExpr argLoad(ImplicitCastExpr::OnStack,
argType.getUnqualifiedType(), CK_LValueToRValue,
- &arg, VK_RValue, FPOptionsOverride());
+ &arg, VK_PRValue, FPOptionsOverride());
// The property type can differ from the ivar type in some situations with
// Objective-C pointer types, we can always bit cast the RHS in these cases.
@@ -1555,15 +1557,15 @@
argCK = CK_BitCast;
}
ImplicitCastExpr argCast(ImplicitCastExpr::OnStack, ivarRef.getType(), argCK,
- &argLoad, VK_RValue, FPOptionsOverride());
+ &argLoad, VK_PRValue, FPOptionsOverride());
Expr *finalArg = &argLoad;
if (!getContext().hasSameUnqualifiedType(ivarRef.getType(),
argLoad.getType()))
finalArg = &argCast;
BinaryOperator *assign = BinaryOperator::Create(
- getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(), VK_RValue,
- OK_Ordinary, SourceLocation(), FPOptionsOverride());
+ getContext(), &ivarRef, finalArg, BO_Assign, ivarRef.getType(),
+ VK_PRValue, OK_Ordinary, SourceLocation(), FPOptionsOverride());
EmitStmt(assign);
}
@@ -1818,9 +1820,10 @@
llvm::Value *StateMutationsPtr
= Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr");
+ llvm::Type *UnsignedLongTy = ConvertType(getContext().UnsignedLongTy);
llvm::Value *initialMutations =
- Builder.CreateAlignedLoad(StateMutationsPtr, getPointerAlign(),
- "forcoll.initial-mutations");
+ Builder.CreateAlignedLoad(UnsignedLongTy, StateMutationsPtr,
+ getPointerAlign(), "forcoll.initial-mutations");
// Start looping. This is the point we return to whenever we have a
// fresh, non-empty batch of objects.
@@ -1842,8 +1845,8 @@
// refreshes.
StateMutationsPtr = Builder.CreateLoad(StateMutationsPtrPtr, "mutationsptr");
llvm::Value *currentMutations
- = Builder.CreateAlignedLoad(StateMutationsPtr, getPointerAlign(),
- "statemutations");
+ = Builder.CreateAlignedLoad(UnsignedLongTy, StateMutationsPtr,
+ getPointerAlign(), "statemutations");
llvm::BasicBlock *WasMutatedBB = createBasicBlock("forcoll.mutated");
llvm::BasicBlock *WasNotMutatedBB = createBasicBlock("forcoll.notmutated");
@@ -1853,9 +1856,9 @@
// If so, call the enumeration-mutation function.
EmitBlock(WasMutatedBB);
+ llvm::Type *ObjCIdType = ConvertType(getContext().getObjCIdType());
llvm::Value *V =
- Builder.CreateBitCast(Collection,
- ConvertType(getContext().getObjCIdType()));
+ Builder.CreateBitCast(Collection, ObjCIdType);
CallArgList Args2;
Args2.add(RValue::get(V), getContext().getObjCIdType());
// FIXME: We shouldn't need to get the function info here, the runtime already
@@ -1901,10 +1904,11 @@
Builder.CreateLoad(StateItemsPtr, "stateitems");
// Fetch the value at the current index from the buffer.
- llvm::Value *CurrentItemPtr =
- Builder.CreateGEP(EnumStateItems, index, "currentitem.ptr");
+ llvm::Value *CurrentItemPtr = Builder.CreateGEP(
+ EnumStateItems->getType()->getPointerElementType(), EnumStateItems, index,
+ "currentitem.ptr");
llvm::Value *CurrentItem =
- Builder.CreateAlignedLoad(CurrentItemPtr, getPointerAlign());
+ Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign());
if (SanOpts.has(SanitizerKind::ObjCCast)) {
// Before using an item from the collection, check that the implicit cast
@@ -2078,6 +2082,15 @@
EmitNounwindRuntimeCall(fn, values);
}
+/// Emit a call to "clang.arc.noop.use", which consumes the result of a call
+/// that has operand bundle "clang.arc.attachedcall".
+void CodeGenFunction::EmitARCNoopIntrinsicUse(ArrayRef<llvm::Value *> values) {
+ llvm::Function *&fn = CGM.getObjCEntrypoints().clang_arc_noop_use;
+ if (!fn)
+ fn = CGM.getIntrinsic(llvm::Intrinsic::objc_clang_arc_noop_use);
+ EmitNounwindRuntimeCall(fn, values);
+}
+
static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM, llvm::Value *RTF) {
if (auto *F = dyn_cast<llvm::Function>(RTF)) {
// If the target runtime doesn't naturally support ARC, emit weak
@@ -2304,10 +2317,11 @@
// with this marker yet, so leave a breadcrumb for the ARC
// optimizer to pick up.
} else {
- const char *markerKey = "clang.arc.retainAutoreleasedReturnValueMarker";
- if (!CGF.CGM.getModule().getModuleFlag(markerKey)) {
+ const char *retainRVMarkerKey = llvm::objcarc::getRVMarkerModuleFlagStr();
+ if (!CGF.CGM.getModule().getModuleFlag(retainRVMarkerKey)) {
auto *str = llvm::MDString::get(CGF.getLLVMContext(), assembly);
- CGF.CGM.getModule().addModuleFlag(llvm::Module::Error, markerKey, str);
+ CGF.CGM.getModule().addModuleFlag(llvm::Module::Error,
+ retainRVMarkerKey, str);
}
}
}
@@ -2317,6 +2331,47 @@
CGF.Builder.CreateCall(marker, None, CGF.getBundlesForFunclet(marker));
}
+static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
+ bool IsRetainRV,
+ CodeGenFunction &CGF) {
+ emitAutoreleasedReturnValueMarker(CGF);
+
+ // Add operand bundle "clang.arc.attachedcall" to the call instead of emitting
+ // retainRV or claimRV calls in the IR. We currently do this only when the
+ // optimization level isn't -O0 since global-isel, which is currently run at
+ // -O0, doesn't know about the operand bundle.
+
+ // FIXME: Do this when the target isn't aarch64.
+ if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ CGF.CGM.getTarget().getTriple().isAArch64()) {
+ llvm::Value *bundleArgs[] = {llvm::ConstantInt::get(
+ CGF.Int64Ty,
+ llvm::objcarc::getAttachedCallOperandBundleEnum(IsRetainRV))};
+ llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs);
+ auto *oldCall = cast<llvm::CallBase>(value);
+ llvm::CallBase *newCall = llvm::CallBase::addOperandBundle(
+ oldCall, llvm::LLVMContext::OB_clang_arc_attachedcall, OB, oldCall);
+ newCall->copyMetadata(*oldCall);
+ oldCall->replaceAllUsesWith(newCall);
+ oldCall->eraseFromParent();
+ CGF.EmitARCNoopIntrinsicUse(newCall);
+ return newCall;
+ }
+
+ bool isNoTail =
+ CGF.CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail();
+ llvm::CallInst::TailCallKind tailKind =
+ isNoTail ? llvm::CallInst::TCK_NoTail : llvm::CallInst::TCK_None;
+ ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints();
+ llvm::Function *&EP = IsRetainRV
+ ? EPs.objc_retainAutoreleasedReturnValue
+ : EPs.objc_unsafeClaimAutoreleasedReturnValue;
+ llvm::Intrinsic::ID IID =
+ IsRetainRV ? llvm::Intrinsic::objc_retainAutoreleasedReturnValue
+ : llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue;
+ return emitARCValueOperation(CGF, value, nullptr, EP, IID, tailKind);
+}
+
/// Retain the given object which is the result of a function call.
/// call i8* \@objc_retainAutoreleasedReturnValue(i8* %value)
///
@@ -2324,15 +2379,7 @@
/// call with completely different semantics.
llvm::Value *
CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
- emitAutoreleasedReturnValueMarker(*this);
- llvm::CallInst::TailCallKind tailKind =
- CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail()
- ? llvm::CallInst::TCK_NoTail
- : llvm::CallInst::TCK_None;
- return emitARCValueOperation(
- *this, value, nullptr,
- CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,
- llvm::Intrinsic::objc_retainAutoreleasedReturnValue, tailKind);
+ return emitOptimizedARCReturnCall(value, true, *this);
}
/// Claim a possibly-autoreleased return value at +0. This is only
@@ -2344,15 +2391,7 @@
/// call i8* \@objc_unsafeClaimAutoreleasedReturnValue(i8* %value)
llvm::Value *
CodeGenFunction::EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value) {
- emitAutoreleasedReturnValueMarker(*this);
- llvm::CallInst::TailCallKind tailKind =
- CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail()
- ? llvm::CallInst::TCK_NoTail
- : llvm::CallInst::TCK_None;
- return emitARCValueOperation(
- *this, value, nullptr,
- CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue,
- llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue, tailKind);
+ return emitOptimizedARCReturnCall(value, false, *this);
}
/// Release the given object.
@@ -2902,8 +2941,12 @@
ValueTransform doAfterCall,
ValueTransform doFallback) {
CGBuilderTy::InsertPoint ip = CGF.Builder.saveIP();
+ auto *callBase = dyn_cast<llvm::CallBase>(value);
- if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(value)) {
+ if (callBase && llvm::objcarc::hasAttachedCallOpBundle(callBase)) {
+ // Fall back if the call base has operand bundle "clang.arc.attachedcall".
+ value = doFallback(CGF, value);
+ } else if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(value)) {
// Place the retain immediately following the call.
CGF.Builder.SetInsertPoint(call->getParent(),
++llvm::BasicBlock::iterator(call));
@@ -3657,12 +3700,18 @@
FunctionTy, nullptr, SC_Static, false, false);
FunctionArgList args;
- ImplicitParamDecl DstDecl(C, FD, SourceLocation(), /*Id=*/nullptr, DestTy,
- ImplicitParamDecl::Other);
- args.push_back(&DstDecl);
- ImplicitParamDecl SrcDecl(C, FD, SourceLocation(), /*Id=*/nullptr, SrcTy,
- ImplicitParamDecl::Other);
- args.push_back(&SrcDecl);
+ ParmVarDecl *Params[2];
+ ParmVarDecl *DstDecl = ParmVarDecl::Create(
+ C, FD, SourceLocation(), SourceLocation(), nullptr, DestTy,
+ C.getTrivialTypeSourceInfo(DestTy, SourceLocation()), SC_None,
+ /*DefArg=*/nullptr);
+ args.push_back(Params[0] = DstDecl);
+ ParmVarDecl *SrcDecl = ParmVarDecl::Create(
+ C, FD, SourceLocation(), SourceLocation(), nullptr, SrcTy,
+ C.getTrivialTypeSourceInfo(SrcTy, SourceLocation()), SC_None,
+ /*DefArg=*/nullptr);
+ args.push_back(Params[1] = SrcDecl);
+ FD->setParams(Params);
const CGFunctionInfo &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
@@ -3678,12 +3727,12 @@
StartFunction(FD, ReturnTy, Fn, FI, args);
- DeclRefExpr DstExpr(C, &DstDecl, false, DestTy, VK_RValue, SourceLocation());
+ DeclRefExpr DstExpr(C, DstDecl, false, DestTy, VK_PRValue, SourceLocation());
UnaryOperator *DST = UnaryOperator::Create(
C, &DstExpr, UO_Deref, DestTy->getPointeeType(), VK_LValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
- DeclRefExpr SrcExpr(C, &SrcDecl, false, SrcTy, VK_RValue, SourceLocation());
+ DeclRefExpr SrcExpr(C, SrcDecl, false, SrcTy, VK_PRValue, SourceLocation());
UnaryOperator *SRC = UnaryOperator::Create(
C, &SrcExpr, UO_Deref, SrcTy->getPointeeType(), VK_LValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
@@ -3741,12 +3790,18 @@
FunctionTy, nullptr, SC_Static, false, false);
FunctionArgList args;
- ImplicitParamDecl DstDecl(C, FD, SourceLocation(), /*Id=*/nullptr, DestTy,
- ImplicitParamDecl::Other);
- args.push_back(&DstDecl);
- ImplicitParamDecl SrcDecl(C, FD, SourceLocation(), /*Id=*/nullptr, SrcTy,
- ImplicitParamDecl::Other);
- args.push_back(&SrcDecl);
+ ParmVarDecl *Params[2];
+ ParmVarDecl *DstDecl = ParmVarDecl::Create(
+ C, FD, SourceLocation(), SourceLocation(), nullptr, DestTy,
+ C.getTrivialTypeSourceInfo(DestTy, SourceLocation()), SC_None,
+ /*DefArg=*/nullptr);
+ args.push_back(Params[0] = DstDecl);
+ ParmVarDecl *SrcDecl = ParmVarDecl::Create(
+ C, FD, SourceLocation(), SourceLocation(), nullptr, SrcTy,
+ C.getTrivialTypeSourceInfo(SrcTy, SourceLocation()), SC_None,
+ /*DefArg=*/nullptr);
+ args.push_back(Params[1] = SrcDecl);
+ FD->setParams(Params);
const CGFunctionInfo &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
@@ -3761,7 +3816,7 @@
StartFunction(FD, ReturnTy, Fn, FI, args);
- DeclRefExpr SrcExpr(getContext(), &SrcDecl, false, SrcTy, VK_RValue,
+ DeclRefExpr SrcExpr(getContext(), SrcDecl, false, SrcTy, VK_PRValue,
SourceLocation());
UnaryOperator *SRC = UnaryOperator::Create(
@@ -3788,7 +3843,7 @@
CXXConstExpr->getConstructionKind(),
SourceRange());
- DeclRefExpr DstExpr(getContext(), &DstDecl, false, DestTy, VK_RValue,
+ DeclRefExpr DstExpr(getContext(), DstDecl, false, DestTy, VK_PRValue,
SourceLocation());
RValue DV = EmitAnyExpr(&DstExpr);
diff --git a/src/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp b/src/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp
index 9825d7b..3f361f4 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -739,9 +739,11 @@
/// Function to perform atomic copies of C++ objects with nontrivial copy
/// constructors to Objective-C ivars.
LazyRuntimeFunction CxxAtomicObjectSetFn;
- /// Type of an slot structure pointer. This is returned by the various
+ /// Type of a slot structure pointer. This is returned by the various
/// lookup functions.
llvm::Type *SlotTy;
+ /// Type of a slot structure.
+ llvm::Type *SlotStructTy;
public:
llvm::Constant *GetEHType(QualType T) override;
@@ -780,7 +782,8 @@
// Load the imp from the slot
llvm::Value *imp = Builder.CreateAlignedLoad(
- Builder.CreateStructGEP(nullptr, slot, 4), CGF.getPointerAlign());
+ IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
+ CGF.getPointerAlign());
// The lookup function may have changed the receiver, so make sure we use
// the new one.
@@ -798,8 +801,9 @@
CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs);
slot->setOnlyReadsMemory();
- return Builder.CreateAlignedLoad(Builder.CreateStructGEP(nullptr, slot, 4),
- CGF.getPointerAlign());
+ return Builder.CreateAlignedLoad(
+ IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
+ CGF.getPointerAlign());
}
public:
@@ -809,8 +813,7 @@
CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) {
const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
- llvm::StructType *SlotStructTy =
- llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy);
+ SlotStructTy = llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy);
SlotTy = llvm::PointerType::getUnqual(SlotStructTy);
// Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy,
@@ -942,7 +945,8 @@
/// Generate the name of a symbol for a reference to a class. Accesses to
/// classes should be indirected via this.
- typedef std::pair<std::string, std::pair<llvm::Constant*, int>> EarlyInitPair;
+ typedef std::pair<std::string, std::pair<llvm::GlobalVariable*, int>>
+ EarlyInitPair;
std::vector<EarlyInitPair> EarlyInitList;
std::string SymbolForClassRef(StringRef Name, bool isWeak) {
@@ -1093,7 +1097,7 @@
}
}
}
- auto *ObjCStrGV =
+ llvm::GlobalVariable *ObjCStrGV =
Fields.finishAndCreateGlobal(
isNamed ? StringRef(StringName) : ".objc_string",
Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
@@ -1104,7 +1108,7 @@
ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
}
if (CGM.getTriple().isOSBinFormatCOFF()) {
- std::pair<llvm::Constant*, int> v{ObjCStrGV, 0};
+ std::pair<llvm::GlobalVariable*, int> v{ObjCStrGV, 0};
EarlyInitList.emplace_back(Sym, v);
}
llvm::Constant *ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStrGV, IdTy);
@@ -1230,7 +1234,7 @@
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
const ObjCInterfaceDecl *OID = nullptr;
- for (const auto &Result : DC->lookup(&II))
+ for (const auto *Result : DC->lookup(&II))
if ((OID = dyn_cast<ObjCInterfaceDecl>(Result)))
break;
@@ -1328,7 +1332,8 @@
Ref = GV;
}
EmittedProtocolRef = true;
- return CGF.Builder.CreateAlignedLoad(Ref, CGM.getPointerAlign());
+ return CGF.Builder.CreateAlignedLoad(ProtocolPtrTy, Ref,
+ CGM.getPointerAlign());
}
llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) {
@@ -1650,9 +1655,10 @@
for (const auto &lateInit : EarlyInitList) {
auto *global = TheModule.getGlobalVariable(lateInit.first);
if (global) {
+ llvm::GlobalVariable *GV = lateInit.second.first;
b.CreateAlignedStore(
global,
- b.CreateStructGEP(lateInit.second.first, lateInit.second.second),
+ b.CreateStructGEP(GV->getValueType(), GV, lateInit.second.second),
CGM.getPointerAlign().getAsAlign());
}
}
@@ -1689,7 +1695,8 @@
IvarOffsetPointer = new llvm::GlobalVariable(TheModule, IntTy, false,
llvm::GlobalValue::ExternalLinkage, nullptr, Name);
CharUnits Align = CGM.getIntAlign();
- llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(IvarOffsetPointer, Align);
+ llvm::Value *Offset =
+ CGF.Builder.CreateAlignedLoad(IntTy, IvarOffsetPointer, Align);
if (Offset->getType() != PtrDiffTy)
Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
return Offset;
@@ -1933,7 +1940,7 @@
// struct objc_property_list *properties
classFields.add(GeneratePropertyList(OID, classDecl));
- auto *classStruct =
+ llvm::GlobalVariable *classStruct =
classFields.finishAndCreateGlobal(SymbolForClass(className),
CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
@@ -1944,12 +1951,12 @@
if (IsCOFF) {
// we can't import a class struct.
if (OID->getClassInterface()->hasAttr<DLLExportAttr>()) {
- cast<llvm::GlobalValue>(classStruct)->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ classStruct->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
cast<llvm::GlobalValue>(classRefSymbol)->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
}
if (SuperClass) {
- std::pair<llvm::Constant*, int> v{classStruct, 1};
+ std::pair<llvm::GlobalVariable*, int> v{classStruct, 1};
EarlyInitList.emplace_back(std::string(SuperClass->getName()),
std::move(v));
}
@@ -2315,7 +2322,7 @@
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
const VarDecl *VD = nullptr;
- for (const auto &Result : DC->lookup(&II))
+ for (const auto *Result : DC->lookup(&II))
if ((VD = dyn_cast<VarDecl>(Result)))
break;
@@ -2543,7 +2550,7 @@
ReceiverClass = Builder.CreateBitCast(ReceiverClass,
llvm::PointerType::getUnqual(IdTy));
ReceiverClass =
- Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
+ Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.getPointerAlign());
}
ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
} else {
@@ -2588,7 +2595,7 @@
ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
// Load the superclass pointer
ReceiverClass =
- Builder.CreateAlignedLoad(ReceiverClass, CGF.getPointerAlign());
+ Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.getPointerAlign());
}
// Construct the structure used to look up the IMP
llvm::StructType *ObjCSuperTy =
@@ -4086,6 +4093,7 @@
return CGF.Builder.CreateZExtOrBitCast(
CGF.Builder.CreateAlignedLoad(
Int32Ty, CGF.Builder.CreateAlignedLoad(
+ llvm::Type::getInt32PtrTy(VMContext),
ObjCIvarOffsetVariable(Interface, Ivar),
CGF.getPointerAlign(), "ivar"),
CharUnits::fromQuantity(4)),
@@ -4101,7 +4109,7 @@
GV->setAlignment(Align.getAsAlign());
Offset = GV;
}
- Offset = CGF.Builder.CreateAlignedLoad(Offset, Align);
+ Offset = CGF.Builder.CreateAlignedLoad(IntTy, Offset, Align);
if (Offset->getType() != PtrDiffTy)
Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
return Offset;
diff --git a/src/llvm-project/clang/lib/CodeGen/CGObjCMac.cpp b/src/llvm-project/clang/lib/CodeGen/CGObjCMac.cpp
index 4c4a316..3de67bb 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGObjCMac.cpp
@@ -2096,6 +2096,7 @@
CGF.Builder.CreateStructGEP(ObjCSuper, 0));
// If this is a class message the metaclass is passed as the target.
+ llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(ObjCTypes.ClassTy);
llvm::Value *Target;
if (IsClassMessage) {
if (isCategoryImpl) {
@@ -2107,13 +2108,14 @@
// isa" is the first ivar in a class (which it must be).
Target = EmitClassRef(CGF, Class->getSuperClass());
Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
- Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign());
+ Target = CGF.Builder.CreateAlignedLoad(ClassTyPtr, Target,
+ CGF.getPointerAlign());
} else {
llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
llvm::Value *SuperPtr =
CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
- llvm::Value *Super =
- CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign());
+ llvm::Value *Super = CGF.Builder.CreateAlignedLoad(ClassTyPtr, SuperPtr,
+ CGF.getPointerAlign());
Target = Super;
}
} else if (isCategoryImpl)
@@ -2121,7 +2123,8 @@
else {
llvm::Value *ClassPtr = EmitSuperClassRef(Class);
ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
- Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign());
+ Target = CGF.Builder.CreateAlignedLoad(ClassTyPtr, ClassPtr,
+ CGF.getPointerAlign());
}
// FIXME: We shouldn't need to do this cast, rectify the ASTContext and
// ObjCTypes types.
@@ -5285,7 +5288,8 @@
CGM.getPointerAlign(), true);
}
- return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign());
+ return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
+ CGF.getPointerAlign());
}
llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
@@ -6518,7 +6522,7 @@
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
const VarDecl *VD = nullptr;
- for (const auto &Result : DC->lookup(&II))
+ for (const auto *Result : DC->lookup(&II))
if ((VD = dyn_cast<VarDecl>(Result)))
break;
@@ -6682,7 +6686,7 @@
llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
if (PTGV)
- return CGF.Builder.CreateAlignedLoad(PTGV, Align);
+ return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
llvm::GlobalValue::WeakAnyLinkage, Init,
ProtocolName);
@@ -6693,7 +6697,7 @@
if (!CGM.getTriple().isOSBinFormatMachO())
PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
CGM.addUsedGlobal(PTGV);
- return CGF.Builder.CreateAlignedLoad(PTGV, Align);
+ return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
}
/// GenerateCategory - Build metadata for a category implementation.
@@ -7246,7 +7250,8 @@
} else {
llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
IvarOffsetValue =
- CGF.Builder.CreateAlignedLoad(GV, CGF.getSizeAlign(), "ivar");
+ CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
+ CGF.getSizeAlign(), "ivar");
if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
cast<llvm::LoadInst>(IvarOffsetValue)
->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
@@ -7486,7 +7491,7 @@
}
CharUnits Align = CGF.getPointerAlign();
- return CGF.Builder.CreateAlignedLoad(Entry, Align);
+ return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
}
llvm::Value *
@@ -7578,7 +7583,7 @@
CGM.addCompilerUsedGlobal(Entry);
}
- return CGF.Builder.CreateAlignedLoad(Entry, Align);
+ return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
}
/// GetClass - Return a reference to the class for the given interface
diff --git a/src/llvm-project/clang/lib/CodeGen/CGObjCRuntime.cpp b/src/llvm-project/clang/lib/CodeGen/CGObjCRuntime.cpp
index 9bf4d83..108f6fc 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGObjCRuntime.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -64,7 +64,7 @@
Ivar->getUsageType(ObjectPtrTy).withCVRQualifiers(CVRQualifiers);
llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy);
- V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr");
+ V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, V, Offset, "add.ptr");
if (!Ivar->isBitField()) {
V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
diff --git a/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index caa5291..c09797e 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -15,6 +15,7 @@
#include "CGCleanup.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
+#include "clang/AST/APValue.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/OpenMPClause.h"
@@ -448,7 +449,7 @@
/// Values for bit flags used in the ident_t to describe the fields.
/// All enumeric elements are named and described in accordance with the code
-/// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
+/// from https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h
enum OpenMPLocationFlags : unsigned {
/// Use trampoline for internal microtask.
OMP_IDENT_IMD = 0x01,
@@ -503,7 +504,7 @@
/// Describes ident structure that describes a source location.
/// All descriptions are taken from
-/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
+/// https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h
/// Original structure:
/// typedef struct ident {
/// kmp_int32 reserved_1; /**< might be used in Fortran;
@@ -655,11 +656,15 @@
InitRVal =
RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
break;
- case TEK_Aggregate:
- InitRVal = RValue::getAggregate(LV.getAddress(CGF));
- break;
+ case TEK_Aggregate: {
+ OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_LValue);
+ CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV);
+ CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
+ /*IsInitializer=*/false);
+ return;
}
- OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
+ }
+ OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_PRValue);
CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
/*IsInitializer=*/false);
@@ -693,7 +698,8 @@
SrcBegin = SrcAddr.getPointer();
llvm::Value *DestBegin = DestAddr.getPointer();
// Cast from pointer to array type to pointer to single element.
- llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
+ llvm::Value *DestEnd =
+ CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements);
// The basic structure here is a while-do loop.
llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
@@ -738,13 +744,15 @@
if (DRD) {
// Shift the address forward by one element.
llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
- SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ SrcAddr.getElementType(), SrcElementPHI, /*Idx0=*/1,
+ "omp.arraycpy.dest.element");
SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
}
// Shift the address forward by one element.
llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
- DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ DestAddr.getElementType(), DestElementPHI, /*Idx0=*/1,
+ "omp.arraycpy.dest.element");
// Check whether we've reached the end.
llvm::Value *Done =
CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
@@ -1005,13 +1013,14 @@
LValue BaseLValue =
loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
OriginalBaseLValue);
+ Address SharedAddr = SharedAddresses[N].first.getAddress(CGF);
llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
- BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF));
+ BaseLValue.getPointer(CGF), SharedAddr.getPointer());
llvm::Value *PrivatePointer =
CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
- PrivateAddr.getPointer(),
- SharedAddresses[N].first.getAddress(CGF).getType());
- llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
+ PrivateAddr.getPointer(), SharedAddr.getType());
+ llvm::Value *Ptr = CGF.Builder.CreateGEP(
+ SharedAddr.getElementType(), PrivatePointer, Adjustment);
return castToBase(CGF, OrigVD->getType(),
SharedAddresses[N].first.getType(),
OriginalBaseLValue.getAddress(CGF).getType(),
@@ -1034,7 +1043,7 @@
getThreadIDVariable()->getType()->castAs<PointerType>());
}
-void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
+void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) {
if (!CGF.HaveInsertPoint())
return;
// 1.2.2 OpenMP Language Terminology
@@ -1043,6 +1052,8 @@
// The point of exit cannot be a branch out of the structured block.
// longjmp() and throw() must not violate the entry/exit criteria.
CGF.EHStack.pushTerminate();
+ if (S)
+ CGF.incrementProfileCounter(S);
CodeGen(CGF);
CGF.EHStack.popTerminate();
}
@@ -1199,7 +1210,7 @@
// Builder if one is present.
struct PushAndPopStackRAII {
PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF,
- bool HasCancel)
+ bool HasCancel, llvm::omp::Directive Kind)
: OMPBuilder(OMPBuilder) {
if (!OMPBuilder)
return;
@@ -1228,8 +1239,7 @@
// TODO: Remove this once we emit parallel regions through the
// OpenMPIRBuilder as it can do this setup internally.
- llvm::OpenMPIRBuilder::FinalizationInfo FI(
- {FiniCB, OMPD_parallel, HasCancel});
+ llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
OMPBuilder->pushFinalizationCB(std::move(FI));
}
~PushAndPopStackRAII() {
@@ -1270,7 +1280,7 @@
// TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new
// parallel region to make cancellation barriers work properly.
llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
- PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel);
+ PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
HasCancel, OutlinedHelperName);
CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
@@ -1654,9 +1664,13 @@
assert(PLoc.isValid() && "Source location is expected to be always valid.");
llvm::sys::fs::UniqueID ID;
- if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
- SM.getDiagnostics().Report(diag::err_cannot_open_file)
- << PLoc.getFilename() << EC.message();
+ if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) {
+ PLoc = SM.getPresumedLoc(Loc, /*UseLineDirectives=*/false);
+ assert(PLoc.isValid() && "Source location is expected to be always valid.");
+ if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
+ SM.getDiagnostics().Report(diag::err_cannot_open_file)
+ << PLoc.getFilename() << EC.message();
+ }
DeviceID = ID.getDevice();
FileID = ID.getFile();
@@ -2269,6 +2283,35 @@
Action.Done(CGF);
}
+void CGOpenMPRuntime::emitMaskedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MaskedOpGen,
+ SourceLocation Loc, const Expr *Filter) {
+ if (!CGF.HaveInsertPoint())
+ return;
+ // if(__kmpc_masked(ident_t *, gtid, filter)) {
+ // MaskedOpGen();
+ // __kmpc_end_masked(iden_t *, gtid);
+ // }
+ // Prepare arguments and build a call to __kmpc_masked
+ llvm::Value *FilterVal = Filter
+ ? CGF.EmitScalarExpr(Filter, CGF.Int32Ty)
+ : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0);
+ llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
+ FilterVal};
+ llvm::Value *ArgsEnd[] = {emitUpdateLocation(CGF, Loc),
+ getThreadID(CGF, Loc)};
+ CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction(
+ CGM.getModule(), OMPRTL___kmpc_masked),
+ Args,
+ OMPBuilder.getOrCreateRuntimeFunction(
+ CGM.getModule(), OMPRTL___kmpc_end_masked),
+ ArgsEnd,
+ /*Conditional=*/true);
+ MaskedOpGen.setAction(Action);
+ emitInlinedDirective(CGF, OMPD_masked, MaskedOpGen);
+ Action.Done(CGF);
+}
+
void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
SourceLocation Loc) {
if (!CGF.HaveInsertPoint())
@@ -2957,8 +3000,7 @@
if (CGM.getLangOpts().OpenMPIsDevice) {
// This could happen if the device compilation is invoked standalone.
if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum))
- initializeTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum,
- OffloadingEntriesNum);
+ return;
auto &Entry =
OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Entry.setAddress(Addr);
@@ -3029,10 +3071,8 @@
if (CGM.getLangOpts().OpenMPIsDevice) {
// This could happen if the device compilation is invoked standalone.
if (!hasDeviceGlobalVarEntryInfo(VarName))
- initializeDeviceGlobalVarEntryInfo(VarName, Flags, OffloadingEntriesNum);
+ return;
auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
- assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
- "Resetting with the new address.");
if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
if (Entry.getVarSize().isZero()) {
Entry.setVarSize(VarSize);
@@ -3048,8 +3088,6 @@
auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
assert(Entry.isValid() && Entry.getFlags() == Flags &&
"Entry not initialized!");
- assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
- "Resetting with the new address.");
if (Entry.getVarSize().isZero()) {
Entry.setVarSize(VarSize);
Entry.setLinkage(Linkage);
@@ -4121,8 +4159,9 @@
dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
LValue UpAddrLVal =
CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
- llvm::Value *UpAddr =
- CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
+ Address UpAddrAddress = UpAddrLVal.getAddress(CGF);
+ llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(
+ UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1);
llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy);
llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy);
SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
@@ -4255,7 +4294,7 @@
// kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
// kmp_routine_entry_t *task_entry);
// Task flags. Format is taken from
- // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
+ // https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h,
// description of kmp_tasking_flags struct.
enum {
TiedFlag = 0x1,
@@ -4364,7 +4403,7 @@
OpaqueValueExpr OVE(
Loc,
C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0),
- VK_RValue);
+ VK_PRValue);
CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE,
RValue::get(NumOfElements));
KmpTaskAffinityInfoArrayTy =
@@ -4437,7 +4476,8 @@
std::tie(Addr, Size) = getPointerAndSize(CGF, E);
llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
LValue Base = CGF.MakeAddrLValue(
- Address(CGF.Builder.CreateGEP(AffinitiesArray.getPointer(), Idx),
+ Address(CGF.Builder.CreateGEP(AffinitiesArray.getElementType(),
+ AffinitiesArray.getPointer(), Idx),
AffinitiesArray.getAlignment()),
KmpTaskAffinityInfoTy);
// affs[i].base_addr = &<Affinities[i].second>;
@@ -4604,7 +4644,7 @@
Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
Base.getTBAAInfo());
llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
- Addr.getPointer(),
+ Addr.getElementType(), Addr.getPointer(),
llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
LValue NumDepsBase = CGF.MakeAddrLValue(
Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
@@ -4644,7 +4684,8 @@
LValue &PosLVal = *Pos.get<LValue *>();
llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
Base = CGF.MakeAddrLValue(
- Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx),
+ Address(CGF.Builder.CreateGEP(DependenciesArray.getElementType(),
+ DependenciesArray.getPointer(), Idx),
DependenciesArray.getAlignment()),
KmpDependInfoTy);
}
@@ -4704,7 +4745,7 @@
Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(),
Base.getTBAAInfo());
llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
- Addr.getPointer(),
+ Addr.getElementType(), Addr.getPointer(),
llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
LValue NumDepsBase = CGF.MakeAddrLValue(
Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
@@ -4765,7 +4806,7 @@
// Get number of elements in a single depobj.
llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
- Addr.getPointer(),
+ Addr.getElementType(), Addr.getPointer(),
llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
LValue NumDepsBase = CGF.MakeAddrLValue(
Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy,
@@ -4782,7 +4823,8 @@
CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false));
llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc());
Address DepAddr =
- Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos),
+ Address(CGF.Builder.CreateGEP(DependenciesArray.getElementType(),
+ DependenciesArray.getPointer(), Pos),
DependenciesArray.getAlignment());
CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size);
@@ -4858,7 +4900,7 @@
}
OpaqueValueExpr OVE(Loc,
C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0),
- VK_RValue);
+ VK_PRValue);
CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE,
RValue::get(NumOfElements));
KmpDependInfoArrayTy =
@@ -5010,7 +5052,7 @@
Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy));
llvm::Value *DepObjAddr = CGF.Builder.CreateGEP(
- Addr.getPointer(),
+ Addr.getElementType(), Addr.getPointer(),
llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true));
DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr,
CGF.VoidPtrTy);
@@ -5040,7 +5082,8 @@
Address Begin = Base.getAddress(CGF);
// Cast from pointer to array type to pointer to single element.
- llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps);
+ llvm::Value *End = CGF.Builder.CreateGEP(
+ Begin.getElementType(), Begin.getPointer(), NumDeps);
// The basic structure here is a while-do loop.
llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body");
llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done");
@@ -5303,7 +5346,8 @@
llvm::Value *RHSBegin = RHSAddr.getPointer();
llvm::Value *LHSBegin = LHSAddr.getPointer();
// Cast from pointer to array type to pointer to single element.
- llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
+ llvm::Value *LHSEnd =
+ CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements);
// The basic structure here is a while-do loop.
llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
@@ -5341,9 +5385,11 @@
// Shift the address forward by one element.
llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
- LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ LHSAddr.getElementType(), LHSElementPHI, /*Idx0=*/1,
+ "omp.arraycpy.dest.element");
llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
- RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
+ RHSAddr.getElementType(), RHSElementPHI, /*Idx0=*/1,
+ "omp.arraycpy.src.element");
// Check whether we've reached the end.
llvm::Value *Done =
CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
@@ -6222,7 +6268,8 @@
return;
InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel,
InnerKind != OMPD_critical &&
- InnerKind != OMPD_master);
+ InnerKind != OMPD_master &&
+ InnerKind != OMPD_masked);
CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
}
@@ -6272,6 +6319,7 @@
CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
Args);
// if (__kmpc_cancellationpoint()) {
+ // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only
// exit from construct;
// }
llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
@@ -6279,6 +6327,8 @@
llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
+ if (CancelRegion == OMPD_parallel)
+ emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
// exit from construct;
CodeGenFunction::JumpDest CancelDest =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
@@ -6308,6 +6358,7 @@
llvm::Value *Result = CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
// if (__kmpc_cancel()) {
+ // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only
// exit from construct;
// }
llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
@@ -6315,6 +6366,8 @@
llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
CGF.EmitBlock(ExitBB);
+ if (CancelRegion == OMPD_parallel)
+ RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false);
// exit from construct;
CodeGenFunction::JumpDest CancelDest =
CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
@@ -6498,6 +6551,20 @@
OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
+
+ // Add NumTeams and ThreadLimit attributes to the outlined GPU function
+ int32_t DefaultValTeams = -1;
+ getNumTeamsExprForTargetDirective(CGF, D, DefaultValTeams);
+ if (DefaultValTeams > 0) {
+ OutlinedFn->addFnAttr("omp_target_num_teams",
+ std::to_string(DefaultValTeams));
+ }
+ int32_t DefaultValThreads = -1;
+ getNumThreadsExprForTargetDirective(CGF, D, DefaultValThreads);
+ if (DefaultValThreads > 0) {
+ OutlinedFn->addFnAttr("omp_target_thread_limit",
+ std::to_string(DefaultValThreads));
+ }
}
/// Checks if the expression is constant or does not have non-trivial function
@@ -6526,7 +6593,7 @@
continue;
// Analyze declarations.
if (const auto *DS = dyn_cast<DeclStmt>(S)) {
- if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
+ if (llvm::all_of(DS->decls(), [](const Decl *D) {
if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
@@ -6537,10 +6604,7 @@
const auto *VD = dyn_cast<VarDecl>(D);
if (!VD)
return false;
- return VD->isConstexpr() ||
- ((VD->getType().isTrivialType(Ctx) ||
- VD->getType()->isReferenceType()) &&
- (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
+ return VD->hasGlobalStorage() || !VD->isUsed();
}))
continue;
}
@@ -6555,24 +6619,13 @@
return Child;
}
-/// Emit the number of teams for a target directive. Inspect the num_teams
-/// clause associated with a teams construct combined or closely nested
-/// with the target directive.
-///
-/// Emit a team of size one for directives such as 'target parallel' that
-/// have no associated teams construct.
-///
-/// Otherwise, return nullptr.
-static llvm::Value *
-emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
- const OMPExecutableDirective &D) {
- assert(!CGF.getLangOpts().OpenMPIsDevice &&
- "Clauses associated with the teams directive expected to be emitted "
- "only for the host!");
+const Expr *CGOpenMPRuntime::getNumTeamsExprForTargetDirective(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ int32_t &DefaultVal) {
+
OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
"Expected target-based executable directive.");
- CGBuilderTy &Bld = CGF.Builder;
switch (DirectiveKind) {
case OMPD_target: {
const auto *CS = D.getInnermostCapturedStmt();
@@ -6584,23 +6637,27 @@
dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
- CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
- CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
const Expr *NumTeams =
NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
- llvm::Value *NumTeamsVal =
- CGF.EmitScalarExpr(NumTeams,
- /*IgnoreResultAssign*/ true);
- return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
- /*isSigned=*/true);
+ if (NumTeams->isIntegerConstantExpr(CGF.getContext()))
+ if (auto Constant =
+ NumTeams->getIntegerConstantExpr(CGF.getContext()))
+ DefaultVal = Constant->getExtValue();
+ return NumTeams;
}
- return Bld.getInt32(0);
+ DefaultVal = 0;
+ return nullptr;
}
if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
- isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
- return Bld.getInt32(1);
- return Bld.getInt32(0);
+ isOpenMPSimdDirective(NestedDir->getDirectiveKind())) {
+ DefaultVal = 1;
+ return nullptr;
+ }
+ DefaultVal = 1;
+ return nullptr;
}
+ // A value of -1 is used to check if we need to emit no teams region
+ DefaultVal = -1;
return nullptr;
}
case OMPD_target_teams:
@@ -6609,22 +6666,22 @@
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd: {
if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
- CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
const Expr *NumTeams =
D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
- llvm::Value *NumTeamsVal =
- CGF.EmitScalarExpr(NumTeams,
- /*IgnoreResultAssign*/ true);
- return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
- /*isSigned=*/true);
+ if (NumTeams->isIntegerConstantExpr(CGF.getContext()))
+ if (auto Constant = NumTeams->getIntegerConstantExpr(CGF.getContext()))
+ DefaultVal = Constant->getExtValue();
+ return NumTeams;
}
- return Bld.getInt32(0);
+ DefaultVal = 0;
+ return nullptr;
}
case OMPD_target_parallel:
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
case OMPD_target_simd:
- return Bld.getInt32(1);
+ DefaultVal = 1;
+ return nullptr;
case OMPD_parallel:
case OMPD_for:
case OMPD_parallel_for:
@@ -6639,6 +6696,8 @@
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
@@ -6688,6 +6747,48 @@
llvm_unreachable("Unexpected directive kind.");
}
+llvm::Value *CGOpenMPRuntime::emitNumTeamsForTargetDirective(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D) {
+ assert(!CGF.getLangOpts().OpenMPIsDevice &&
+ "Clauses associated with the teams directive expected to be emitted "
+ "only for the host!");
+ CGBuilderTy &Bld = CGF.Builder;
+ int32_t DefaultNT = -1;
+ const Expr *NumTeams = getNumTeamsExprForTargetDirective(CGF, D, DefaultNT);
+ if (NumTeams != nullptr) {
+ OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
+
+ switch (DirectiveKind) {
+ case OMPD_target: {
+ const auto *CS = D.getInnermostCapturedStmt();
+ CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
+ llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams,
+ /*IgnoreResultAssign*/ true);
+ return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
+ /*isSigned=*/true);
+ }
+ case OMPD_target_teams:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd: {
+ CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
+ llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams,
+ /*IgnoreResultAssign*/ true);
+ return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
+ /*isSigned=*/true);
+ }
+ default:
+ break;
+ }
+ } else if (DefaultNT == -1) {
+ return nullptr;
+ }
+
+ return Bld.getInt32(DefaultNT);
+}
+
static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
llvm::Value *DefaultThreadLimitVal) {
const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
@@ -6780,17 +6881,130 @@
: CGF.Builder.getInt32(0);
}
-/// Emit the number of threads for a target directive. Inspect the
-/// thread_limit clause associated with a teams construct combined or closely
-/// nested with the target directive.
-///
-/// Emit the num_threads clause for directives such as 'target parallel' that
-/// have no associated teams construct.
-///
-/// Otherwise, return nullptr.
-static llvm::Value *
-emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
- const OMPExecutableDirective &D) {
+const Expr *CGOpenMPRuntime::getNumThreadsExprForTargetDirective(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D,
+ int32_t &DefaultVal) {
+ OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
+ assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
+ "Expected target-based executable directive.");
+
+ switch (DirectiveKind) {
+ case OMPD_target:
+ // Teams have no clause thread_limit
+ return nullptr;
+ case OMPD_target_teams:
+ case OMPD_target_teams_distribute:
+ if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
+ const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
+ const Expr *ThreadLimit = ThreadLimitClause->getThreadLimit();
+ if (ThreadLimit->isIntegerConstantExpr(CGF.getContext()))
+ if (auto Constant =
+ ThreadLimit->getIntegerConstantExpr(CGF.getContext()))
+ DefaultVal = Constant->getExtValue();
+ return ThreadLimit;
+ }
+ return nullptr;
+ case OMPD_target_parallel:
+ case OMPD_target_parallel_for:
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute_parallel_for_simd: {
+ Expr *ThreadLimit = nullptr;
+ Expr *NumThreads = nullptr;
+ if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
+ const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
+ ThreadLimit = ThreadLimitClause->getThreadLimit();
+ if (ThreadLimit->isIntegerConstantExpr(CGF.getContext()))
+ if (auto Constant =
+ ThreadLimit->getIntegerConstantExpr(CGF.getContext()))
+ DefaultVal = Constant->getExtValue();
+ }
+ if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
+ const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
+ NumThreads = NumThreadsClause->getNumThreads();
+ if (NumThreads->isIntegerConstantExpr(CGF.getContext())) {
+ if (auto Constant =
+ NumThreads->getIntegerConstantExpr(CGF.getContext())) {
+ if (Constant->getExtValue() < DefaultVal) {
+ DefaultVal = Constant->getExtValue();
+ ThreadLimit = NumThreads;
+ }
+ }
+ }
+ }
+ return ThreadLimit;
+ }
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_target_simd:
+ DefaultVal = 1;
+ return nullptr;
+ case OMPD_parallel:
+ case OMPD_for:
+ case OMPD_parallel_for:
+ case OMPD_parallel_master:
+ case OMPD_parallel_sections:
+ case OMPD_for_simd:
+ case OMPD_parallel_for_simd:
+ case OMPD_cancel:
+ case OMPD_cancellation_point:
+ case OMPD_ordered:
+ case OMPD_threadprivate:
+ case OMPD_allocate:
+ case OMPD_task:
+ case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
+ case OMPD_sections:
+ case OMPD_section:
+ case OMPD_single:
+ case OMPD_master:
+ case OMPD_critical:
+ case OMPD_taskyield:
+ case OMPD_barrier:
+ case OMPD_taskwait:
+ case OMPD_taskgroup:
+ case OMPD_atomic:
+ case OMPD_flush:
+ case OMPD_depobj:
+ case OMPD_scan:
+ case OMPD_teams:
+ case OMPD_target_data:
+ case OMPD_target_exit_data:
+ case OMPD_target_enter_data:
+ case OMPD_distribute:
+ case OMPD_distribute_simd:
+ case OMPD_distribute_parallel_for:
+ case OMPD_distribute_parallel_for_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_target_update:
+ case OMPD_declare_simd:
+ case OMPD_declare_variant:
+ case OMPD_begin_declare_variant:
+ case OMPD_end_declare_variant:
+ case OMPD_declare_target:
+ case OMPD_end_declare_target:
+ case OMPD_declare_reduction:
+ case OMPD_declare_mapper:
+ case OMPD_taskloop:
+ case OMPD_taskloop_simd:
+ case OMPD_master_taskloop:
+ case OMPD_master_taskloop_simd:
+ case OMPD_parallel_master_taskloop:
+ case OMPD_parallel_master_taskloop_simd:
+ case OMPD_requires:
+ case OMPD_unknown:
+ break;
+ default:
+ break;
+ }
+ llvm_unreachable("Unsupported directive kind.");
+}
+
+llvm::Value *CGOpenMPRuntime::emitNumThreadsForTargetDirective(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D) {
assert(!CGF.getLangOpts().OpenMPIsDevice &&
"Clauses associated with the teams directive expected to be emitted "
"only for the host!");
@@ -6956,6 +7170,8 @@
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
@@ -7157,12 +7373,15 @@
/// [ValueDecl *] --> {LE(FieldIndex, Pointer),
/// HE(FieldIndex, Pointer)}
struct StructRangeInfoTy {
+ MapCombinedInfoTy PreliminaryMapData;
std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
0, Address::invalid()};
std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
0, Address::invalid()};
Address Base = Address::invalid();
+ Address LB = Address::invalid();
bool IsArraySection = false;
+ bool HasCompleteRecord = false;
};
private:
@@ -7345,11 +7564,10 @@
if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
!= MapModifiers.end())
Bits |= OMP_MAP_CLOSE;
- if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present)
- != MapModifiers.end())
- Bits |= OMP_MAP_PRESENT;
- if (llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present)
- != MotionModifiers.end())
+ if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present) !=
+ MapModifiers.end() ||
+ llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) !=
+ MotionModifiers.end())
Bits |= OMP_MAP_PRESENT;
if (IsNonContiguous)
Bits |= OMP_MAP_NON_CONTIG;
@@ -7429,6 +7647,7 @@
// S1 s;
// double *p;
// struct S2 *ps;
+ // int &ref;
// }
// S2 s;
// S2 *ps;
@@ -7472,6 +7691,14 @@
// optimizes this entry out, same in the examples below)
// (***) map the pointee (map: to)
//
+ // map(to: s.ref)
+ // &s, &(s.ref), sizeof(int*), TARGET_PARAM (*)
+ // &s, &(s.ref), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
+ // (*) alloc space for struct members, only this is a target parameter
+ // (**) map the pointer (nothing to be mapped in this example) (the compiler
+ // optimizes this entry out, same in the examples below)
+ // (***) map the pointee (map: to)
+ //
// map(s.ps)
// &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
//
@@ -7669,6 +7896,7 @@
uint64_t DimSize = 1;
bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous;
+ bool IsPrevMemberReference = false;
for (; I != CE; ++I) {
// If the current component is member of a struct (parent struct) mark it.
@@ -7710,6 +7938,8 @@
const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
? I->getAssociatedDeclaration()
: BaseDecl;
+ MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
+ : MapExpr;
// Get information on whether the element is a pointer. Have to do a
// special treatment for array sections given that they are built-in
@@ -7726,12 +7956,16 @@
.getCanonicalType()
->isAnyPointerType()) ||
I->getAssociatedExpression()->getType()->isAnyPointerType();
+ bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) &&
+ MapDecl &&
+ MapDecl->getType()->isLValueReferenceType();
bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous;
if (OASE)
++DimSize;
- if (Next == CE || IsNonDerefPointer || IsFinalArraySection) {
+ if (Next == CE || IsMemberReference || IsNonDerefPointer ||
+ IsFinalArraySection) {
// If this is not the last component, we expect the pointer to be
// associated with an array expression or member expression.
assert((Next == CE ||
@@ -7744,36 +7978,65 @@
"Unexpected expression");
Address LB = Address::invalid();
+ Address LowestElem = Address::invalid();
+ auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
+ const MemberExpr *E) {
+ const Expr *BaseExpr = E->getBase();
+ // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a
+ // scalar.
+ LValue BaseLV;
+ if (E->isArrow()) {
+ LValueBaseInfo BaseInfo;
+ TBAAAccessInfo TBAAInfo;
+ Address Addr =
+ CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo);
+ QualType PtrTy = BaseExpr->getType()->getPointeeType();
+ BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo);
+ } else {
+ BaseLV = CGF.EmitOMPSharedLValue(BaseExpr);
+ }
+ return BaseLV;
+ };
if (OAShE) {
- LB = Address(CGF.EmitScalarExpr(OAShE->getBase()),
- CGF.getContext().getTypeAlignInChars(
- OAShE->getBase()->getType()));
- } else {
- LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
+ LowestElem = LB = Address(CGF.EmitScalarExpr(OAShE->getBase()),
+ CGF.getContext().getTypeAlignInChars(
+ OAShE->getBase()->getType()));
+ } else if (IsMemberReference) {
+ const auto *ME = cast<MemberExpr>(I->getAssociatedExpression());
+ LValue BaseLVal = EmitMemberExprBase(CGF, ME);
+ LowestElem = CGF.EmitLValueForFieldInitialization(
+ BaseLVal, cast<FieldDecl>(MapDecl))
+ .getAddress(CGF);
+ LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType())
.getAddress(CGF);
+ } else {
+ LowestElem = LB =
+ CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
+ .getAddress(CGF);
}
// If this component is a pointer inside the base struct then we don't
// need to create any entry for it - it will be combined with the object
// it is pointing to into a single PTR_AND_OBJ entry.
bool IsMemberPointerOrAddr =
- (IsPointer || ForDeviceAddr) && EncounteredME &&
- (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
- EncounteredME);
- if (!OverlappedElements.empty()) {
+ EncounteredME &&
+ (((IsPointer || ForDeviceAddr) &&
+ I->getAssociatedExpression() == EncounteredME) ||
+ (IsPrevMemberReference && !IsPointer) ||
+ (IsMemberReference && Next != CE &&
+ !Next->getAssociatedExpression()->getType()->isPointerType()));
+ if (!OverlappedElements.empty() && Next == CE) {
// Handle base element with the info for overlapped elements.
assert(!PartialStruct.Base.isValid() && "The base element is set.");
- assert(Next == CE &&
- "Expected last element for the overlapped elements.");
assert(!IsPointer &&
"Unexpected base element with the pointer type.");
// Mark the whole struct as the struct that requires allocation on the
// device.
- PartialStruct.LowestElem = {0, LB};
+ PartialStruct.LowestElem = {0, LowestElem};
CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
I->getAssociatedExpression()->getType());
Address HB = CGF.Builder.CreateConstGEP(
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
+ CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LowestElem,
CGF.VoidPtrTy),
TypeSize.getQuantity() - 1);
PartialStruct.HighestElem = {
@@ -7781,13 +8044,17 @@
PartialStruct.HighestElem.first)>::max(),
HB};
PartialStruct.Base = BP;
+ PartialStruct.LB = LB;
+ assert(
+ PartialStruct.PreliminaryMapData.BasePointers.empty() &&
+ "Overlapped elements must be used only once for the variable.");
+ std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
// Emit data for non-overlapped data.
OpenMPOffloadMappingFlags Flags =
OMP_MAP_MEMBER_OF |
getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
/*AddPtrFlag=*/false,
/*AddIsTargetParamFlag=*/false, IsNonContiguous);
- LB = BP;
llvm::Value *Size = nullptr;
// Do bitcopy of all non-overlapped structure elements.
for (OMPClauseMappableExprCommon::MappableExprComponentListRef
@@ -7795,10 +8062,20 @@
Address ComponentLB = Address::invalid();
for (const OMPClauseMappableExprCommon::MappableComponent &MC :
Component) {
- if (MC.getAssociatedDeclaration()) {
- ComponentLB =
- CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
- .getAddress(CGF);
+ if (const ValueDecl *VD = MC.getAssociatedDeclaration()) {
+ const auto *FD = dyn_cast<FieldDecl>(VD);
+ if (FD && FD->getType()->isLValueReferenceType()) {
+ const auto *ME =
+ cast<MemberExpr>(MC.getAssociatedExpression());
+ LValue BaseLVal = EmitMemberExprBase(CGF, ME);
+ ComponentLB =
+ CGF.EmitLValueForFieldInitialization(BaseLVal, FD)
+ .getAddress(CGF);
+ } else {
+ ComponentLB =
+ CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
+ .getAddress(CGF);
+ }
Size = CGF.Builder.CreatePtrDiff(
CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
CGF.EmitCastToVoidPtr(LB.getPointer()));
@@ -7821,8 +8098,7 @@
CombinedInfo.BasePointers.push_back(BP.getPointer());
CombinedInfo.Pointers.push_back(LB.getPointer());
Size = CGF.Builder.CreatePtrDiff(
- CGF.EmitCastToVoidPtr(
- CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
+ CGF.Builder.CreateConstGEP(HB, 1).getPointer(),
CGF.EmitCastToVoidPtr(LB.getPointer()));
CombinedInfo.Sizes.push_back(
CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
@@ -7854,13 +8130,13 @@
OpenMPOffloadMappingFlags Flags = getMapTypeBits(
MapType, MapModifiers, MotionModifiers, IsImplicit,
!IsExpressionFirstInfo || RequiresReference ||
- FirstPointerInComplexData,
+ FirstPointerInComplexData || IsMemberReference,
IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
- if (!IsExpressionFirstInfo) {
+ if (!IsExpressionFirstInfo || IsMemberReference) {
// If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
// then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
- if (IsPointer)
+ if (IsPointer || (IsMemberReference && Next != CE))
Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
OMP_MAP_DELETE | OMP_MAP_CLOSE);
@@ -7886,20 +8162,21 @@
// Update info about the lowest and highest elements for this struct
if (!PartialStruct.Base.isValid()) {
- PartialStruct.LowestElem = {FieldIndex, LB};
+ PartialStruct.LowestElem = {FieldIndex, LowestElem};
if (IsFinalArraySection) {
Address HB =
CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false)
.getAddress(CGF);
PartialStruct.HighestElem = {FieldIndex, HB};
} else {
- PartialStruct.HighestElem = {FieldIndex, LB};
+ PartialStruct.HighestElem = {FieldIndex, LowestElem};
}
PartialStruct.Base = BP;
+ PartialStruct.LB = BP;
} else if (FieldIndex < PartialStruct.LowestElem.first) {
- PartialStruct.LowestElem = {FieldIndex, LB};
+ PartialStruct.LowestElem = {FieldIndex, LowestElem};
} else if (FieldIndex > PartialStruct.HighestElem.first) {
- PartialStruct.HighestElem = {FieldIndex, LB};
+ PartialStruct.HighestElem = {FieldIndex, LowestElem};
}
}
@@ -7913,11 +8190,12 @@
// The pointer becomes the base for the next element.
if (Next != CE)
- BP = LB;
+ BP = IsMemberReference ? LowestElem : LB;
IsExpressionFirstInfo = false;
IsCaptureFirstInfo = false;
FirstPointerInComplexData = false;
+ IsPrevMemberReference = IsMemberReference;
} else if (FirstPointerInComplexData) {
QualType Ty = Components.rbegin()
->getAssociatedDeclaration()
@@ -7927,6 +8205,10 @@
FirstPointerInComplexData = false;
}
}
+ // If ran into the whole component - allocate the space for the whole
+ // record.
+ if (!EncounteredME)
+ PartialStruct.HasCompleteRecord = true;
if (!IsNonContiguous)
return;
@@ -8116,10 +8398,6 @@
// 'private ptr' and 'map to' flag. Return the right flags if the captured
// declaration is known as first-private in this handler.
if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
- if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
- Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
- return MappableExprsHandler::OMP_MAP_ALWAYS |
- MappableExprsHandler::OMP_MAP_TO;
if (Cap.getCapturedVar()->getType()->isAnyPointerType())
return MappableExprsHandler::OMP_MAP_TO |
MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
@@ -8211,6 +8489,360 @@
}
}
+ /// Generate all the base pointers, section pointers, sizes, map types, and
+ /// mappers for the extracted mappable expressions (all included in \a
+ /// CombinedInfo). Also, for each item that relates with a device pointer, a
+ /// pair of the relevant declaration and index where it occurs is appended to
+ /// the device pointers info array.
+ void generateAllInfoForClauses(
+ ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
+ const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
+ llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
+ // We have to process the component lists that relate with the same
+ // declaration in a single chunk so that we can generate the map flags
+ // correctly. Therefore, we organize all lists in a map.
+ enum MapKind { Present, Allocs, Other, Total };
+ llvm::MapVector<CanonicalDeclPtr<const Decl>,
+ SmallVector<SmallVector<MapInfo, 8>, 4>>
+ Info;
+
+ // Helper function to fill the information map for the different supported
+ // clauses.
+ auto &&InfoGen =
+ [&Info, &SkipVarSet](
+ const ValueDecl *D, MapKind Kind,
+ OMPClauseMappableExprCommon::MappableExprComponentListRef L,
+ OpenMPMapClauseKind MapType,
+ ArrayRef<OpenMPMapModifierKind> MapModifiers,
+ ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
+ bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper,
+ const Expr *VarRef = nullptr, bool ForDeviceAddr = false) {
+ if (SkipVarSet.contains(D))
+ return;
+ auto It = Info.find(D);
+ if (It == Info.end())
+ It = Info
+ .insert(std::make_pair(
+ D, SmallVector<SmallVector<MapInfo, 8>, 4>(Total)))
+ .first;
+ It->second[Kind].emplace_back(
+ L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
+ IsImplicit, Mapper, VarRef, ForDeviceAddr);
+ };
+
+ for (const auto *Cl : Clauses) {
+ const auto *C = dyn_cast<OMPMapClause>(Cl);
+ if (!C)
+ continue;
+ MapKind Kind = Other;
+ if (!C->getMapTypeModifiers().empty() &&
+ llvm::any_of(C->getMapTypeModifiers(), [](OpenMPMapModifierKind K) {
+ return K == OMPC_MAP_MODIFIER_present;
+ }))
+ Kind = Present;
+ else if (C->getMapType() == OMPC_MAP_alloc)
+ Kind = Allocs;
+ const auto *EI = C->getVarRefs().begin();
+ for (const auto L : C->component_lists()) {
+ const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr;
+ InfoGen(std::get<0>(L), Kind, std::get<1>(L), C->getMapType(),
+ C->getMapTypeModifiers(), llvm::None,
+ /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L),
+ E);
+ ++EI;
+ }
+ }
+ for (const auto *Cl : Clauses) {
+ const auto *C = dyn_cast<OMPToClause>(Cl);
+ if (!C)
+ continue;
+ MapKind Kind = Other;
+ if (!C->getMotionModifiers().empty() &&
+ llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) {
+ return K == OMPC_MOTION_MODIFIER_present;
+ }))
+ Kind = Present;
+ const auto *EI = C->getVarRefs().begin();
+ for (const auto L : C->component_lists()) {
+ InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, llvm::None,
+ C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
+ C->isImplicit(), std::get<2>(L), *EI);
+ ++EI;
+ }
+ }
+ for (const auto *Cl : Clauses) {
+ const auto *C = dyn_cast<OMPFromClause>(Cl);
+ if (!C)
+ continue;
+ MapKind Kind = Other;
+ if (!C->getMotionModifiers().empty() &&
+ llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) {
+ return K == OMPC_MOTION_MODIFIER_present;
+ }))
+ Kind = Present;
+ const auto *EI = C->getVarRefs().begin();
+ for (const auto L : C->component_lists()) {
+ InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, llvm::None,
+ C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
+ C->isImplicit(), std::get<2>(L), *EI);
+ ++EI;
+ }
+ }
+
+ // Look at the use_device_ptr clause information and mark the existing map
+ // entries as such. If there is no map information for an entry in the
+ // use_device_ptr list, we create one with map type 'alloc' and zero size
+ // section. It is the user fault if that was not mapped before. If there is
+ // no map information and the pointer is a struct member, then we defer the
+ // emission of that entry until the whole struct has been processed.
+ llvm::MapVector<CanonicalDeclPtr<const Decl>,
+ SmallVector<DeferredDevicePtrEntryTy, 4>>
+ DeferredInfo;
+ MapCombinedInfoTy UseDevicePtrCombinedInfo;
+
+ for (const auto *Cl : Clauses) {
+ const auto *C = dyn_cast<OMPUseDevicePtrClause>(Cl);
+ if (!C)
+ continue;
+ for (const auto L : C->component_lists()) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
+ std::get<1>(L);
+ assert(!Components.empty() &&
+ "Not expecting empty list of components!");
+ const ValueDecl *VD = Components.back().getAssociatedDeclaration();
+ VD = cast<ValueDecl>(VD->getCanonicalDecl());
+ const Expr *IE = Components.back().getAssociatedExpression();
+ // If the first component is a member expression, we have to look into
+ // 'this', which maps to null in the map of map information. Otherwise
+ // look directly for the information.
+ auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
+
+ // We potentially have map information for this declaration already.
+ // Look for the first set of components that refer to it.
+ if (It != Info.end()) {
+ bool Found = false;
+ for (auto &Data : It->second) {
+ auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) {
+ return MI.Components.back().getAssociatedDeclaration() == VD;
+ });
+ // If we found a map entry, signal that the pointer has to be
+ // returned and move on to the next declaration. Exclude cases where
+ // the base pointer is mapped as array subscript, array section or
+ // array shaping. The base address is passed as a pointer to base in
+ // this case and cannot be used as a base for use_device_ptr list
+ // item.
+ if (CI != Data.end()) {
+ auto PrevCI = std::next(CI->Components.rbegin());
+ const auto *VarD = dyn_cast<VarDecl>(VD);
+ if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
+ isa<MemberExpr>(IE) ||
+ !VD->getType().getNonReferenceType()->isPointerType() ||
+ PrevCI == CI->Components.rend() ||
+ isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
+ VarD->hasLocalStorage()) {
+ CI->ReturnDevicePointer = true;
+ Found = true;
+ break;
+ }
+ }
+ }
+ if (Found)
+ continue;
+ }
+
+ // We didn't find any match in our map information - generate a zero
+ // size array section - if the pointer is a struct member we defer this
+ // action until the whole struct has been processed.
+ if (isa<MemberExpr>(IE)) {
+ // Insert the pointer into Info to be processed by
+ // generateInfoForComponentList. Because it is a member pointer
+ // without a pointee, no entry will be generated for it, therefore
+ // we need to generate one after the whole struct has been processed.
+ // Nonetheless, generateInfoForComponentList must be called to take
+ // the pointer into account for the calculation of the range of the
+ // partial struct.
+ InfoGen(nullptr, Other, Components, OMPC_MAP_unknown, llvm::None,
+ llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(),
+ nullptr);
+ DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false);
+ } else {
+ llvm::Value *Ptr =
+ CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
+ UseDevicePtrCombinedInfo.Exprs.push_back(VD);
+ UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD);
+ UseDevicePtrCombinedInfo.Pointers.push_back(Ptr);
+ UseDevicePtrCombinedInfo.Sizes.push_back(
+ llvm::Constant::getNullValue(CGF.Int64Ty));
+ UseDevicePtrCombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM);
+ UseDevicePtrCombinedInfo.Mappers.push_back(nullptr);
+ }
+ }
+ }
+
+ // Look at the use_device_addr clause information and mark the existing map
+ // entries as such. If there is no map information for an entry in the
+ // use_device_addr list, we create one with map type 'alloc' and zero size
+ // section. It is the user fault if that was not mapped before. If there is
+ // no map information and the pointer is a struct member, then we defer the
+ // emission of that entry until the whole struct has been processed.
+ llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
+ for (const auto *Cl : Clauses) {
+ const auto *C = dyn_cast<OMPUseDeviceAddrClause>(Cl);
+ if (!C)
+ continue;
+ for (const auto L : C->component_lists()) {
+ assert(!std::get<1>(L).empty() &&
+ "Not expecting empty list of components!");
+ const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
+ if (!Processed.insert(VD).second)
+ continue;
+ VD = cast<ValueDecl>(VD->getCanonicalDecl());
+ const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
+ // If the first component is a member expression, we have to look into
+ // 'this', which maps to null in the map of map information. Otherwise
+ // look directly for the information.
+ auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
+
+ // We potentially have map information for this declaration already.
+ // Look for the first set of components that refer to it.
+ if (It != Info.end()) {
+ bool Found = false;
+ for (auto &Data : It->second) {
+ auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) {
+ return MI.Components.back().getAssociatedDeclaration() == VD;
+ });
+ // If we found a map entry, signal that the pointer has to be
+ // returned and move on to the next declaration.
+ if (CI != Data.end()) {
+ CI->ReturnDevicePointer = true;
+ Found = true;
+ break;
+ }
+ }
+ if (Found)
+ continue;
+ }
+
+ // We didn't find any match in our map information - generate a zero
+ // size array section - if the pointer is a struct member we defer this
+ // action until the whole struct has been processed.
+ if (isa<MemberExpr>(IE)) {
+ // Insert the pointer into Info to be processed by
+ // generateInfoForComponentList. Because it is a member pointer
+ // without a pointee, no entry will be generated for it, therefore
+ // we need to generate one after the whole struct has been processed.
+ // Nonetheless, generateInfoForComponentList must be called to take
+ // the pointer into account for the calculation of the range of the
+ // partial struct.
+ InfoGen(nullptr, Other, std::get<1>(L), OMPC_MAP_unknown, llvm::None,
+ llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(),
+ nullptr, nullptr, /*ForDeviceAddr=*/true);
+ DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true);
+ } else {
+ llvm::Value *Ptr;
+ if (IE->isGLValue())
+ Ptr = CGF.EmitLValue(IE).getPointer(CGF);
+ else
+ Ptr = CGF.EmitScalarExpr(IE);
+ CombinedInfo.Exprs.push_back(VD);
+ CombinedInfo.BasePointers.emplace_back(Ptr, VD);
+ CombinedInfo.Pointers.push_back(Ptr);
+ CombinedInfo.Sizes.push_back(
+ llvm::Constant::getNullValue(CGF.Int64Ty));
+ CombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM);
+ CombinedInfo.Mappers.push_back(nullptr);
+ }
+ }
+ }
+
+ for (const auto &Data : Info) {
+ StructRangeInfoTy PartialStruct;
+ // Temporary generated information.
+ MapCombinedInfoTy CurInfo;
+ const Decl *D = Data.first;
+ const ValueDecl *VD = cast_or_null<ValueDecl>(D);
+ for (const auto &M : Data.second) {
+ for (const MapInfo &L : M) {
+ assert(!L.Components.empty() &&
+ "Not expecting declaration with no component lists.");
+
+ // Remember the current base pointer index.
+ unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
+ CurInfo.NonContigInfo.IsNonContiguous =
+ L.Components.back().isNonContiguous();
+ generateInfoForComponentList(
+ L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
+ CurInfo, PartialStruct, /*IsFirstComponentList=*/false,
+ L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef);
+
+ // If this entry relates with a device pointer, set the relevant
+ // declaration and add the 'return pointer' flag.
+ if (L.ReturnDevicePointer) {
+ assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx &&
+ "Unexpected number of mapped base pointers.");
+
+ const ValueDecl *RelevantVD =
+ L.Components.back().getAssociatedDeclaration();
+ assert(RelevantVD &&
+ "No relevant declaration related with device pointer??");
+
+ CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(
+ RelevantVD);
+ CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
+ }
+ }
+ }
+
+ // Append any pending zero-length pointers which are struct members and
+ // used with use_device_ptr or use_device_addr.
+ auto CI = DeferredInfo.find(Data.first);
+ if (CI != DeferredInfo.end()) {
+ for (const DeferredDevicePtrEntryTy &L : CI->second) {
+ llvm::Value *BasePtr;
+ llvm::Value *Ptr;
+ if (L.ForDeviceAddr) {
+ if (L.IE->isGLValue())
+ Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
+ else
+ Ptr = this->CGF.EmitScalarExpr(L.IE);
+ BasePtr = Ptr;
+ // Entry is RETURN_PARAM. Also, set the placeholder value
+ // MEMBER_OF=FFFF so that the entry is later updated with the
+ // correct value of MEMBER_OF.
+ CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF);
+ } else {
+ BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
+ Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE),
+ L.IE->getExprLoc());
+ // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the
+ // placeholder value MEMBER_OF=FFFF so that the entry is later
+ // updated with the correct value of MEMBER_OF.
+ CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
+ OMP_MAP_MEMBER_OF);
+ }
+ CurInfo.Exprs.push_back(L.VD);
+ CurInfo.BasePointers.emplace_back(BasePtr, L.VD);
+ CurInfo.Pointers.push_back(Ptr);
+ CurInfo.Sizes.push_back(
+ llvm::Constant::getNullValue(this->CGF.Int64Ty));
+ CurInfo.Mappers.push_back(nullptr);
+ }
+ }
+ // If there is an entry in PartialStruct it means we have a struct with
+ // individual members mapped. Emit an extra combined entry.
+ if (PartialStruct.Base.isValid()) {
+ CurInfo.NonContigInfo.Dims.push_back(0);
+ emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD);
+ }
+
+ // We need to append the results of this capture to what we already
+ // have.
+ CombinedInfo.append(CurInfo);
+ }
+ // Append data for use_device_ptr clauses.
+ CombinedInfo.append(UseDevicePtrCombinedInfo);
+ }
+
public:
MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
: CurDir(&Dir), CGF(CGF) {
@@ -8254,17 +8886,24 @@
((CurTypes.back() & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF) &&
!PartialStruct.IsArraySection)
return;
+ Address LBAddr = PartialStruct.LowestElem.second;
+ Address HBAddr = PartialStruct.HighestElem.second;
+ if (PartialStruct.HasCompleteRecord) {
+ LBAddr = PartialStruct.LB;
+ HBAddr = PartialStruct.LB;
+ }
CombinedInfo.Exprs.push_back(VD);
// Base is the base of the struct
CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer());
// Pointer is the address of the lowest element
- llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
+ llvm::Value *LB = LBAddr.getPointer();
CombinedInfo.Pointers.push_back(LB);
// There should not be a mapper for a combined entry.
CombinedInfo.Mappers.push_back(nullptr);
// Size is (addr of {highest+1} element) - (addr of lowest element)
- llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
- llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
+ llvm::Value *HB = HBAddr.getPointer();
+ llvm::Value *HAddr =
+ CGF.Builder.CreateConstGEP1_32(HBAddr.getElementType(), HB, /*Idx0=*/1);
llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
@@ -8281,9 +8920,8 @@
return Type & OMP_MAP_PRESENT;
}))
CombinedInfo.Types.back() |= OMP_MAP_PRESENT;
- // Remove TARGET_PARAM flag from the first element if any.
- if (!CurTypes.empty())
- CurTypes.front() &= ~OMP_MAP_TARGET_PARAM;
+ // Remove TARGET_PARAM flag from the first element
+ (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
// All other current entries will be MEMBER_OF the combined entry
// (except for PTR_AND_OBJ entries which do not have a placeholder value
@@ -8303,297 +8941,10 @@
MapCombinedInfoTy &CombinedInfo,
const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
- // We have to process the component lists that relate with the same
- // declaration in a single chunk so that we can generate the map flags
- // correctly. Therefore, we organize all lists in a map.
- llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
-
- // Helper function to fill the information map for the different supported
- // clauses.
- auto &&InfoGen =
- [&Info, &SkipVarSet](
- const ValueDecl *D,
- OMPClauseMappableExprCommon::MappableExprComponentListRef L,
- OpenMPMapClauseKind MapType,
- ArrayRef<OpenMPMapModifierKind> MapModifiers,
- ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
- bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper,
- const Expr *VarRef = nullptr, bool ForDeviceAddr = false) {
- const ValueDecl *VD =
- D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
- if (SkipVarSet.count(VD))
- return;
- Info[VD].emplace_back(L, MapType, MapModifiers, MotionModifiers,
- ReturnDevicePointer, IsImplicit, Mapper, VarRef,
- ForDeviceAddr);
- };
-
assert(CurDir.is<const OMPExecutableDirective *>() &&
"Expect a executable directive");
const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
- for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
- const auto *EI = C->getVarRefs().begin();
- for (const auto L : C->component_lists()) {
- // The Expression is not correct if the mapping is implicit
- const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr;
- InfoGen(std::get<0>(L), std::get<1>(L), C->getMapType(),
- C->getMapTypeModifiers(), llvm::None,
- /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L),
- E);
- ++EI;
- }
- }
- for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) {
- const auto *EI = C->getVarRefs().begin();
- for (const auto L : C->component_lists()) {
- InfoGen(std::get<0>(L), std::get<1>(L), OMPC_MAP_to, llvm::None,
- C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
- C->isImplicit(), std::get<2>(L), *EI);
- ++EI;
- }
- }
- for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) {
- const auto *EI = C->getVarRefs().begin();
- for (const auto L : C->component_lists()) {
- InfoGen(std::get<0>(L), std::get<1>(L), OMPC_MAP_from, llvm::None,
- C->getMotionModifiers(), /*ReturnDevicePointer=*/false,
- C->isImplicit(), std::get<2>(L), *EI);
- ++EI;
- }
- }
-
- // Look at the use_device_ptr clause information and mark the existing map
- // entries as such. If there is no map information for an entry in the
- // use_device_ptr list, we create one with map type 'alloc' and zero size
- // section. It is the user fault if that was not mapped before. If there is
- // no map information and the pointer is a struct member, then we defer the
- // emission of that entry until the whole struct has been processed.
- llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
- DeferredInfo;
- MapCombinedInfoTy UseDevicePtrCombinedInfo;
-
- for (const auto *C :
- CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
- for (const auto L : C->component_lists()) {
- OMPClauseMappableExprCommon::MappableExprComponentListRef Components =
- std::get<1>(L);
- assert(!Components.empty() &&
- "Not expecting empty list of components!");
- const ValueDecl *VD = Components.back().getAssociatedDeclaration();
- VD = cast<ValueDecl>(VD->getCanonicalDecl());
- const Expr *IE = Components.back().getAssociatedExpression();
- // If the first component is a member expression, we have to look into
- // 'this', which maps to null in the map of map information. Otherwise
- // look directly for the information.
- auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
-
- // We potentially have map information for this declaration already.
- // Look for the first set of components that refer to it.
- if (It != Info.end()) {
- auto *CI = llvm::find_if(It->second, [VD](const MapInfo &MI) {
- return MI.Components.back().getAssociatedDeclaration() == VD;
- });
- // If we found a map entry, signal that the pointer has to be returned
- // and move on to the next declaration.
- // Exclude cases where the base pointer is mapped as array subscript,
- // array section or array shaping. The base address is passed as a
- // pointer to base in this case and cannot be used as a base for
- // use_device_ptr list item.
- if (CI != It->second.end()) {
- auto PrevCI = std::next(CI->Components.rbegin());
- const auto *VarD = dyn_cast<VarDecl>(VD);
- if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
- isa<MemberExpr>(IE) ||
- !VD->getType().getNonReferenceType()->isPointerType() ||
- PrevCI == CI->Components.rend() ||
- isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD ||
- VarD->hasLocalStorage()) {
- CI->ReturnDevicePointer = true;
- continue;
- }
- }
- }
-
- // We didn't find any match in our map information - generate a zero
- // size array section - if the pointer is a struct member we defer this
- // action until the whole struct has been processed.
- if (isa<MemberExpr>(IE)) {
- // Insert the pointer into Info to be processed by
- // generateInfoForComponentList. Because it is a member pointer
- // without a pointee, no entry will be generated for it, therefore
- // we need to generate one after the whole struct has been processed.
- // Nonetheless, generateInfoForComponentList must be called to take
- // the pointer into account for the calculation of the range of the
- // partial struct.
- InfoGen(nullptr, Components, OMPC_MAP_unknown, llvm::None, llvm::None,
- /*ReturnDevicePointer=*/false, C->isImplicit(), nullptr);
- DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false);
- } else {
- llvm::Value *Ptr =
- CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
- UseDevicePtrCombinedInfo.Exprs.push_back(VD);
- UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD);
- UseDevicePtrCombinedInfo.Pointers.push_back(Ptr);
- UseDevicePtrCombinedInfo.Sizes.push_back(
- llvm::Constant::getNullValue(CGF.Int64Ty));
- UseDevicePtrCombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM);
- UseDevicePtrCombinedInfo.Mappers.push_back(nullptr);
- }
- }
- }
-
- // Look at the use_device_addr clause information and mark the existing map
- // entries as such. If there is no map information for an entry in the
- // use_device_addr list, we create one with map type 'alloc' and zero size
- // section. It is the user fault if that was not mapped before. If there is
- // no map information and the pointer is a struct member, then we defer the
- // emission of that entry until the whole struct has been processed.
- llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
- for (const auto *C :
- CurExecDir->getClausesOfKind<OMPUseDeviceAddrClause>()) {
- for (const auto L : C->component_lists()) {
- assert(!std::get<1>(L).empty() &&
- "Not expecting empty list of components!");
- const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
- if (!Processed.insert(VD).second)
- continue;
- VD = cast<ValueDecl>(VD->getCanonicalDecl());
- const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
- // If the first component is a member expression, we have to look into
- // 'this', which maps to null in the map of map information. Otherwise
- // look directly for the information.
- auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
-
- // We potentially have map information for this declaration already.
- // Look for the first set of components that refer to it.
- if (It != Info.end()) {
- auto *CI = llvm::find_if(It->second, [VD](const MapInfo &MI) {
- return MI.Components.back().getAssociatedDeclaration() == VD;
- });
- // If we found a map entry, signal that the pointer has to be returned
- // and move on to the next declaration.
- if (CI != It->second.end()) {
- CI->ReturnDevicePointer = true;
- continue;
- }
- }
-
- // We didn't find any match in our map information - generate a zero
- // size array section - if the pointer is a struct member we defer this
- // action until the whole struct has been processed.
- if (isa<MemberExpr>(IE)) {
- // Insert the pointer into Info to be processed by
- // generateInfoForComponentList. Because it is a member pointer
- // without a pointee, no entry will be generated for it, therefore
- // we need to generate one after the whole struct has been processed.
- // Nonetheless, generateInfoForComponentList must be called to take
- // the pointer into account for the calculation of the range of the
- // partial struct.
- InfoGen(nullptr, std::get<1>(L), OMPC_MAP_unknown, llvm::None,
- llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(),
- nullptr, nullptr, /*ForDeviceAddr=*/true);
- DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true);
- } else {
- llvm::Value *Ptr;
- if (IE->isGLValue())
- Ptr = CGF.EmitLValue(IE).getPointer(CGF);
- else
- Ptr = CGF.EmitScalarExpr(IE);
- CombinedInfo.Exprs.push_back(VD);
- CombinedInfo.BasePointers.emplace_back(Ptr, VD);
- CombinedInfo.Pointers.push_back(Ptr);
- CombinedInfo.Sizes.push_back(
- llvm::Constant::getNullValue(CGF.Int64Ty));
- CombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM);
- CombinedInfo.Mappers.push_back(nullptr);
- }
- }
- }
-
- for (const auto &M : Info) {
- // Underlying variable declaration used in the map clause.
- const ValueDecl *VD = std::get<0>(M);
-
- // Temporary generated information.
- MapCombinedInfoTy CurInfo;
- StructRangeInfoTy PartialStruct;
-
- for (const MapInfo &L : M.second) {
- assert(!L.Components.empty() &&
- "Not expecting declaration with no component lists.");
-
- // Remember the current base pointer index.
- unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
- CurInfo.NonContigInfo.IsNonContiguous =
- L.Components.back().isNonContiguous();
- generateInfoForComponentList(
- L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, CurInfo,
- PartialStruct, /*IsFirstComponentList=*/false, L.IsImplicit,
- L.Mapper, L.ForDeviceAddr, VD, L.VarRef);
-
- // If this entry relates with a device pointer, set the relevant
- // declaration and add the 'return pointer' flag.
- if (L.ReturnDevicePointer) {
- assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx &&
- "Unexpected number of mapped base pointers.");
-
- const ValueDecl *RelevantVD =
- L.Components.back().getAssociatedDeclaration();
- assert(RelevantVD &&
- "No relevant declaration related with device pointer??");
-
- CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(
- RelevantVD);
- CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
- }
- }
-
- // Append any pending zero-length pointers which are struct members and
- // used with use_device_ptr or use_device_addr.
- auto CI = DeferredInfo.find(M.first);
- if (CI != DeferredInfo.end()) {
- for (const DeferredDevicePtrEntryTy &L : CI->second) {
- llvm::Value *BasePtr;
- llvm::Value *Ptr;
- if (L.ForDeviceAddr) {
- if (L.IE->isGLValue())
- Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
- else
- Ptr = this->CGF.EmitScalarExpr(L.IE);
- BasePtr = Ptr;
- // Entry is RETURN_PARAM. Also, set the placeholder value
- // MEMBER_OF=FFFF so that the entry is later updated with the
- // correct value of MEMBER_OF.
- CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF);
- } else {
- BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
- Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE),
- L.IE->getExprLoc());
- // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
- // value MEMBER_OF=FFFF so that the entry is later updated with the
- // correct value of MEMBER_OF.
- CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
- OMP_MAP_MEMBER_OF);
- }
- CurInfo.Exprs.push_back(L.VD);
- CurInfo.BasePointers.emplace_back(BasePtr, L.VD);
- CurInfo.Pointers.push_back(Ptr);
- CurInfo.Sizes.push_back(
- llvm::Constant::getNullValue(this->CGF.Int64Ty));
- CurInfo.Mappers.push_back(nullptr);
- }
- }
-
- // If there is an entry in PartialStruct it means we have a struct with
- // individual members mapped. Emit an extra combined entry.
- if (PartialStruct.Base.isValid())
- emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD);
-
- // We need to append the results of this capture to what we already have.
- CombinedInfo.append(CurInfo);
- }
- // Append data for use_device_ptr clauses.
- CombinedInfo.append(UseDevicePtrCombinedInfo);
+ generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet);
}
/// Generate all the base pointers, section pointers, sizes, map types, and
@@ -8603,62 +8954,7 @@
assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
"Expect a declare mapper directive");
const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
- // We have to process the component lists that relate with the same
- // declaration in a single chunk so that we can generate the map flags
- // correctly. Therefore, we organize all lists in a map.
- llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
-
- // Fill the information map for map clauses.
- for (const auto *C : CurMapperDir->clauselists()) {
- const auto *MC = cast<OMPMapClause>(C);
- const auto *EI = MC->getVarRefs().begin();
- for (const auto L : MC->component_lists()) {
- // The Expression is not correct if the mapping is implicit
- const Expr *E = (MC->getMapLoc().isValid()) ? *EI : nullptr;
- const ValueDecl *VD =
- std::get<0>(L) ? cast<ValueDecl>(std::get<0>(L)->getCanonicalDecl())
- : nullptr;
- // Get the corresponding user-defined mapper.
- Info[VD].emplace_back(std::get<1>(L), MC->getMapType(),
- MC->getMapTypeModifiers(), llvm::None,
- /*ReturnDevicePointer=*/false, MC->isImplicit(),
- std::get<2>(L), E);
- ++EI;
- }
- }
-
- for (const auto &M : Info) {
- // We need to know when we generate information for the first component
- // associated with a capture, because the mapping flags depend on it.
- bool IsFirstComponentList = true;
-
- // Underlying variable declaration used in the map clause.
- const ValueDecl *VD = std::get<0>(M);
-
- // Temporary generated information.
- MapCombinedInfoTy CurInfo;
- StructRangeInfoTy PartialStruct;
-
- for (const MapInfo &L : M.second) {
- assert(!L.Components.empty() &&
- "Not expecting declaration with no component lists.");
- generateInfoForComponentList(
- L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, CurInfo,
- PartialStruct, IsFirstComponentList, L.IsImplicit, L.Mapper,
- L.ForDeviceAddr, VD, L.VarRef);
- IsFirstComponentList = false;
- }
-
- // If there is an entry in PartialStruct it means we have a struct with
- // individual members mapped. Emit an extra combined entry.
- if (PartialStruct.Base.isValid()) {
- CurInfo.NonContigInfo.Dims.push_back(0);
- emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD);
- }
-
- // We need to append the results of this capture to what we already have.
- CombinedInfo.append(CurInfo);
- }
+ generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo);
}
/// Emit capture info for lambdas for variables captured by reference.
@@ -8812,6 +9108,25 @@
++EI;
}
}
+ llvm::stable_sort(DeclComponentLists, [](const MapData &LHS,
+ const MapData &RHS) {
+ ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
+ OpenMPMapClauseKind MapType = std::get<1>(RHS);
+ bool HasPresent = !MapModifiers.empty() &&
+ llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) {
+ return K == clang::OMPC_MAP_MODIFIER_present;
+ });
+ bool HasAllocs = MapType == OMPC_MAP_alloc;
+ MapModifiers = std::get<2>(RHS);
+ MapType = std::get<1>(LHS);
+ bool HasPresentR =
+ !MapModifiers.empty() &&
+ llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) {
+ return K == clang::OMPC_MAP_MODIFIER_present;
+ });
+ bool HasAllocsR = MapType == OMPC_MAP_alloc;
+ return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
+ });
// Find overlapping elements (including the offset from the base element).
llvm::SmallDenseMap<
@@ -8847,11 +9162,28 @@
if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
break;
}
- // Found overlapping if, at least for one component, reached the head of
- // the components list.
+ // Found overlapping if, at least for one component, reached the head
+ // of the components list.
if (CI == CE || SI == SE) {
- assert((CI != CE || SI != SE) &&
- "Unexpected full match of the mapping components.");
+ // Ignore it if it is the same component.
+ if (CI == CE && SI == SE)
+ continue;
+ const auto It = (SI == SE) ? CI : SI;
+ // If one component is a pointer and another one is a kind of
+ // dereference of this pointer (array subscript, section, dereference,
+ // etc.), it is not an overlapping.
+ // Same, if one component is a base and another component is a
+ // dereferenced pointer memberexpr with the same base.
+ if (!isa<MemberExpr>(It->getAssociatedExpression()) ||
+ (std::prev(It)->getAssociatedDeclaration() &&
+ std::prev(It)
+ ->getAssociatedDeclaration()
+ ->getType()
+ ->isPointerType()) ||
+ (It->getAssociatedDeclaration() &&
+ It->getAssociatedDeclaration()->getType()->isPointerType() &&
+ std::next(It) != CE && std::next(It) != SE))
+ continue;
const MapData &BaseData = CI == CE ? L : L1;
OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
SI == SE ? Components : Components1;
@@ -8863,16 +9195,22 @@
// Sort the overlapped elements for each item.
llvm::SmallVector<const FieldDecl *, 4> Layout;
if (!OverlappedData.empty()) {
- if (const auto *CRD =
- VD->getType().getCanonicalType()->getAsCXXRecordDecl())
+ const Type *BaseType = VD->getType().getCanonicalType().getTypePtr();
+ const Type *OrigType = BaseType->getPointeeOrArrayElementType();
+ while (BaseType != OrigType) {
+ BaseType = OrigType->getCanonicalTypeInternal().getTypePtr();
+ OrigType = BaseType->getPointeeOrArrayElementType();
+ }
+
+ if (const auto *CRD = BaseType->getAsCXXRecordDecl())
getPlainLayout(CRD, Layout, /*AsBase=*/false);
else {
- const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
+ const auto *RD = BaseType->getAsRecordDecl();
Layout.append(RD->field_begin(), RD->field_end());
}
}
for (auto &Pair : OverlappedData) {
- llvm::sort(
+ llvm::stable_sort(
Pair.getSecond(),
[&Layout](
OMPClauseMappableExprCommon::MappableExprComponentListRef First,
@@ -8904,7 +9242,7 @@
const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
if (FD1->getParent() == FD2->getParent())
return FD1->getFieldIndex() < FD2->getFieldIndex();
- const auto It =
+ const auto *It =
llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
return FD == FD1 || FD == FD2;
});
@@ -8914,6 +9252,7 @@
// Associated with a capture, because the mapping flags depend on it.
// Go through all of the elements with the overlapped elements.
+ bool IsFirstComponentList = true;
for (const auto &Pair : OverlappedData) {
const MapData &L = *Pair.getFirst();
OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
@@ -8926,14 +9265,13 @@
L;
ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
OverlappedComponents = Pair.getSecond();
- bool IsFirstComponentList = true;
generateInfoForComponentList(
MapType, MapModifiers, llvm::None, Components, CombinedInfo,
PartialStruct, IsFirstComponentList, IsImplicit, Mapper,
/*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents);
+ IsFirstComponentList = false;
}
// Go through other elements without overlapped elements.
- bool IsFirstComponentList = OverlappedData.empty();
for (const MapData &L : DeclComponentLists) {
OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
OpenMPMapClauseKind MapType;
@@ -9002,30 +9340,15 @@
CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
const VarDecl *VD = CI.getCapturedVar();
auto I = FirstPrivateDecls.find(VD);
- if (I != FirstPrivateDecls.end() &&
- VD->getType().isConstant(CGF.getContext())) {
- llvm::Constant *Addr =
- CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
- // Copy the value of the original variable to the new global copy.
- CGF.Builder.CreateMemCpy(
- CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF),
- Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
- CombinedInfo.Sizes.back(), /*IsVolatile=*/false);
- // Use new global variable as the base pointers.
- CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
- CombinedInfo.BasePointers.push_back(Addr);
- CombinedInfo.Pointers.push_back(Addr);
+ CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
+ CombinedInfo.BasePointers.push_back(CV);
+ if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
+ Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
+ CV, ElementType, CGF.getContext().getDeclAlign(VD),
+ AlignmentSource::Decl));
+ CombinedInfo.Pointers.push_back(PtrAddr.getPointer());
} else {
- CombinedInfo.Exprs.push_back(VD->getCanonicalDecl());
- CombinedInfo.BasePointers.push_back(CV);
- if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
- Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
- CV, ElementType, CGF.getContext().getDeclAlign(VD),
- AlignmentSource::Decl));
- CombinedInfo.Pointers.push_back(PtrAddr.getPointer());
- } else {
- CombinedInfo.Pointers.push_back(CV);
- }
+ CombinedInfo.Pointers.push_back(CV);
}
if (I != FirstPrivateDecls.end())
IsImplicit = I->getSecond();
@@ -9138,7 +9461,6 @@
SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FileName, ExprName.c_str(),
Line, Column);
}
-
return SrcLocStr;
}
@@ -9219,15 +9541,10 @@
// fill arrays. Instead, we create an array constant.
SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0);
llvm::copy(CombinedInfo.Types, Mapping.begin());
- llvm::Constant *MapTypesArrayInit =
- llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
std::string MaptypesName =
CGM.getOpenMPRuntime().getName({"offload_maptypes"});
- auto *MapTypesArrayGbl = new llvm::GlobalVariable(
- CGM.getModule(), MapTypesArrayInit->getType(),
- /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
- MapTypesArrayInit, MaptypesName);
- MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ auto *MapTypesArrayGbl =
+ OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName);
Info.MapTypesArray = MapTypesArrayGbl;
// The information types are only built if there is debug information
@@ -9241,17 +9558,10 @@
};
SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size());
llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap);
-
- llvm::Constant *MapNamesArrayInit = llvm::ConstantArray::get(
- llvm::ArrayType::get(
- llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo(),
- CombinedInfo.Exprs.size()),
- InfoMap);
- auto *MapNamesArrayGbl = new llvm::GlobalVariable(
- CGM.getModule(), MapNamesArrayInit->getType(),
- /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
- MapNamesArrayInit,
- CGM.getOpenMPRuntime().getName({"offload_mapnames"}));
+ std::string MapnamesName =
+ CGM.getOpenMPRuntime().getName({"offload_mapnames"});
+ auto *MapNamesArrayGbl =
+ OMPBuilder.createOffloadMapnames(InfoMap, MapnamesName);
Info.MapNamesArray = MapNamesArrayGbl;
}
@@ -9266,15 +9576,8 @@
}
}
if (EndMapTypesDiffer) {
- MapTypesArrayInit =
- llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
- MaptypesName = CGM.getOpenMPRuntime().getName({"offload_maptypes"});
- MapTypesArrayGbl = new llvm::GlobalVariable(
- CGM.getModule(), MapTypesArrayInit->getType(),
- /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
- MapTypesArrayInit, MaptypesName);
- MapTypesArrayGbl->setUnnamedAddr(
- llvm::GlobalValue::UnnamedAddr::Global);
+ MapTypesArrayGbl =
+ OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName);
Info.MapTypesArrayEnd = MapTypesArrayGbl;
}
}
@@ -9463,6 +9766,8 @@
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
@@ -9520,14 +9825,16 @@
/// void *base, void *begin,
/// int64_t size, int64_t type,
/// void *name = nullptr) {
-/// // Allocate space for an array section first.
-/// if (size > 1 && !maptype.IsDelete)
+/// // Allocate space for an array section first or add a base/begin for
+/// // pointer dereference.
+/// if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) &&
+/// !maptype.IsDelete)
/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
-/// size*sizeof(Ty), clearToFrom(type));
+/// size*sizeof(Ty), clearToFromMember(type));
/// // Map members.
/// for (unsigned i = 0; i < size; i++) {
/// // For each component specified by this mapper:
-/// for (auto c : all_components) {
+/// for (auto c : begin[i]->all_components) {
/// if (c.hasMapper())
/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
/// c.arg_type, c.arg_name);
@@ -9540,7 +9847,7 @@
/// // Delete the array section.
/// if (size > 1 && maptype.IsDelete)
/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
-/// size*sizeof(Ty), clearToFrom(type));
+/// size*sizeof(Ty), clearToFromMember(type));
/// }
/// \endcode
void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
@@ -9590,20 +9897,10 @@
// Start the mapper function code generation.
CodeGenFunction MapperCGF(CGM);
MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
- // Compute the starting and end addreses of array elements.
+ // Compute the starting and end addresses of array elements.
llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
C.getPointerType(Int64Ty), Loc);
- // Convert the size in bytes into the number of array elements.
- Size = MapperCGF.Builder.CreateExactUDiv(
- Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
- llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
- MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
- CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
- llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
- llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
- MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
- C.getPointerType(Int64Ty), Loc);
// Prepare common arguments for array initiation and deletion.
llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
MapperCGF.GetAddrOfLocalVar(&HandleArg),
@@ -9614,12 +9911,25 @@
llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
MapperCGF.GetAddrOfLocalVar(&BeginArg),
/*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
+ // Convert the size in bytes into the number of array elements.
+ Size = MapperCGF.Builder.CreateExactUDiv(
+ Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
+ llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
+ BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy));
+ llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(
+ PtrBegin->getType()->getPointerElementType(), PtrBegin, Size);
+ llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
+ MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
+ C.getPointerType(Int64Ty), Loc);
+ llvm::Value *MapName = MapperCGF.EmitLoadOfScalar(
+ MapperCGF.GetAddrOfLocalVar(&NameArg),
+ /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
// Emit array initiation if this is an array section and \p MapType indicates
// that memory allocation is required.
llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
- ElementSize, HeadBB, /*IsInit=*/true);
+ MapName, ElementSize, HeadBB, /*IsInit=*/true);
// Emit a for loop to iterate through SizeArg of elements and map all of them.
@@ -9645,11 +9955,7 @@
.alignmentOfArrayElement(ElementSize));
// Privatize the declared variable of mapper to be the current array element.
CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
- Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
- return MapperCGF
- .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
- .getAddress(MapperCGF);
- });
+ Scope.addPrivate(MapperVarDecl, [PtrCurrent]() { return PtrCurrent; });
(void)Scope.Privatize();
// Get map clause information. Fill up the arrays with all mapped variables.
@@ -9681,28 +9987,9 @@
: emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]);
// Extract the MEMBER_OF field from the map type.
- llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
- MapperCGF.EmitBlock(MemberBB);
llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]);
- llvm::Value *Member = MapperCGF.Builder.CreateAnd(
- OriMapType,
- MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
- llvm::BasicBlock *MemberCombineBB =
- MapperCGF.createBasicBlock("omp.member.combine");
- llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
- llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
- MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
- // Add the number of pre-existing components to the MEMBER_OF field if it
- // is valid.
- MapperCGF.EmitBlock(MemberCombineBB);
- llvm::Value *CombinedMember =
+ llvm::Value *MemberMapType =
MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
- // Do nothing if it is not a member of previous components.
- MapperCGF.EmitBlock(TypeBB);
- llvm::PHINode *MemberMapType =
- MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
- MemberMapType->addIncoming(OriMapType, MemberBB);
- MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
// Combine the map type inherited from user-defined mapper with that
// specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
@@ -9787,8 +10074,9 @@
// Update the pointer to point to the next element that needs to be mapped,
// and check whether we have mapped all elements.
+ llvm::Type *ElemTy = PtrPHI->getType()->getPointerElementType();
llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
- PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
+ ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
PtrPHI->addIncoming(PtrNext, LastBB);
llvm::Value *IsDone =
MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
@@ -9799,7 +10087,7 @@
// Emit array deletion if this is an array section and \p MapType indicates
// that deletion is required.
emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
- ElementSize, DoneBB, /*IsInit=*/false);
+ MapName, ElementSize, DoneBB, /*IsInit=*/false);
// Emit the function exit block.
MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
@@ -9820,32 +10108,40 @@
void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
- CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
+ llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB,
+ bool IsInit) {
StringRef Prefix = IsInit ? ".init" : ".del";
// Evaluate if this is an array section.
- llvm::BasicBlock *IsDeleteBB =
- MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"}));
llvm::BasicBlock *BodyBB =
MapperCGF.createBasicBlock(getName({"omp.array", Prefix}));
- llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
+ llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT(
Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
- MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
-
- // Evaluate if we are going to delete this section.
- MapperCGF.EmitBlock(IsDeleteBB);
llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
MapType,
MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
llvm::Value *DeleteCond;
+ llvm::Value *Cond;
if (IsInit) {
+ // base != begin?
+ llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateIsNotNull(
+ MapperCGF.Builder.CreatePtrDiff(Base, Begin));
+ // IsPtrAndObj?
+ llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd(
+ MapType,
+ MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_PTR_AND_OBJ));
+ PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit);
+ BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit);
+ Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin);
DeleteCond = MapperCGF.Builder.CreateIsNull(
DeleteBit, getName({"omp.array", Prefix, ".delete"}));
} else {
+ Cond = IsArray;
DeleteCond = MapperCGF.Builder.CreateIsNotNull(
DeleteBit, getName({"omp.array", Prefix, ".delete"}));
}
- MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
+ Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond);
+ MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB);
MapperCGF.EmitBlock(BodyBB);
// Get the array size by multiplying element size and element number (i.e., \p
@@ -9858,12 +10154,14 @@
MapType,
MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
MappableExprsHandler::OMP_MAP_FROM)));
- llvm::Value *MapNameArg = llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
+ MapTypeArg = MapperCGF.Builder.CreateOr(
+ MapTypeArg,
+ MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_IMPLICIT));
// Call the runtime API __tgt_push_mapper_component to fill up the runtime
// data structure.
llvm::Value *OffloadingArgs[] = {Handle, Base, Begin,
- ArraySize, MapTypeArg, MapNameArg};
+ ArraySize, MapTypeArg, MapName};
MapperCGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
OMPRTL___tgt_push_mapper_component),
@@ -10024,18 +10322,27 @@
// passed to the runtime library - a 32-bit integer with the value zero.
assert(NumThreads && "Thread limit expression should be available along "
"with number of teams.");
- llvm::Value *OffloadingArgs[] = {RTLoc,
- DeviceID,
- OutlinedFnID,
- PointerNum,
- InputInfo.BasePointersArray.getPointer(),
- InputInfo.PointersArray.getPointer(),
- InputInfo.SizesArray.getPointer(),
- MapTypesArray,
- MapNamesArray,
- InputInfo.MappersArray.getPointer(),
- NumTeams,
- NumThreads};
+ SmallVector<llvm::Value *> OffloadingArgs = {
+ RTLoc,
+ DeviceID,
+ OutlinedFnID,
+ PointerNum,
+ InputInfo.BasePointersArray.getPointer(),
+ InputInfo.PointersArray.getPointer(),
+ InputInfo.SizesArray.getPointer(),
+ MapTypesArray,
+ MapNamesArray,
+ InputInfo.MappersArray.getPointer(),
+ NumTeams,
+ NumThreads};
+ if (HasNowait) {
+ // Add int32_t depNum = 0, void *depList = nullptr, int32_t
+ // noAliasDepNum = 0, void *noAliasDepList = nullptr.
+ OffloadingArgs.push_back(CGF.Builder.getInt32(0));
+ OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy));
+ OffloadingArgs.push_back(CGF.Builder.getInt32(0));
+ OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy));
+ }
Return = CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), HasNowait
@@ -10043,16 +10350,25 @@
: OMPRTL___tgt_target_teams_mapper),
OffloadingArgs);
} else {
- llvm::Value *OffloadingArgs[] = {RTLoc,
- DeviceID,
- OutlinedFnID,
- PointerNum,
- InputInfo.BasePointersArray.getPointer(),
- InputInfo.PointersArray.getPointer(),
- InputInfo.SizesArray.getPointer(),
- MapTypesArray,
- MapNamesArray,
- InputInfo.MappersArray.getPointer()};
+ SmallVector<llvm::Value *> OffloadingArgs = {
+ RTLoc,
+ DeviceID,
+ OutlinedFnID,
+ PointerNum,
+ InputInfo.BasePointersArray.getPointer(),
+ InputInfo.PointersArray.getPointer(),
+ InputInfo.SizesArray.getPointer(),
+ MapTypesArray,
+ MapNamesArray,
+ InputInfo.MappersArray.getPointer()};
+ if (HasNowait) {
+ // Add int32_t depNum = 0, void *depList = nullptr, int32_t
+ // noAliasDepNum = 0, void *noAliasDepList = nullptr.
+ OffloadingArgs.push_back(CGF.Builder.getInt32(0));
+ OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy));
+ OffloadingArgs.push_back(CGF.Builder.getInt32(0));
+ OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy));
+ }
Return = CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper
@@ -10102,7 +10418,7 @@
llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
auto RI = CS.getCapturedRecordDecl()->field_begin();
- auto CV = CapturedVars.begin();
+ auto *CV = CapturedVars.begin();
for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
CE = CS.capture_end();
CI != CE; ++CI, ++RI, ++CV) {
@@ -10149,9 +10465,12 @@
// If there is an entry in PartialStruct it means we have a struct with
// individual members mapped. Emit an extra combined entry.
- if (PartialStruct.Base.isValid())
- MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
- nullptr, /*NoTargetParam=*/false);
+ if (PartialStruct.Base.isValid()) {
+ CombinedInfo.append(PartialStruct.PreliminaryMapData);
+ MEHandler.emitCombinedEntry(
+ CombinedInfo, CurInfo.Types, PartialStruct, nullptr,
+ !PartialStruct.PreliminaryMapData.BasePointers.empty());
+ }
// We need to append the results of this capture to what we already have.
CombinedInfo.append(CurInfo);
@@ -10297,6 +10616,8 @@
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
@@ -10362,17 +10683,28 @@
scanForTargetRegionsFunctions(II, ParentName);
}
+static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice) {
+ Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
+ OMPDeclareTargetDeclAttr::getDeviceType(VD);
+ if (!DevTy)
+ return false;
+ // Do not emit device_type(nohost) functions for the host.
+ if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
+ return true;
+ // Do not emit device_type(host) functions for the device.
+ if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
+ return true;
+ return false;
+}
+
bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
// If emitting code for the host, we do not process FD here. Instead we do
// the normal code generation.
if (!CGM.getLangOpts().OpenMPIsDevice) {
- if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
- Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
- OMPDeclareTargetDeclAttr::getDeviceType(FD);
- // Do not emit device_type(nohost) functions for the host.
- if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
+ if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl()))
+ if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD),
+ CGM.getLangOpts().OpenMPIsDevice))
return true;
- }
return false;
}
@@ -10381,10 +10713,8 @@
if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
StringRef Name = CGM.getMangledName(GD);
scanForTargetRegionsFunctions(FD->getBody(), Name);
- Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
- OMPDeclareTargetDeclAttr::getDeviceType(FD);
- // Do not emit device_type(nohost) functions for the host.
- if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
+ if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD),
+ CGM.getLangOpts().OpenMPIsDevice))
return true;
}
@@ -10394,6 +10724,10 @@
}
bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
+ if (isAssumedToBeNotEmitted(cast<ValueDecl>(GD.getDecl()),
+ CGM.getLangOpts().OpenMPIsDevice))
+ return true;
+
if (!CGM.getLangOpts().OpenMPIsDevice)
return false;
@@ -10427,45 +10761,18 @@
return false;
}
-llvm::Constant *
-CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
- const VarDecl *VD) {
- assert(VD->getType().isConstant(CGM.getContext()) &&
- "Expected constant variable.");
- StringRef VarName;
- llvm::Constant *Addr;
- llvm::GlobalValue::LinkageTypes Linkage;
- QualType Ty = VD->getType();
- SmallString<128> Buffer;
- {
- unsigned DeviceID;
- unsigned FileID;
- unsigned Line;
- getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
- FileID, Line);
- llvm::raw_svector_ostream OS(Buffer);
- OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
- << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
- VarName = OS.str();
- }
- Linkage = llvm::GlobalValue::InternalLinkage;
- Addr =
- getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
- getDefaultFirstprivateAddressSpace());
- cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
- CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
- CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
- OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
- VarName, Addr, VarSize,
- OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
- return Addr;
-}
-
void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
llvm::Constant *Addr) {
if (CGM.getLangOpts().OMPTargetTriples.empty() &&
!CGM.getLangOpts().OpenMPIsDevice)
return;
+
+ // If we have host/nohost variables, they do not need to be registered.
+ Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
+ OMPDeclareTargetDeclAttr::getDeviceType(VD);
+ if (DevTy && DevTy.getValue() != OMPDeclareTargetDeclAttr::DT_Any)
+ return;
+
llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (!Res) {
@@ -10496,6 +10803,10 @@
Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
// Temp solution to prevent optimizations of the internal variables.
if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
+ // Do not create a "ref-variable" if the original is not also available
+ // on the host.
+ if (!OffloadEntriesInfoManager.hasDeviceGlobalVarEntryInfo(VarName))
+ return;
std::string RefName = getName({VarName, "ref"});
if (!CGM.GetGlobalValue(RefName)) {
llvm::Constant *AddrRef =
@@ -10979,6 +11290,8 @@
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
@@ -11867,13 +12180,14 @@
// Cleanup action for allocate support.
class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
llvm::FunctionCallee RTLFn;
- unsigned LocEncoding;
+ SourceLocation::UIntTy LocEncoding;
Address Addr;
const Expr *Allocator;
public:
- OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, unsigned LocEncoding,
- Address Addr, const Expr *Allocator)
+ OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
+ SourceLocation::UIntTy LocEncoding, Address Addr,
+ const Expr *Allocator)
: RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr),
Allocator(Allocator) {}
void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
@@ -11951,8 +12265,8 @@
CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII(
CodeGenFunction &CGF,
- const llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
- std::pair<Address, Address>> &LocalVars)
+ const llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
+ std::pair<Address, Address>> &LocalVars)
: CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
if (!NeedToPush)
return;
@@ -12473,6 +12787,13 @@
llvm_unreachable("Not supported in SIMD-only mode");
}
+void CGOpenMPSIMDRuntime::emitMaskedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MasterOpGen,
+ SourceLocation Loc,
+ const Expr *Filter) {
+ llvm_unreachable("Not supported in SIMD-only mode");
+}
+
void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
SourceLocation Loc) {
llvm_unreachable("Not supported in SIMD-only mode");
diff --git a/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.h b/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.h
index b8bb6d8..c24648a 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -73,7 +73,6 @@
CodeGenTy Callback;
mutable PrePostActionTy *PrePostAction;
RegionCodeGenTy() = delete;
- RegionCodeGenTy &operator=(const RegionCodeGenTy &) = delete;
template <typename Callable>
static void CallbackFn(intptr_t CodeGen, CodeGenFunction &CGF,
PrePostActionTy &Action) {
@@ -254,8 +253,8 @@
public:
UntiedTaskLocalDeclsRAII(
CodeGenFunction &CGF,
- const llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
- std::pair<Address, Address>> &LocalVars);
+ const llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
+ std::pair<Address, Address>> &LocalVars);
~UntiedTaskLocalDeclsRAII();
};
@@ -341,6 +340,35 @@
llvm::Value *emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc,
unsigned Flags = 0);
+ /// Emit the number of teams for a target directive. Inspect the num_teams
+ /// clause associated with a teams construct combined or closely nested
+ /// with the target directive.
+ ///
+ /// Emit a team of size one for directives such as 'target parallel' that
+ /// have no associated teams construct.
+ ///
+ /// Otherwise, return nullptr.
+ const Expr *getNumTeamsExprForTargetDirective(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ int32_t &DefaultVal);
+ llvm::Value *emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D);
+ /// Emit the number of threads for a target directive. Inspect the
+ /// thread_limit clause associated with a teams construct combined or closely
+ /// nested with the target directive.
+ ///
+ /// Emit the num_threads clause for directives such as 'target parallel' that
+ /// have no associated teams construct.
+ ///
+ /// Otherwise, return nullptr.
+ const Expr *
+ getNumThreadsExprForTargetDirective(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D,
+ int32_t &DefaultVal);
+ llvm::Value *
+ emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
+ const OMPExecutableDirective &D);
+
/// Returns pointer to ident_t type.
llvm::Type *getIdentTyPointerTy();
@@ -724,8 +752,8 @@
llvm::SmallVector<NontemporalDeclsSet, 4> NontemporalDeclsStack;
using UntiedLocalVarsAddressesMap =
- llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
- std::pair<Address, Address>>;
+ llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
+ std::pair<Address, Address>>;
llvm::SmallVector<UntiedLocalVarsAddressesMap, 4> UntiedLocalVarsStack;
/// Stack for list of addresses of declarations in current context marked as
@@ -824,7 +852,8 @@
void emitUDMapperArrayInitOrDel(CodeGenFunction &MapperCGF,
llvm::Value *Handle, llvm::Value *BasePtr,
llvm::Value *Ptr, llvm::Value *Size,
- llvm::Value *MapType, CharUnits ElementSize,
+ llvm::Value *MapType, llvm::Value *MapName,
+ CharUnits ElementSize,
llvm::BasicBlock *ExitBB, bool IsInit);
struct TaskResultTy {
@@ -862,10 +891,6 @@
llvm::Function *TaskFunction, QualType SharedsTy,
Address Shareds, const OMPTaskDataTy &Data);
- /// Returns default address space for the constant firstprivates, 0 by
- /// default.
- virtual unsigned getDefaultFirstprivateAddressSpace() const { return 0; }
-
/// Emit code that pushes the trip count of loops associated with constructs
/// 'target teams distribute' and 'teams distribute parallel for'.
/// \param SizeEmitter Emits the int64 value for the number of iterations of
@@ -1011,6 +1036,14 @@
const RegionCodeGenTy &MasterOpGen,
SourceLocation Loc);
+ /// Emits a masked region.
+ /// \param MaskedOpGen Generator for the statement associated with the given
+ /// masked region.
+ virtual void emitMaskedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MaskedOpGen,
+ SourceLocation Loc,
+ const Expr *Filter = nullptr);
+
/// Emits code for a taskyield directive.
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc);
@@ -1583,11 +1616,6 @@
virtual void registerTargetGlobalVariable(const VarDecl *VD,
llvm::Constant *Addr);
- /// Registers provided target firstprivate variable as global on the
- /// target.
- llvm::Constant *registerTargetFirstprivateCopy(CodeGenFunction &CGF,
- const VarDecl *VD);
-
/// Emit the global \a GD if it is meaningful for the target. Returns
/// if it was emitted successfully.
/// \param GD Global to scan.
@@ -1983,6 +2011,17 @@
const RegionCodeGenTy &MasterOpGen,
SourceLocation Loc) override;
+ /// Emits a masked region.
+ /// \param MaskedOpGen Generator for the statement associated with the given
+ /// masked region.
+ void emitMaskedRegion(CodeGenFunction &CGF,
+ const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc,
+ const Expr *Filter = nullptr) override;
+
+ /// Emits a masked region.
+ /// \param MaskedOpGen Generator for the statement associated with the given
+ /// masked region.
+
/// Emits code for a taskyield directive.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override;
diff --git a/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
index 9c8c7b8..63feced 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
@@ -553,57 +553,6 @@
"nvptx_lane_id");
}
-/// Get the value of the thread_limit clause in the teams directive.
-/// For the 'generic' execution mode, the runtime encodes thread_limit in
-/// the launch parameters, always starting thread_limit+warpSize threads per
-/// CTA. The threads in the last warp are reserved for master execution.
-/// For the 'spmd' execution mode, all threads in a CTA are part of the team.
-static llvm::Value *getThreadLimit(CodeGenFunction &CGF,
- bool IsInSPMDExecutionMode = false) {
- CGBuilderTy &Bld = CGF.Builder;
- auto &RT = static_cast<CGOpenMPRuntimeGPU &>(CGF.CGM.getOpenMPRuntime());
- return IsInSPMDExecutionMode
- ? RT.getGPUNumThreads(CGF)
- : Bld.CreateNUWSub(RT.getGPUNumThreads(CGF),
- RT.getGPUWarpSize(CGF), "thread_limit");
-}
-
-/// Get the thread id of the OMP master thread.
-/// The master thread id is the first thread (lane) of the last warp in the
-/// GPU block. Warp size is assumed to be some power of 2.
-/// Thread id is 0 indexed.
-/// E.g: If NumThreads is 33, master id is 32.
-/// If NumThreads is 64, master id is 32.
-/// If NumThreads is 1024, master id is 992.
-static llvm::Value *getMasterThreadID(CodeGenFunction &CGF) {
- CGBuilderTy &Bld = CGF.Builder;
- auto &RT = static_cast<CGOpenMPRuntimeGPU &>(CGF.CGM.getOpenMPRuntime());
- llvm::Value *NumThreads = RT.getGPUNumThreads(CGF);
- // We assume that the warp size is a power of 2.
- llvm::Value *Mask = Bld.CreateNUWSub(RT.getGPUWarpSize(CGF), Bld.getInt32(1));
-
- return Bld.CreateAnd(Bld.CreateNUWSub(NumThreads, Bld.getInt32(1)),
- Bld.CreateNot(Mask), "master_tid");
-}
-
-CGOpenMPRuntimeGPU::WorkerFunctionState::WorkerFunctionState(
- CodeGenModule &CGM, SourceLocation Loc)
- : WorkerFn(nullptr), CGFI(CGM.getTypes().arrangeNullaryFunction()),
- Loc(Loc) {
- createWorkerFunction(CGM);
-}
-
-void CGOpenMPRuntimeGPU::WorkerFunctionState::createWorkerFunction(
- CodeGenModule &CGM) {
- // Create an worker function with no arguments.
-
- WorkerFn = llvm::Function::Create(
- CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
- /*placeholder=*/"_worker", &CGM.getModule());
- CGM.SetInternalFunctionAttributes(GlobalDecl(), WorkerFn, CGFI);
- WorkerFn->setDoesNotRecurse();
-}
-
CGOpenMPRuntimeGPU::ExecutionMode
CGOpenMPRuntimeGPU::getExecutionMode() const {
return CurrentExecutionMode;
@@ -1067,23 +1016,19 @@
const RegionCodeGenTy &CodeGen) {
ExecutionRuntimeModesRAII ModeRAII(CurrentExecutionMode);
EntryFunctionState EST;
- WorkerFunctionState WST(CGM, D.getBeginLoc());
- Work.clear();
WrapperFunctionsMap.clear();
// Emit target region as a standalone region.
class NVPTXPrePostActionTy : public PrePostActionTy {
CGOpenMPRuntimeGPU::EntryFunctionState &EST;
- CGOpenMPRuntimeGPU::WorkerFunctionState &WST;
public:
- NVPTXPrePostActionTy(CGOpenMPRuntimeGPU::EntryFunctionState &EST,
- CGOpenMPRuntimeGPU::WorkerFunctionState &WST)
- : EST(EST), WST(WST) {}
+ NVPTXPrePostActionTy(CGOpenMPRuntimeGPU::EntryFunctionState &EST)
+ : EST(EST) {}
void Enter(CodeGenFunction &CGF) override {
auto &RT =
static_cast<CGOpenMPRuntimeGPU &>(CGF.CGM.getOpenMPRuntime());
- RT.emitNonSPMDEntryHeader(CGF, EST, WST);
+ RT.emitKernelInit(CGF, EST, /* IsSPMD */ false);
// Skip target region initialization.
RT.setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true);
}
@@ -1091,106 +1036,33 @@
auto &RT =
static_cast<CGOpenMPRuntimeGPU &>(CGF.CGM.getOpenMPRuntime());
RT.clearLocThreadIdInsertPt(CGF);
- RT.emitNonSPMDEntryFooter(CGF, EST);
+ RT.emitKernelDeinit(CGF, EST, /* IsSPMD */ false);
}
- } Action(EST, WST);
+ } Action(EST);
CodeGen.setAction(Action);
IsInTTDRegion = true;
- // Reserve place for the globalized memory.
- GlobalizedRecords.emplace_back();
- if (!KernelStaticGlobalized) {
- KernelStaticGlobalized = new llvm::GlobalVariable(
- CGM.getModule(), CGM.VoidPtrTy, /*isConstant=*/false,
- llvm::GlobalValue::InternalLinkage,
- llvm::UndefValue::get(CGM.VoidPtrTy),
- "_openmp_kernel_static_glob_rd$ptr", /*InsertBefore=*/nullptr,
- llvm::GlobalValue::NotThreadLocal,
- CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared));
- }
emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
IsOffloadEntry, CodeGen);
IsInTTDRegion = false;
-
- // Now change the name of the worker function to correspond to this target
- // region's entry function.
- WST.WorkerFn->setName(Twine(OutlinedFn->getName(), "_worker"));
-
- // Create the worker function
- emitWorkerFunction(WST);
}
-// Setup NVPTX threads for master-worker OpenMP scheme.
-void CGOpenMPRuntimeGPU::emitNonSPMDEntryHeader(CodeGenFunction &CGF,
- EntryFunctionState &EST,
- WorkerFunctionState &WST) {
+void CGOpenMPRuntimeGPU::emitKernelInit(CodeGenFunction &CGF,
+ EntryFunctionState &EST, bool IsSPMD) {
CGBuilderTy &Bld = CGF.Builder;
-
- llvm::BasicBlock *WorkerBB = CGF.createBasicBlock(".worker");
- llvm::BasicBlock *MasterCheckBB = CGF.createBasicBlock(".mastercheck");
- llvm::BasicBlock *MasterBB = CGF.createBasicBlock(".master");
- EST.ExitBB = CGF.createBasicBlock(".exit");
-
- auto &RT = static_cast<CGOpenMPRuntimeGPU &>(CGF.CGM.getOpenMPRuntime());
- llvm::Value *IsWorker =
- Bld.CreateICmpULT(RT.getGPUThreadID(CGF), getThreadLimit(CGF));
- Bld.CreateCondBr(IsWorker, WorkerBB, MasterCheckBB);
-
- CGF.EmitBlock(WorkerBB);
- emitCall(CGF, WST.Loc, WST.WorkerFn);
- CGF.EmitBranch(EST.ExitBB);
-
- CGF.EmitBlock(MasterCheckBB);
- llvm::Value *IsMaster =
- Bld.CreateICmpEQ(RT.getGPUThreadID(CGF), getMasterThreadID(CGF));
- Bld.CreateCondBr(IsMaster, MasterBB, EST.ExitBB);
-
- CGF.EmitBlock(MasterBB);
- IsInTargetMasterThreadRegion = true;
- // SEQUENTIAL (MASTER) REGION START
- // First action in sequential region:
- // Initialize the state of the OpenMP runtime library on the GPU.
- // TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {getThreadLimit(CGF),
- Bld.getInt16(/*RequiresOMPRuntime=*/1)};
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_kernel_init),
- Args);
-
- // For data sharing, we need to initialize the stack.
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_data_sharing_init_stack));
-
- emitGenericVarsProlog(CGF, WST.Loc);
+ Bld.restoreIP(OMPBuilder.createTargetInit(Bld, IsSPMD, requiresFullRuntime()));
+ IsInTargetMasterThreadRegion = IsSPMD;
+ if (!IsSPMD)
+ emitGenericVarsProlog(CGF, EST.Loc);
}
-void CGOpenMPRuntimeGPU::emitNonSPMDEntryFooter(CodeGenFunction &CGF,
- EntryFunctionState &EST) {
- IsInTargetMasterThreadRegion = false;
- if (!CGF.HaveInsertPoint())
- return;
+void CGOpenMPRuntimeGPU::emitKernelDeinit(CodeGenFunction &CGF,
+ EntryFunctionState &EST,
+ bool IsSPMD) {
+ if (!IsSPMD)
+ emitGenericVarsEpilog(CGF);
- emitGenericVarsEpilog(CGF);
-
- if (!EST.ExitBB)
- EST.ExitBB = CGF.createBasicBlock(".exit");
-
- llvm::BasicBlock *TerminateBB = CGF.createBasicBlock(".termination.notifier");
- CGF.EmitBranch(TerminateBB);
-
- CGF.EmitBlock(TerminateBB);
- // Signal termination condition.
- // TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {CGF.Builder.getInt16(/*IsOMPRuntimeInitialized=*/1)};
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_kernel_deinit),
- Args);
- // Barrier to terminate worker threads.
- syncCTAThreads(CGF);
- // Master thread jumps to exit point.
- CGF.EmitBranch(EST.ExitBB);
-
- CGF.EmitBlock(EST.ExitBB);
- EST.ExitBB = nullptr;
+ CGBuilderTy &Bld = CGF.Builder;
+ OMPBuilder.createTargetDeinit(Bld, IsSPMD, requiresFullRuntime());
}
void CGOpenMPRuntimeGPU::emitSPMDKernel(const OMPExecutableDirective &D,
@@ -1209,95 +1081,28 @@
class NVPTXPrePostActionTy : public PrePostActionTy {
CGOpenMPRuntimeGPU &RT;
CGOpenMPRuntimeGPU::EntryFunctionState &EST;
- const OMPExecutableDirective &D;
public:
NVPTXPrePostActionTy(CGOpenMPRuntimeGPU &RT,
- CGOpenMPRuntimeGPU::EntryFunctionState &EST,
- const OMPExecutableDirective &D)
- : RT(RT), EST(EST), D(D) {}
+ CGOpenMPRuntimeGPU::EntryFunctionState &EST)
+ : RT(RT), EST(EST) {}
void Enter(CodeGenFunction &CGF) override {
- RT.emitSPMDEntryHeader(CGF, EST, D);
+ RT.emitKernelInit(CGF, EST, /* IsSPMD */ true);
// Skip target region initialization.
RT.setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true);
}
void Exit(CodeGenFunction &CGF) override {
RT.clearLocThreadIdInsertPt(CGF);
- RT.emitSPMDEntryFooter(CGF, EST);
+ RT.emitKernelDeinit(CGF, EST, /* IsSPMD */ true);
}
- } Action(*this, EST, D);
+ } Action(*this, EST);
CodeGen.setAction(Action);
IsInTTDRegion = true;
- // Reserve place for the globalized memory.
- GlobalizedRecords.emplace_back();
- if (!KernelStaticGlobalized) {
- KernelStaticGlobalized = new llvm::GlobalVariable(
- CGM.getModule(), CGM.VoidPtrTy, /*isConstant=*/false,
- llvm::GlobalValue::InternalLinkage,
- llvm::UndefValue::get(CGM.VoidPtrTy),
- "_openmp_kernel_static_glob_rd$ptr", /*InsertBefore=*/nullptr,
- llvm::GlobalValue::NotThreadLocal,
- CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared));
- }
emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
IsOffloadEntry, CodeGen);
IsInTTDRegion = false;
}
-void CGOpenMPRuntimeGPU::emitSPMDEntryHeader(
- CodeGenFunction &CGF, EntryFunctionState &EST,
- const OMPExecutableDirective &D) {
- CGBuilderTy &Bld = CGF.Builder;
-
- // Setup BBs in entry function.
- llvm::BasicBlock *ExecuteBB = CGF.createBasicBlock(".execute");
- EST.ExitBB = CGF.createBasicBlock(".exit");
-
- llvm::Value *Args[] = {getThreadLimit(CGF, /*IsInSPMDExecutionMode=*/true),
- /*RequiresOMPRuntime=*/
- Bld.getInt16(RequiresFullRuntime ? 1 : 0)};
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_spmd_kernel_init),
- Args);
-
- if (RequiresFullRuntime) {
- // For data sharing, we need to initialize the stack.
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_data_sharing_init_stack_spmd));
- }
-
- CGF.EmitBranch(ExecuteBB);
-
- CGF.EmitBlock(ExecuteBB);
-
- IsInTargetMasterThreadRegion = true;
-}
-
-void CGOpenMPRuntimeGPU::emitSPMDEntryFooter(CodeGenFunction &CGF,
- EntryFunctionState &EST) {
- IsInTargetMasterThreadRegion = false;
- if (!CGF.HaveInsertPoint())
- return;
-
- if (!EST.ExitBB)
- EST.ExitBB = CGF.createBasicBlock(".exit");
-
- llvm::BasicBlock *OMPDeInitBB = CGF.createBasicBlock(".omp.deinit");
- CGF.EmitBranch(OMPDeInitBB);
-
- CGF.EmitBlock(OMPDeInitBB);
- // DeInitialize the OMP state in the runtime; called by all active threads.
- llvm::Value *Args[] = {/*RequiresOMPRuntime=*/
- CGF.Builder.getInt16(RequiresFullRuntime ? 1 : 0)};
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_spmd_kernel_deinit_v2),
- Args);
- CGF.EmitBranch(EST.ExitBB);
-
- CGF.EmitBlock(EST.ExitBB);
- EST.ExitBB = nullptr;
-}
-
// Create a unique global variable to indicate the execution mode of this target
// region. The execution mode is either 'generic', or 'spmd' depending on the
// target directive. This variable is picked up by the offload library to setup
@@ -1314,137 +1119,6 @@
CGM.addCompilerUsedGlobal(GVMode);
}
-void CGOpenMPRuntimeGPU::emitWorkerFunction(WorkerFunctionState &WST) {
- ASTContext &Ctx = CGM.getContext();
-
- CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
- CGF.StartFunction(GlobalDecl(), Ctx.VoidTy, WST.WorkerFn, WST.CGFI, {},
- WST.Loc, WST.Loc);
- emitWorkerLoop(CGF, WST);
- CGF.FinishFunction();
-}
-
-void CGOpenMPRuntimeGPU::emitWorkerLoop(CodeGenFunction &CGF,
- WorkerFunctionState &WST) {
- //
- // The workers enter this loop and wait for parallel work from the master.
- // When the master encounters a parallel region it sets up the work + variable
- // arguments, and wakes up the workers. The workers first check to see if
- // they are required for the parallel region, i.e., within the # of requested
- // parallel threads. The activated workers load the variable arguments and
- // execute the parallel work.
- //
-
- CGBuilderTy &Bld = CGF.Builder;
-
- llvm::BasicBlock *AwaitBB = CGF.createBasicBlock(".await.work");
- llvm::BasicBlock *SelectWorkersBB = CGF.createBasicBlock(".select.workers");
- llvm::BasicBlock *ExecuteBB = CGF.createBasicBlock(".execute.parallel");
- llvm::BasicBlock *TerminateBB = CGF.createBasicBlock(".terminate.parallel");
- llvm::BasicBlock *BarrierBB = CGF.createBasicBlock(".barrier.parallel");
- llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
-
- CGF.EmitBranch(AwaitBB);
-
- // Workers wait for work from master.
- CGF.EmitBlock(AwaitBB);
- // Wait for parallel work
- syncCTAThreads(CGF);
-
- Address WorkFn =
- CGF.CreateDefaultAlignTempAlloca(CGF.Int8PtrTy, /*Name=*/"work_fn");
- Address ExecStatus =
- CGF.CreateDefaultAlignTempAlloca(CGF.Int8Ty, /*Name=*/"exec_status");
- CGF.InitTempAlloca(ExecStatus, Bld.getInt8(/*C=*/0));
- CGF.InitTempAlloca(WorkFn, llvm::Constant::getNullValue(CGF.Int8PtrTy));
-
- // TODO: Optimize runtime initialization and pass in correct value.
- llvm::Value *Args[] = {WorkFn.getPointer()};
- llvm::Value *Ret =
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_kernel_parallel),
- Args);
- Bld.CreateStore(Bld.CreateZExt(Ret, CGF.Int8Ty), ExecStatus);
-
- // On termination condition (workid == 0), exit loop.
- llvm::Value *WorkID = Bld.CreateLoad(WorkFn);
- llvm::Value *ShouldTerminate = Bld.CreateIsNull(WorkID, "should_terminate");
- Bld.CreateCondBr(ShouldTerminate, ExitBB, SelectWorkersBB);
-
- // Activate requested workers.
- CGF.EmitBlock(SelectWorkersBB);
- llvm::Value *IsActive =
- Bld.CreateIsNotNull(Bld.CreateLoad(ExecStatus), "is_active");
- Bld.CreateCondBr(IsActive, ExecuteBB, BarrierBB);
-
- // Signal start of parallel region.
- CGF.EmitBlock(ExecuteBB);
- // Skip initialization.
- setLocThreadIdInsertPt(CGF, /*AtCurrentPoint=*/true);
-
- // Process work items: outlined parallel functions.
- for (llvm::Function *W : Work) {
- // Try to match this outlined function.
- llvm::Value *ID = Bld.CreatePointerBitCastOrAddrSpaceCast(W, CGM.Int8PtrTy);
-
- llvm::Value *WorkFnMatch =
- Bld.CreateICmpEQ(Bld.CreateLoad(WorkFn), ID, "work_match");
-
- llvm::BasicBlock *ExecuteFNBB = CGF.createBasicBlock(".execute.fn");
- llvm::BasicBlock *CheckNextBB = CGF.createBasicBlock(".check.next");
- Bld.CreateCondBr(WorkFnMatch, ExecuteFNBB, CheckNextBB);
-
- // Execute this outlined function.
- CGF.EmitBlock(ExecuteFNBB);
-
- // Insert call to work function via shared wrapper. The shared
- // wrapper takes two arguments:
- // - the parallelism level;
- // - the thread ID;
- emitCall(CGF, WST.Loc, W,
- {Bld.getInt16(/*ParallelLevel=*/0), getThreadID(CGF, WST.Loc)});
-
- // Go to end of parallel region.
- CGF.EmitBranch(TerminateBB);
-
- CGF.EmitBlock(CheckNextBB);
- }
- // Default case: call to outlined function through pointer if the target
- // region makes a declare target call that may contain an orphaned parallel
- // directive.
- auto *ParallelFnTy =
- llvm::FunctionType::get(CGM.VoidTy, {CGM.Int16Ty, CGM.Int32Ty},
- /*isVarArg=*/false);
- llvm::Value *WorkFnCast =
- Bld.CreateBitCast(WorkID, ParallelFnTy->getPointerTo());
- // Insert call to work function via shared wrapper. The shared
- // wrapper takes two arguments:
- // - the parallelism level;
- // - the thread ID;
- emitCall(CGF, WST.Loc, {ParallelFnTy, WorkFnCast},
- {Bld.getInt16(/*ParallelLevel=*/0), getThreadID(CGF, WST.Loc)});
- // Go to end of parallel region.
- CGF.EmitBranch(TerminateBB);
-
- // Signal end of parallel region.
- CGF.EmitBlock(TerminateBB);
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_kernel_end_parallel),
- llvm::None);
- CGF.EmitBranch(BarrierBB);
-
- // All active and inactive workers wait at a barrier after parallel region.
- CGF.EmitBlock(BarrierBB);
- // Barrier after parallel region.
- syncCTAThreads(CGF);
- CGF.EmitBranch(AwaitBB);
-
- // Exit target region.
- CGF.EmitBlock(ExitBB);
- // Skip initialization.
- clearLocThreadIdInsertPt(CGF);
-}
-
void CGOpenMPRuntimeGPU::createOffloadEntry(llvm::Constant *ID,
llvm::Constant *Addr,
uint64_t Size, int32_t,
@@ -1671,16 +1345,13 @@
static_cast<CGOpenMPRuntimeGPU &>(CGF.CGM.getOpenMPRuntime());
if (GlobalizedRD) {
auto I = Rt.FunctionGlobalizedDecls.try_emplace(CGF.CurFn).first;
- I->getSecond().GlobalRecord = GlobalizedRD;
I->getSecond().MappedParams =
std::make_unique<CodeGenFunction::OMPMapVars>();
DeclToAddrMapTy &Data = I->getSecond().LocalVarData;
for (const auto &Pair : MappedDeclsFields) {
assert(Pair.getFirst()->isCanonicalDecl() &&
"Expected canonical declaration");
- Data.insert(std::make_pair(Pair.getFirst(),
- MappedVarData(Pair.getSecond(),
- /*IsOnePerTeam=*/true)));
+ Data.insert(std::make_pair(Pair.getFirst(), MappedVarData()));
}
}
Rt.emitGenericVarsProlog(CGF, Loc);
@@ -1709,281 +1380,71 @@
const auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
if (I == FunctionGlobalizedDecls.end())
return;
- if (const RecordDecl *GlobalizedVarsRecord = I->getSecond().GlobalRecord) {
- QualType GlobalRecTy = CGM.getContext().getRecordType(GlobalizedVarsRecord);
- QualType SecGlobalRecTy;
- // Recover pointer to this function's global record. The runtime will
- // handle the specifics of the allocation of the memory.
- // Use actual memory size of the record including the padding
- // for alignment purposes.
- unsigned Alignment =
- CGM.getContext().getTypeAlignInChars(GlobalRecTy).getQuantity();
- unsigned GlobalRecordSize =
- CGM.getContext().getTypeSizeInChars(GlobalRecTy).getQuantity();
- GlobalRecordSize = llvm::alignTo(GlobalRecordSize, Alignment);
+ for (auto &Rec : I->getSecond().LocalVarData) {
+ const auto *VD = cast<VarDecl>(Rec.first);
+ bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first);
+ QualType VarTy = VD->getType();
- llvm::PointerType *GlobalRecPtrTy =
- CGF.ConvertTypeForMem(GlobalRecTy)->getPointerTo();
- llvm::Value *GlobalRecCastAddr;
- llvm::Value *IsTTD = nullptr;
- if (!IsInTTDRegion &&
- (WithSPMDCheck ||
- getExecutionMode() == CGOpenMPRuntimeGPU::EM_Unknown)) {
- llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
- llvm::BasicBlock *SPMDBB = CGF.createBasicBlock(".spmd");
- llvm::BasicBlock *NonSPMDBB = CGF.createBasicBlock(".non-spmd");
- if (I->getSecond().SecondaryGlobalRecord.hasValue()) {
- llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
- llvm::Value *ThreadID = getThreadID(CGF, Loc);
- llvm::Value *PL = CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
- OMPRTL___kmpc_parallel_level),
- {RTLoc, ThreadID});
- IsTTD = Bld.CreateIsNull(PL);
- }
- llvm::Value *IsSPMD = Bld.CreateIsNotNull(
- CGF.EmitNounwindRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_is_spmd_exec_mode)));
- Bld.CreateCondBr(IsSPMD, SPMDBB, NonSPMDBB);
- // There is no need to emit line number for unconditional branch.
- (void)ApplyDebugLocation::CreateEmpty(CGF);
- CGF.EmitBlock(SPMDBB);
- Address RecPtr = Address(llvm::ConstantPointerNull::get(GlobalRecPtrTy),
- CharUnits::fromQuantity(Alignment));
- CGF.EmitBranch(ExitBB);
- // There is no need to emit line number for unconditional branch.
- (void)ApplyDebugLocation::CreateEmpty(CGF);
- CGF.EmitBlock(NonSPMDBB);
- llvm::Value *Size = llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize);
- if (const RecordDecl *SecGlobalizedVarsRecord =
- I->getSecond().SecondaryGlobalRecord.getValueOr(nullptr)) {
- SecGlobalRecTy =
- CGM.getContext().getRecordType(SecGlobalizedVarsRecord);
-
- // Recover pointer to this function's global record. The runtime will
- // handle the specifics of the allocation of the memory.
- // Use actual memory size of the record including the padding
- // for alignment purposes.
- unsigned Alignment =
- CGM.getContext().getTypeAlignInChars(SecGlobalRecTy).getQuantity();
- unsigned GlobalRecordSize =
- CGM.getContext().getTypeSizeInChars(SecGlobalRecTy).getQuantity();
- GlobalRecordSize = llvm::alignTo(GlobalRecordSize, Alignment);
- Size = Bld.CreateSelect(
- IsTTD, llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize), Size);
- }
- // TODO: allow the usage of shared memory to be controlled by
- // the user, for now, default to global.
- llvm::Value *GlobalRecordSizeArg[] = {
- Size, CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
- llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_data_sharing_coalesced_push_stack),
- GlobalRecordSizeArg);
- GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
- GlobalRecValue, GlobalRecPtrTy);
- CGF.EmitBlock(ExitBB);
- auto *Phi = Bld.CreatePHI(GlobalRecPtrTy,
- /*NumReservedValues=*/2, "_select_stack");
- Phi->addIncoming(RecPtr.getPointer(), SPMDBB);
- Phi->addIncoming(GlobalRecCastAddr, NonSPMDBB);
- GlobalRecCastAddr = Phi;
- I->getSecond().GlobalRecordAddr = Phi;
- I->getSecond().IsInSPMDModeFlag = IsSPMD;
- } else if (!CGM.getLangOpts().OpenMPCUDATargetParallel && IsInTTDRegion) {
- assert(GlobalizedRecords.back().Records.size() < 2 &&
- "Expected less than 2 globalized records: one for target and one "
- "for teams.");
- unsigned Offset = 0;
- for (const RecordDecl *RD : GlobalizedRecords.back().Records) {
- QualType RDTy = CGM.getContext().getRecordType(RD);
- unsigned Alignment =
- CGM.getContext().getTypeAlignInChars(RDTy).getQuantity();
- unsigned Size = CGM.getContext().getTypeSizeInChars(RDTy).getQuantity();
- Offset =
- llvm::alignTo(llvm::alignTo(Offset, Alignment) + Size, Alignment);
- }
- unsigned Alignment =
- CGM.getContext().getTypeAlignInChars(GlobalRecTy).getQuantity();
- Offset = llvm::alignTo(Offset, Alignment);
- GlobalizedRecords.back().Records.push_back(GlobalizedVarsRecord);
- ++GlobalizedRecords.back().RegionCounter;
- if (GlobalizedRecords.back().Records.size() == 1) {
- assert(KernelStaticGlobalized &&
- "Kernel static pointer must be initialized already.");
- auto *UseSharedMemory = new llvm::GlobalVariable(
- CGM.getModule(), CGM.Int16Ty, /*isConstant=*/true,
- llvm::GlobalValue::InternalLinkage, nullptr,
- "_openmp_static_kernel$is_shared");
- UseSharedMemory->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- QualType Int16Ty = CGM.getContext().getIntTypeForBitwidth(
- /*DestWidth=*/16, /*Signed=*/0);
- llvm::Value *IsInSharedMemory = CGF.EmitLoadOfScalar(
- Address(UseSharedMemory,
- CGM.getContext().getTypeAlignInChars(Int16Ty)),
- /*Volatile=*/false, Int16Ty, Loc);
- auto *StaticGlobalized = new llvm::GlobalVariable(
- CGM.getModule(), CGM.Int8Ty, /*isConstant=*/false,
- llvm::GlobalValue::CommonLinkage, nullptr);
- auto *RecSize = new llvm::GlobalVariable(
- CGM.getModule(), CGM.SizeTy, /*isConstant=*/true,
- llvm::GlobalValue::InternalLinkage, nullptr,
- "_openmp_static_kernel$size");
- RecSize->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- llvm::Value *Ld = CGF.EmitLoadOfScalar(
- Address(RecSize, CGM.getSizeAlign()), /*Volatile=*/false,
- CGM.getContext().getSizeType(), Loc);
- llvm::Value *ResAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
- KernelStaticGlobalized, CGM.VoidPtrPtrTy);
- llvm::Value *GlobalRecordSizeArg[] = {
- llvm::ConstantInt::get(
- CGM.Int16Ty,
- getExecutionMode() == CGOpenMPRuntimeGPU::EM_SPMD ? 1 : 0),
- StaticGlobalized, Ld, IsInSharedMemory, ResAddr};
- CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_get_team_static_memory),
- GlobalRecordSizeArg);
- GlobalizedRecords.back().Buffer = StaticGlobalized;
- GlobalizedRecords.back().RecSize = RecSize;
- GlobalizedRecords.back().UseSharedMemory = UseSharedMemory;
- GlobalizedRecords.back().Loc = Loc;
- }
- assert(KernelStaticGlobalized && "Global address must be set already.");
- Address FrameAddr = CGF.EmitLoadOfPointer(
- Address(KernelStaticGlobalized, CGM.getPointerAlign()),
- CGM.getContext()
- .getPointerType(CGM.getContext().VoidPtrTy)
- .castAs<PointerType>());
- llvm::Value *GlobalRecValue =
- Bld.CreateConstInBoundsGEP(FrameAddr, Offset).getPointer();
- I->getSecond().GlobalRecordAddr = GlobalRecValue;
- I->getSecond().IsInSPMDModeFlag = nullptr;
- GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
- GlobalRecValue, CGF.ConvertTypeForMem(GlobalRecTy)->getPointerTo());
- } else {
- // TODO: allow the usage of shared memory to be controlled by
- // the user, for now, default to global.
- bool UseSharedMemory =
- IsInTTDRegion && GlobalRecordSize <= SharedMemorySize;
- llvm::Value *GlobalRecordSizeArg[] = {
- llvm::ConstantInt::get(CGM.SizeTy, GlobalRecordSize),
- CGF.Builder.getInt16(UseSharedMemory ? 1 : 0)};
- llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(),
- IsInTTDRegion ? OMPRTL___kmpc_data_sharing_push_stack
- : OMPRTL___kmpc_data_sharing_coalesced_push_stack),
- GlobalRecordSizeArg);
- GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
- GlobalRecValue, GlobalRecPtrTy);
- I->getSecond().GlobalRecordAddr = GlobalRecValue;
- I->getSecond().IsInSPMDModeFlag = nullptr;
+ // Get the local allocation of a firstprivate variable before sharing
+ llvm::Value *ParValue;
+ if (EscapedParam) {
+ LValue ParLVal =
+ CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
+ ParValue = CGF.EmitLoadOfScalar(ParLVal, Loc);
}
- LValue Base =
- CGF.MakeNaturalAlignPointeeAddrLValue(GlobalRecCastAddr, GlobalRecTy);
- // Emit the "global alloca" which is a GEP from the global declaration
- // record using the pointer returned by the runtime.
- LValue SecBase;
- decltype(I->getSecond().LocalVarData)::const_iterator SecIt;
- if (IsTTD) {
- SecIt = I->getSecond().SecondaryLocalVarData->begin();
- llvm::PointerType *SecGlobalRecPtrTy =
- CGF.ConvertTypeForMem(SecGlobalRecTy)->getPointerTo();
- SecBase = CGF.MakeNaturalAlignPointeeAddrLValue(
- Bld.CreatePointerBitCastOrAddrSpaceCast(
- I->getSecond().GlobalRecordAddr, SecGlobalRecPtrTy),
- SecGlobalRecTy);
+ // Allocate space for the variable to be globalized
+ llvm::Value *AllocArgs[] = {CGF.getTypeSize(VD->getType())};
+ llvm::Instruction *VoidPtr =
+ CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
+ CGM.getModule(), OMPRTL___kmpc_alloc_shared),
+ AllocArgs, VD->getName());
+
+ // Cast the void pointer and get the address of the globalized variable.
+ llvm::PointerType *VarPtrTy = CGF.ConvertTypeForMem(VarTy)->getPointerTo();
+ llvm::Value *CastedVoidPtr = Bld.CreatePointerBitCastOrAddrSpaceCast(
+ VoidPtr, VarPtrTy, VD->getName() + "_on_stack");
+ LValue VarAddr = CGF.MakeNaturalAlignAddrLValue(CastedVoidPtr, VarTy);
+ Rec.second.PrivateAddr = VarAddr.getAddress(CGF);
+ Rec.second.GlobalizedVal = VoidPtr;
+
+ // Assign the local allocation to the newly globalized location.
+ if (EscapedParam) {
+ CGF.EmitStoreOfScalar(ParValue, VarAddr);
+ I->getSecond().MappedParams->setVarAddr(CGF, VD, VarAddr.getAddress(CGF));
}
- for (auto &Rec : I->getSecond().LocalVarData) {
- bool EscapedParam = I->getSecond().EscapedParameters.count(Rec.first);
- llvm::Value *ParValue;
- if (EscapedParam) {
- const auto *VD = cast<VarDecl>(Rec.first);
- LValue ParLVal =
- CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
- ParValue = CGF.EmitLoadOfScalar(ParLVal, Loc);
- }
- LValue VarAddr = CGF.EmitLValueForField(Base, Rec.second.FD);
- // Emit VarAddr basing on lane-id if required.
- QualType VarTy;
- if (Rec.second.IsOnePerTeam) {
- VarTy = Rec.second.FD->getType();
- } else {
- llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(
- VarAddr.getAddress(CGF).getPointer(),
- {Bld.getInt32(0), getNVPTXLaneID(CGF)});
- VarTy =
- Rec.second.FD->getType()->castAsArrayTypeUnsafe()->getElementType();
- VarAddr = CGF.MakeAddrLValue(
- Address(Ptr, CGM.getContext().getDeclAlign(Rec.first)), VarTy,
- AlignmentSource::Decl);
- }
- Rec.second.PrivateAddr = VarAddr.getAddress(CGF);
- if (!IsInTTDRegion &&
- (WithSPMDCheck ||
- getExecutionMode() == CGOpenMPRuntimeGPU::EM_Unknown)) {
- assert(I->getSecond().IsInSPMDModeFlag &&
- "Expected unknown execution mode or required SPMD check.");
- if (IsTTD) {
- assert(SecIt->second.IsOnePerTeam &&
- "Secondary glob data must be one per team.");
- LValue SecVarAddr = CGF.EmitLValueForField(SecBase, SecIt->second.FD);
- VarAddr.setAddress(
- Address(Bld.CreateSelect(IsTTD, SecVarAddr.getPointer(CGF),
- VarAddr.getPointer(CGF)),
- VarAddr.getAlignment()));
- Rec.second.PrivateAddr = VarAddr.getAddress(CGF);
- }
- Address GlobalPtr = Rec.second.PrivateAddr;
- Address LocalAddr = CGF.CreateMemTemp(VarTy, Rec.second.FD->getName());
- Rec.second.PrivateAddr = Address(
- Bld.CreateSelect(I->getSecond().IsInSPMDModeFlag,
- LocalAddr.getPointer(), GlobalPtr.getPointer()),
- LocalAddr.getAlignment());
- }
- if (EscapedParam) {
- const auto *VD = cast<VarDecl>(Rec.first);
- CGF.EmitStoreOfScalar(ParValue, VarAddr);
- I->getSecond().MappedParams->setVarAddr(CGF, VD,
- VarAddr.getAddress(CGF));
- }
- if (IsTTD)
- ++SecIt;
- }
+ if (auto *DI = CGF.getDebugInfo())
+ VoidPtr->setDebugLoc(DI->SourceLocToDebugLoc(VD->getLocation()));
}
- for (const ValueDecl *VD : I->getSecond().EscapedVariableLengthDecls) {
- // Recover pointer to this function's global record. The runtime will
- // handle the specifics of the allocation of the memory.
- // Use actual memory size of the record including the padding
+ for (const auto *VD : I->getSecond().EscapedVariableLengthDecls) {
+ // Use actual memory size of the VLA object including the padding
// for alignment purposes.
- CGBuilderTy &Bld = CGF.Builder;
llvm::Value *Size = CGF.getTypeSize(VD->getType());
CharUnits Align = CGM.getContext().getDeclAlign(VD);
Size = Bld.CreateNUWAdd(
Size, llvm::ConstantInt::get(CGF.SizeTy, Align.getQuantity() - 1));
llvm::Value *AlignVal =
llvm::ConstantInt::get(CGF.SizeTy, Align.getQuantity());
+
Size = Bld.CreateUDiv(Size, AlignVal);
Size = Bld.CreateNUWMul(Size, AlignVal);
- // TODO: allow the usage of shared memory to be controlled by
- // the user, for now, default to global.
- llvm::Value *GlobalRecordSizeArg[] = {
- Size, CGF.Builder.getInt16(/*UseSharedMemory=*/0)};
- llvm::Value *GlobalRecValue = CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_data_sharing_coalesced_push_stack),
- GlobalRecordSizeArg);
- llvm::Value *GlobalRecCastAddr = Bld.CreatePointerBitCastOrAddrSpaceCast(
- GlobalRecValue, CGF.ConvertTypeForMem(VD->getType())->getPointerTo());
- LValue Base = CGF.MakeAddrLValue(GlobalRecCastAddr, VD->getType(),
+
+ // Allocate space for this VLA object to be globalized.
+ llvm::Value *AllocArgs[] = {CGF.getTypeSize(VD->getType())};
+ llvm::Instruction *VoidPtr =
+ CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
+ CGM.getModule(), OMPRTL___kmpc_alloc_shared),
+ AllocArgs, VD->getName());
+
+ I->getSecond().EscapedVariableLengthDeclsAddrs.emplace_back(
+ std::pair<llvm::Value *, llvm::Value *>(
+ {VoidPtr, CGF.getTypeSize(VD->getType())}));
+ LValue Base = CGF.MakeAddrLValue(VoidPtr, VD->getType(),
CGM.getContext().getDeclAlign(VD),
AlignmentSource::Decl);
I->getSecond().MappedParams->setVarAddr(CGF, cast<VarDecl>(VD),
Base.getAddress(CGF));
- I->getSecond().EscapedVariableLengthDeclsAddrs.emplace_back(GlobalRecValue);
}
I->getSecond().MappedParams->apply(CGF);
}
@@ -1996,60 +1457,23 @@
const auto I = FunctionGlobalizedDecls.find(CGF.CurFn);
if (I != FunctionGlobalizedDecls.end()) {
- I->getSecond().MappedParams->restore(CGF);
- if (!CGF.HaveInsertPoint())
- return;
- for (llvm::Value *Addr :
+ // Deallocate the memory for each globalized VLA object
+ for (auto AddrSizePair :
llvm::reverse(I->getSecond().EscapedVariableLengthDeclsAddrs)) {
- CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_data_sharing_pop_stack),
- Addr);
+ CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
+ CGM.getModule(), OMPRTL___kmpc_free_shared),
+ {AddrSizePair.first, AddrSizePair.second});
}
- if (I->getSecond().GlobalRecordAddr) {
- if (!IsInTTDRegion &&
- (WithSPMDCheck ||
- getExecutionMode() == CGOpenMPRuntimeGPU::EM_Unknown)) {
- CGBuilderTy &Bld = CGF.Builder;
- llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
- llvm::BasicBlock *NonSPMDBB = CGF.createBasicBlock(".non-spmd");
- Bld.CreateCondBr(I->getSecond().IsInSPMDModeFlag, ExitBB, NonSPMDBB);
- // There is no need to emit line number for unconditional branch.
- (void)ApplyDebugLocation::CreateEmpty(CGF);
- CGF.EmitBlock(NonSPMDBB);
- CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_data_sharing_pop_stack),
- CGF.EmitCastToVoidPtr(I->getSecond().GlobalRecordAddr));
- CGF.EmitBlock(ExitBB);
- } else if (!CGM.getLangOpts().OpenMPCUDATargetParallel && IsInTTDRegion) {
- assert(GlobalizedRecords.back().RegionCounter > 0 &&
- "region counter must be > 0.");
- --GlobalizedRecords.back().RegionCounter;
- // Emit the restore function only in the target region.
- if (GlobalizedRecords.back().RegionCounter == 0) {
- QualType Int16Ty = CGM.getContext().getIntTypeForBitwidth(
- /*DestWidth=*/16, /*Signed=*/0);
- llvm::Value *IsInSharedMemory = CGF.EmitLoadOfScalar(
- Address(GlobalizedRecords.back().UseSharedMemory,
- CGM.getContext().getTypeAlignInChars(Int16Ty)),
- /*Volatile=*/false, Int16Ty, GlobalizedRecords.back().Loc);
- llvm::Value *Args[] = {
- llvm::ConstantInt::get(
- CGM.Int16Ty,
- getExecutionMode() == CGOpenMPRuntimeGPU::EM_SPMD ? 1 : 0),
- IsInSharedMemory};
- CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_restore_team_static_memory),
- Args);
- }
- } else {
- CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_data_sharing_pop_stack),
- I->getSecond().GlobalRecordAddr);
- }
+ // Deallocate the memory for each globalized value
+ for (auto &Rec : llvm::reverse(I->getSecond().LocalVarData)) {
+ const auto *VD = cast<VarDecl>(Rec.first);
+ I->getSecond().MappedParams->restore(CGF);
+
+ llvm::Value *FreeArgs[] = {Rec.second.GlobalizedVal,
+ CGF.getTypeSize(VD->getType())};
+ CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
+ CGM.getModule(), OMPRTL___kmpc_free_shared),
+ FreeArgs);
}
}
}
@@ -2072,113 +1496,38 @@
emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
}
-void CGOpenMPRuntimeGPU::emitParallelCall(
- CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn,
- ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) {
+void CGOpenMPRuntimeGPU::emitParallelCall(CodeGenFunction &CGF,
+ SourceLocation Loc,
+ llvm::Function *OutlinedFn,
+ ArrayRef<llvm::Value *> CapturedVars,
+ const Expr *IfCond) {
if (!CGF.HaveInsertPoint())
return;
- if (getExecutionMode() == CGOpenMPRuntimeGPU::EM_SPMD)
- emitSPMDParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond);
- else
- emitNonSPMDParallelCall(CGF, Loc, OutlinedFn, CapturedVars, IfCond);
-}
-
-void CGOpenMPRuntimeGPU::emitNonSPMDParallelCall(
- CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *OutlinedFn,
- ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) {
- llvm::Function *Fn = cast<llvm::Function>(OutlinedFn);
-
- // Force inline this outlined function at its call site.
- Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
-
- // Ensure we do not inline the function. This is trivially true for the ones
- // passed to __kmpc_fork_call but the ones calles in serialized regions
- // could be inlined. This is not a perfect but it is closer to the invariant
- // we want, namely, every data environment starts with a new function.
- // TODO: We should pass the if condition to the runtime function and do the
- // handling there. Much cleaner code.
- cast<llvm::Function>(OutlinedFn)->addFnAttr(llvm::Attribute::NoInline);
-
- Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
- /*Name=*/".zero.addr");
- CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
- // ThreadId for serialized parallels is 0.
- Address ThreadIDAddr = ZeroAddr;
- auto &&CodeGen = [this, Fn, CapturedVars, Loc, &ThreadIDAddr](
- CodeGenFunction &CGF, PrePostActionTy &Action) {
- Action.Enter(CGF);
-
- Address ZeroAddr =
- CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
- /*Name=*/".bound.zero.addr");
- CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
- llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
- OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
- OutlinedFnArgs.push_back(ZeroAddr.getPointer());
- OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
- emitOutlinedFunctionCall(CGF, Loc, Fn, OutlinedFnArgs);
- };
- auto &&SeqGen = [this, &CodeGen, Loc](CodeGenFunction &CGF,
- PrePostActionTy &) {
-
- RegionCodeGenTy RCG(CodeGen);
- llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
- llvm::Value *ThreadID = getThreadID(CGF, Loc);
- llvm::Value *Args[] = {RTLoc, ThreadID};
-
- NVPTXActionTy Action(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_serialized_parallel),
- Args,
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_end_serialized_parallel),
- Args);
- RCG.setAction(Action);
- RCG(CGF);
- };
-
- auto &&L0ParallelGen = [this, CapturedVars, Fn](CodeGenFunction &CGF,
- PrePostActionTy &Action) {
+ auto &&ParallelGen = [this, Loc, OutlinedFn, CapturedVars,
+ IfCond](CodeGenFunction &CGF, PrePostActionTy &Action) {
CGBuilderTy &Bld = CGF.Builder;
- llvm::Function *WFn = WrapperFunctionsMap[Fn];
- assert(WFn && "Wrapper function does not exist!");
- llvm::Value *ID = Bld.CreateBitOrPointerCast(WFn, CGM.Int8PtrTy);
-
- // Prepare for parallel region. Indicate the outlined function.
- llvm::Value *Args[] = {ID};
- CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_kernel_prepare_parallel),
- Args);
+ llvm::Function *WFn = WrapperFunctionsMap[OutlinedFn];
+ llvm::Value *ID = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
+ if (WFn)
+ ID = Bld.CreateBitOrPointerCast(WFn, CGM.Int8PtrTy);
+ llvm::Value *FnPtr = Bld.CreateBitOrPointerCast(OutlinedFn, CGM.Int8PtrTy);
// Create a private scope that will globalize the arguments
// passed from the outside of the target region.
+ // TODO: Is that needed?
CodeGenFunction::OMPPrivateScope PrivateArgScope(CGF);
+ Address CapturedVarsAddrs = CGF.CreateDefaultAlignTempAlloca(
+ llvm::ArrayType::get(CGM.VoidPtrTy, CapturedVars.size()),
+ "captured_vars_addrs");
// There's something to share.
if (!CapturedVars.empty()) {
// Prepare for parallel region. Indicate the outlined function.
- Address SharedArgs =
- CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "shared_arg_refs");
- llvm::Value *SharedArgsPtr = SharedArgs.getPointer();
-
- llvm::Value *DataSharingArgs[] = {
- SharedArgsPtr,
- llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())};
- CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_begin_sharing_variables),
- DataSharingArgs);
-
- // Store variable address in a list of references to pass to workers.
- unsigned Idx = 0;
ASTContext &Ctx = CGF.getContext();
- Address SharedArgListAddress = CGF.EmitLoadOfPointer(
- SharedArgs, Ctx.getPointerType(Ctx.getPointerType(Ctx.VoidPtrTy))
- .castAs<PointerType>());
+ unsigned Idx = 0;
for (llvm::Value *V : CapturedVars) {
- Address Dst = Bld.CreateConstInBoundsGEP(SharedArgListAddress, Idx);
+ Address Dst = Bld.CreateConstArrayGEP(CapturedVarsAddrs, Idx);
llvm::Value *PtrV;
if (V->getType()->isIntegerTy())
PtrV = Bld.CreateIntToPtr(V, CGF.VoidPtrTy);
@@ -2190,141 +1539,33 @@
}
}
- // Activate workers. This barrier is used by the master to signal
- // work for the workers.
- syncCTAThreads(CGF);
+ llvm::Value *IfCondVal = nullptr;
+ if (IfCond)
+ IfCondVal = Bld.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.Int32Ty,
+ /* isSigned */ false);
+ else
+ IfCondVal = llvm::ConstantInt::get(CGF.Int32Ty, 1);
- // OpenMP [2.5, Parallel Construct, p.49]
- // There is an implied barrier at the end of a parallel region. After the
- // end of a parallel region, only the master thread of the team resumes
- // execution of the enclosing task region.
- //
- // The master waits at this barrier until all workers are done.
- syncCTAThreads(CGF);
-
- if (!CapturedVars.empty())
- CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_end_sharing_variables));
-
- // Remember for post-processing in worker loop.
- Work.emplace_back(WFn);
- };
-
- auto &&LNParallelGen = [this, Loc, &SeqGen, &L0ParallelGen](
- CodeGenFunction &CGF, PrePostActionTy &Action) {
- if (IsInParallelRegion) {
- SeqGen(CGF, Action);
- } else if (IsInTargetMasterThreadRegion) {
- L0ParallelGen(CGF, Action);
- } else {
- // Check for master and then parallelism:
- // if (__kmpc_is_spmd_exec_mode() || __kmpc_parallel_level(loc, gtid)) {
- // Serialized execution.
- // } else {
- // Worker call.
- // }
- CGBuilderTy &Bld = CGF.Builder;
- llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".exit");
- llvm::BasicBlock *SeqBB = CGF.createBasicBlock(".sequential");
- llvm::BasicBlock *ParallelCheckBB = CGF.createBasicBlock(".parcheck");
- llvm::BasicBlock *MasterBB = CGF.createBasicBlock(".master");
- llvm::Value *IsSPMD = Bld.CreateIsNotNull(
- CGF.EmitNounwindRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_is_spmd_exec_mode)));
- Bld.CreateCondBr(IsSPMD, SeqBB, ParallelCheckBB);
- // There is no need to emit line number for unconditional branch.
- (void)ApplyDebugLocation::CreateEmpty(CGF);
- CGF.EmitBlock(ParallelCheckBB);
- llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
- llvm::Value *ThreadID = getThreadID(CGF, Loc);
- llvm::Value *PL = CGF.EmitRuntimeCall(
- OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(),
- OMPRTL___kmpc_parallel_level),
- {RTLoc, ThreadID});
- llvm::Value *Res = Bld.CreateIsNotNull(PL);
- Bld.CreateCondBr(Res, SeqBB, MasterBB);
- CGF.EmitBlock(SeqBB);
- SeqGen(CGF, Action);
- CGF.EmitBranch(ExitBB);
- // There is no need to emit line number for unconditional branch.
- (void)ApplyDebugLocation::CreateEmpty(CGF);
- CGF.EmitBlock(MasterBB);
- L0ParallelGen(CGF, Action);
- CGF.EmitBranch(ExitBB);
- // There is no need to emit line number for unconditional branch.
- (void)ApplyDebugLocation::CreateEmpty(CGF);
- // Emit the continuation block for code after the if.
- CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
- }
- };
-
- if (IfCond) {
- emitIfClause(CGF, IfCond, LNParallelGen, SeqGen);
- } else {
- CodeGenFunction::RunCleanupsScope Scope(CGF);
- RegionCodeGenTy ThenRCG(LNParallelGen);
- ThenRCG(CGF);
- }
-}
-
-void CGOpenMPRuntimeGPU::emitSPMDParallelCall(
- CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn,
- ArrayRef<llvm::Value *> CapturedVars, const Expr *IfCond) {
- // Just call the outlined function to execute the parallel region.
- // OutlinedFn(>id, &zero, CapturedStruct);
- //
- llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
-
- Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
- /*Name=*/".zero.addr");
- CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
- // ThreadId for serialized parallels is 0.
- Address ThreadIDAddr = ZeroAddr;
- auto &&CodeGen = [this, OutlinedFn, CapturedVars, Loc, &ThreadIDAddr](
- CodeGenFunction &CGF, PrePostActionTy &Action) {
- Action.Enter(CGF);
-
- Address ZeroAddr =
- CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
- /*Name=*/".bound.zero.addr");
- CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
- llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
- OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
- OutlinedFnArgs.push_back(ZeroAddr.getPointer());
- OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
- emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
- };
- auto &&SeqGen = [this, &CodeGen, Loc](CodeGenFunction &CGF,
- PrePostActionTy &) {
-
- RegionCodeGenTy RCG(CodeGen);
+ assert(IfCondVal && "Expected a value");
llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
- llvm::Value *ThreadID = getThreadID(CGF, Loc);
- llvm::Value *Args[] = {RTLoc, ThreadID};
-
- NVPTXActionTy Action(
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_serialized_parallel),
- Args,
- OMPBuilder.getOrCreateRuntimeFunction(
- CGM.getModule(), OMPRTL___kmpc_end_serialized_parallel),
- Args);
- RCG.setAction(Action);
- RCG(CGF);
+ llvm::Value *Args[] = {
+ RTLoc,
+ getThreadID(CGF, Loc),
+ IfCondVal,
+ llvm::ConstantInt::get(CGF.Int32Ty, -1),
+ llvm::ConstantInt::get(CGF.Int32Ty, -1),
+ FnPtr,
+ ID,
+ Bld.CreateBitOrPointerCast(CapturedVarsAddrs.getPointer(),
+ CGF.VoidPtrPtrTy),
+ llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())};
+ CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
+ CGM.getModule(), OMPRTL___kmpc_parallel_51),
+ Args);
};
- if (IsInTargetMasterThreadRegion) {
- // In the worker need to use the real thread id.
- ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
- RegionCodeGenTy RCG(CodeGen);
- RCG(CGF);
- } else {
- // If we are not in the target region, it is definitely L2 parallelism or
- // more, because for SPMD mode we always has L1 parallel level, sowe don't
- // need to check for orphaned directives.
- RegionCodeGenTy RCG(SeqGen);
- RCG(CGF);
- }
+ RegionCodeGenTy RCG(ParallelGen);
+ RCG(CGF);
}
void CGOpenMPRuntimeGPU::syncCTAThreads(CodeGenFunction &CGF) {
@@ -2936,14 +2177,16 @@
Address ElemPtr = Address(ElemPtrPtr, Align);
ElemPtr = Bld.CreateElementBitCast(ElemPtr, CopyType);
if (NumIters > 1) {
- ElemPtr = Address(Bld.CreateGEP(ElemPtr.getPointer(), Cnt),
+ ElemPtr = Address(Bld.CreateGEP(ElemPtr.getElementType(),
+ ElemPtr.getPointer(), Cnt),
ElemPtr.getAlignment());
}
// Get pointer to location in transfer medium.
// MediumPtr = &medium[warp_id]
llvm::Value *MediumPtrVal = Bld.CreateInBoundsGEP(
- TransferMedium, {llvm::Constant::getNullValue(CGM.Int64Ty), WarpID});
+ TransferMedium->getValueType(), TransferMedium,
+ {llvm::Constant::getNullValue(CGM.Int64Ty), WarpID});
Address MediumPtr(MediumPtrVal, Align);
// Casting to actual data type.
// MediumPtr = (CopyType*)MediumPtrAddr;
@@ -2991,7 +2234,7 @@
// SrcMediumPtr = &medium[tid]
llvm::Value *SrcMediumPtrVal = Bld.CreateInBoundsGEP(
- TransferMedium,
+ TransferMedium->getValueType(), TransferMedium,
{llvm::Constant::getNullValue(CGM.Int64Ty), ThreadID});
Address SrcMediumPtr(SrcMediumPtrVal, Align);
// SrcMediumVal = *SrcMediumPtr;
@@ -3004,7 +2247,8 @@
Address TargetElemPtr = Address(TargetElemPtrVal, Align);
TargetElemPtr = Bld.CreateElementBitCast(TargetElemPtr, CopyType);
if (NumIters > 1) {
- TargetElemPtr = Address(Bld.CreateGEP(TargetElemPtr.getPointer(), Cnt),
+ TargetElemPtr = Address(Bld.CreateGEP(TargetElemPtr.getElementType(),
+ TargetElemPtr.getPointer(), Cnt),
TargetElemPtr.getAlignment());
}
@@ -3327,9 +2571,10 @@
const FieldDecl *FD = VarFieldMap.lookup(VD);
LValue GlobLVal = CGF.EmitLValueForField(
CGF.MakeNaturalAlignAddrLValue(BufferArrPtr, StaticTy), FD);
- llvm::Value *BufferPtr =
- Bld.CreateInBoundsGEP(GlobLVal.getPointer(CGF), Idxs);
- GlobLVal.setAddress(Address(BufferPtr, GlobLVal.getAlignment()));
+ Address GlobAddr = GlobLVal.getAddress(CGF);
+ llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(
+ GlobAddr.getElementType(), GlobAddr.getPointer(), Idxs);
+ GlobLVal.setAddress(Address(BufferPtr, GlobAddr.getAlignment()));
switch (CGF.getEvaluationKind(Private->getType())) {
case TEK_Scalar: {
llvm::Value *V = CGF.EmitLoadOfScalar(
@@ -3426,8 +2671,9 @@
const FieldDecl *FD = VarFieldMap.lookup(VD);
LValue GlobLVal = CGF.EmitLValueForField(
CGF.MakeNaturalAlignAddrLValue(BufferArrPtr, StaticTy), FD);
- llvm::Value *BufferPtr =
- Bld.CreateInBoundsGEP(GlobLVal.getPointer(CGF), Idxs);
+ Address GlobAddr = GlobLVal.getAddress(CGF);
+ llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(
+ GlobAddr.getElementType(), GlobAddr.getPointer(), Idxs);
llvm::Value *Ptr = CGF.EmitCastToVoidPtr(BufferPtr);
CGF.EmitStoreOfScalar(Ptr, Elem, /*Volatile=*/false, C.VoidPtrTy);
if ((*IPriv)->getType()->isVariablyModifiedType()) {
@@ -3531,9 +2777,10 @@
const FieldDecl *FD = VarFieldMap.lookup(VD);
LValue GlobLVal = CGF.EmitLValueForField(
CGF.MakeNaturalAlignAddrLValue(BufferArrPtr, StaticTy), FD);
- llvm::Value *BufferPtr =
- Bld.CreateInBoundsGEP(GlobLVal.getPointer(CGF), Idxs);
- GlobLVal.setAddress(Address(BufferPtr, GlobLVal.getAlignment()));
+ Address GlobAddr = GlobLVal.getAddress(CGF);
+ llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(
+ GlobAddr.getElementType(), GlobAddr.getPointer(), Idxs);
+ GlobLVal.setAddress(Address(BufferPtr, GlobAddr.getAlignment()));
switch (CGF.getEvaluationKind(Private->getType())) {
case TEK_Scalar: {
llvm::Value *V = CGF.EmitLoadOfScalar(GlobLVal, Loc);
@@ -3630,8 +2877,9 @@
const FieldDecl *FD = VarFieldMap.lookup(VD);
LValue GlobLVal = CGF.EmitLValueForField(
CGF.MakeNaturalAlignAddrLValue(BufferArrPtr, StaticTy), FD);
- llvm::Value *BufferPtr =
- Bld.CreateInBoundsGEP(GlobLVal.getPointer(CGF), Idxs);
+ Address GlobAddr = GlobLVal.getAddress(CGF);
+ llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(
+ GlobAddr.getElementType(), GlobAddr.getPointer(), Idxs);
llvm::Value *Ptr = CGF.EmitCastToVoidPtr(BufferPtr);
CGF.EmitStoreOfScalar(Ptr, Elem, /*Volatile=*/false, C.VoidPtrTy);
if ((*IPriv)->getType()->isVariablyModifiedType()) {
@@ -4100,10 +3348,6 @@
if (Attr->getCaptureKind() == OMPC_map) {
PointeeTy = CGM.getContext().getAddrSpaceQualType(PointeeTy,
LangAS::opencl_global);
- } else if (Attr->getCaptureKind() == OMPC_firstprivate &&
- PointeeTy.isConstant(CGM.getContext())) {
- PointeeTy = CGM.getContext().getAddrSpaceQualType(PointeeTy,
- LangAS::opencl_generic);
}
}
ArgType = CGM.getContext().getPointerType(PointeeTy);
@@ -4210,6 +3454,15 @@
auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage,
Twine(OutlinedParallelFn->getName(), "_wrapper"), &CGM.getModule());
+
+ // Ensure we do not inline the function. This is trivially true for the ones
+ // passed to __kmpc_fork_call but the ones calles in serialized regions
+ // could be inlined. This is not a perfect but it is closer to the invariant
+ // we want, namely, every data environment starts with a new function.
+ // TODO: We should pass the if condition to the runtime function and do the
+ // handling there. Much cleaner code.
+ Fn->addFnAttr(llvm::Attribute::NoInline);
+
CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
Fn->setDoesNotRecurse();
@@ -4340,7 +3593,6 @@
auto I = FunctionGlobalizedDecls.try_emplace(CGF.CurFn).first;
I->getSecond().MappedParams =
std::make_unique<CodeGenFunction::OMPMapVars>();
- I->getSecond().GlobalRecord = GlobalizedVarsRecord;
I->getSecond().EscapedParameters.insert(
VarChecker.getEscapedParameters().begin(),
VarChecker.getEscapedParameters().end());
@@ -4349,21 +3601,16 @@
DeclToAddrMapTy &Data = I->getSecond().LocalVarData;
for (const ValueDecl *VD : VarChecker.getEscapedDecls()) {
assert(VD->isCanonicalDecl() && "Expected canonical declaration");
- const FieldDecl *FD = VarChecker.getFieldForGlobalizedVar(VD);
- Data.insert(std::make_pair(VD, MappedVarData(FD, IsInTTDRegion)));
+ Data.insert(std::make_pair(VD, MappedVarData()));
}
if (!IsInTTDRegion && !NeedToDelayGlobalization && !IsInParallelRegion) {
CheckVarsEscapingDeclContext VarChecker(CGF, llvm::None);
VarChecker.Visit(Body);
- I->getSecond().SecondaryGlobalRecord =
- VarChecker.getGlobalizedRecord(/*IsInTTDRegion=*/true);
I->getSecond().SecondaryLocalVarData.emplace();
DeclToAddrMapTy &Data = I->getSecond().SecondaryLocalVarData.getValue();
for (const ValueDecl *VD : VarChecker.getEscapedDecls()) {
assert(VD->isCanonicalDecl() && "Expected canonical declaration");
- const FieldDecl *FD = VarChecker.getFieldForGlobalizedVar(VD);
- Data.insert(
- std::make_pair(VD, MappedVarData(FD, /*IsInTTDRegion=*/true)));
+ Data.insert(std::make_pair(VD, MappedVarData()));
}
}
if (!NeedToDelayGlobalization) {
@@ -4535,10 +3782,6 @@
}
}
-unsigned CGOpenMPRuntimeGPU::getDefaultFirstprivateAddressSpace() const {
- return CGM.getContext().getTargetAddressSpace(LangAS::cuda_constant);
-}
-
bool CGOpenMPRuntimeGPU::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
LangAS &AS) {
if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
@@ -4598,10 +3841,7 @@
case CudaArch::SM_37:
case CudaArch::SM_50:
case CudaArch::SM_52:
- case CudaArch::SM_53:
- case CudaArch::SM_60:
- case CudaArch::SM_61:
- case CudaArch::SM_62: {
+ case CudaArch::SM_53: {
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
Out << "Target architecture " << CudaArchToString(Arch)
@@ -4609,10 +3849,14 @@
CGM.Error(Clause->getBeginLoc(), Out.str());
return;
}
+ case CudaArch::SM_60:
+ case CudaArch::SM_61:
+ case CudaArch::SM_62:
case CudaArch::SM_70:
case CudaArch::SM_72:
case CudaArch::SM_75:
case CudaArch::SM_80:
+ case CudaArch::SM_86:
case CudaArch::GFX600:
case CudaArch::GFX601:
case CudaArch::GFX602:
@@ -4633,14 +3877,18 @@
case CudaArch::GFX906:
case CudaArch::GFX908:
case CudaArch::GFX909:
+ case CudaArch::GFX90a:
case CudaArch::GFX90c:
case CudaArch::GFX1010:
case CudaArch::GFX1011:
case CudaArch::GFX1012:
+ case CudaArch::GFX1013:
case CudaArch::GFX1030:
case CudaArch::GFX1031:
case CudaArch::GFX1032:
case CudaArch::GFX1033:
+ case CudaArch::GFX1034:
+ case CudaArch::GFX1035:
case CudaArch::UNUSED:
case CudaArch::UNKNOWN:
break;
@@ -4652,183 +3900,8 @@
CGOpenMPRuntime::processRequiresDirective(D);
}
-/// Get number of SMs and number of blocks per SM.
-static std::pair<unsigned, unsigned> getSMsBlocksPerSM(CodeGenModule &CGM) {
- std::pair<unsigned, unsigned> Data;
- if (CGM.getLangOpts().OpenMPCUDANumSMs)
- Data.first = CGM.getLangOpts().OpenMPCUDANumSMs;
- if (CGM.getLangOpts().OpenMPCUDABlocksPerSM)
- Data.second = CGM.getLangOpts().OpenMPCUDABlocksPerSM;
- if (Data.first && Data.second)
- return Data;
- switch (getCudaArch(CGM)) {
- case CudaArch::SM_20:
- case CudaArch::SM_21:
- case CudaArch::SM_30:
- case CudaArch::SM_32:
- case CudaArch::SM_35:
- case CudaArch::SM_37:
- case CudaArch::SM_50:
- case CudaArch::SM_52:
- case CudaArch::SM_53:
- return {16, 16};
- case CudaArch::SM_60:
- case CudaArch::SM_61:
- case CudaArch::SM_62:
- return {56, 32};
- case CudaArch::SM_70:
- case CudaArch::SM_72:
- case CudaArch::SM_75:
- case CudaArch::SM_80:
- return {84, 32};
- case CudaArch::GFX600:
- case CudaArch::GFX601:
- case CudaArch::GFX602:
- case CudaArch::GFX700:
- case CudaArch::GFX701:
- case CudaArch::GFX702:
- case CudaArch::GFX703:
- case CudaArch::GFX704:
- case CudaArch::GFX705:
- case CudaArch::GFX801:
- case CudaArch::GFX802:
- case CudaArch::GFX803:
- case CudaArch::GFX805:
- case CudaArch::GFX810:
- case CudaArch::GFX900:
- case CudaArch::GFX902:
- case CudaArch::GFX904:
- case CudaArch::GFX906:
- case CudaArch::GFX908:
- case CudaArch::GFX909:
- case CudaArch::GFX90c:
- case CudaArch::GFX1010:
- case CudaArch::GFX1011:
- case CudaArch::GFX1012:
- case CudaArch::GFX1030:
- case CudaArch::GFX1031:
- case CudaArch::GFX1032:
- case CudaArch::GFX1033:
- case CudaArch::UNUSED:
- case CudaArch::UNKNOWN:
- break;
- case CudaArch::LAST:
- llvm_unreachable("Unexpected Cuda arch.");
- }
- llvm_unreachable("Unexpected NVPTX target without ptx feature.");
-}
-
void CGOpenMPRuntimeGPU::clear() {
- if (!GlobalizedRecords.empty() &&
- !CGM.getLangOpts().OpenMPCUDATargetParallel) {
- ASTContext &C = CGM.getContext();
- llvm::SmallVector<const GlobalPtrSizeRecsTy *, 4> GlobalRecs;
- llvm::SmallVector<const GlobalPtrSizeRecsTy *, 4> SharedRecs;
- RecordDecl *StaticRD = C.buildImplicitRecord(
- "_openmp_static_memory_type_$_", RecordDecl::TagKind::TTK_Union);
- StaticRD->startDefinition();
- RecordDecl *SharedStaticRD = C.buildImplicitRecord(
- "_shared_openmp_static_memory_type_$_", RecordDecl::TagKind::TTK_Union);
- SharedStaticRD->startDefinition();
- for (const GlobalPtrSizeRecsTy &Records : GlobalizedRecords) {
- if (Records.Records.empty())
- continue;
- unsigned Size = 0;
- unsigned RecAlignment = 0;
- for (const RecordDecl *RD : Records.Records) {
- QualType RDTy = C.getRecordType(RD);
- unsigned Alignment = C.getTypeAlignInChars(RDTy).getQuantity();
- RecAlignment = std::max(RecAlignment, Alignment);
- unsigned RecSize = C.getTypeSizeInChars(RDTy).getQuantity();
- Size =
- llvm::alignTo(llvm::alignTo(Size, Alignment) + RecSize, Alignment);
- }
- Size = llvm::alignTo(Size, RecAlignment);
- llvm::APInt ArySize(/*numBits=*/64, Size);
- QualType SubTy = C.getConstantArrayType(
- C.CharTy, ArySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
- const bool UseSharedMemory = Size <= SharedMemorySize;
- auto *Field =
- FieldDecl::Create(C, UseSharedMemory ? SharedStaticRD : StaticRD,
- SourceLocation(), SourceLocation(), nullptr, SubTy,
- C.getTrivialTypeSourceInfo(SubTy, SourceLocation()),
- /*BW=*/nullptr, /*Mutable=*/false,
- /*InitStyle=*/ICIS_NoInit);
- Field->setAccess(AS_public);
- if (UseSharedMemory) {
- SharedStaticRD->addDecl(Field);
- SharedRecs.push_back(&Records);
- } else {
- StaticRD->addDecl(Field);
- GlobalRecs.push_back(&Records);
- }
- Records.RecSize->setInitializer(llvm::ConstantInt::get(CGM.SizeTy, Size));
- Records.UseSharedMemory->setInitializer(
- llvm::ConstantInt::get(CGM.Int16Ty, UseSharedMemory ? 1 : 0));
- }
- // Allocate SharedMemorySize buffer for the shared memory.
- // FIXME: nvlink does not handle weak linkage correctly (object with the
- // different size are reported as erroneous).
- // Restore this code as sson as nvlink is fixed.
- if (!SharedStaticRD->field_empty()) {
- llvm::APInt ArySize(/*numBits=*/64, SharedMemorySize);
- QualType SubTy = C.getConstantArrayType(
- C.CharTy, ArySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
- auto *Field = FieldDecl::Create(
- C, SharedStaticRD, SourceLocation(), SourceLocation(), nullptr, SubTy,
- C.getTrivialTypeSourceInfo(SubTy, SourceLocation()),
- /*BW=*/nullptr, /*Mutable=*/false,
- /*InitStyle=*/ICIS_NoInit);
- Field->setAccess(AS_public);
- SharedStaticRD->addDecl(Field);
- }
- SharedStaticRD->completeDefinition();
- if (!SharedStaticRD->field_empty()) {
- QualType StaticTy = C.getRecordType(SharedStaticRD);
- llvm::Type *LLVMStaticTy = CGM.getTypes().ConvertTypeForMem(StaticTy);
- auto *GV = new llvm::GlobalVariable(
- CGM.getModule(), LLVMStaticTy,
- /*isConstant=*/false, llvm::GlobalValue::WeakAnyLinkage,
- llvm::UndefValue::get(LLVMStaticTy),
- "_openmp_shared_static_glob_rd_$_", /*InsertBefore=*/nullptr,
- llvm::GlobalValue::NotThreadLocal,
- C.getTargetAddressSpace(LangAS::cuda_shared));
- auto *Replacement = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
- GV, CGM.VoidPtrTy);
- for (const GlobalPtrSizeRecsTy *Rec : SharedRecs) {
- Rec->Buffer->replaceAllUsesWith(Replacement);
- Rec->Buffer->eraseFromParent();
- }
- }
- StaticRD->completeDefinition();
- if (!StaticRD->field_empty()) {
- QualType StaticTy = C.getRecordType(StaticRD);
- std::pair<unsigned, unsigned> SMsBlockPerSM = getSMsBlocksPerSM(CGM);
- llvm::APInt Size1(32, SMsBlockPerSM.second);
- QualType Arr1Ty =
- C.getConstantArrayType(StaticTy, Size1, nullptr, ArrayType::Normal,
- /*IndexTypeQuals=*/0);
- llvm::APInt Size2(32, SMsBlockPerSM.first);
- QualType Arr2Ty =
- C.getConstantArrayType(Arr1Ty, Size2, nullptr, ArrayType::Normal,
- /*IndexTypeQuals=*/0);
- llvm::Type *LLVMArr2Ty = CGM.getTypes().ConvertTypeForMem(Arr2Ty);
- // FIXME: nvlink does not handle weak linkage correctly (object with the
- // different size are reported as erroneous).
- // Restore CommonLinkage as soon as nvlink is fixed.
- auto *GV = new llvm::GlobalVariable(
- CGM.getModule(), LLVMArr2Ty,
- /*isConstant=*/false, llvm::GlobalValue::InternalLinkage,
- llvm::Constant::getNullValue(LLVMArr2Ty),
- "_openmp_static_glob_rd_$_");
- auto *Replacement = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
- GV, CGM.VoidPtrTy);
- for (const GlobalPtrSizeRecsTy *Rec : GlobalRecs) {
- Rec->Buffer->replaceAllUsesWith(Replacement);
- Rec->Buffer->eraseFromParent();
- }
- }
- }
+
if (!TeamsReductions.empty()) {
ASTContext &C = CGM.getContext();
RecordDecl *StaticRD = C.buildImplicitRecord(
diff --git a/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h b/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h
index 7267511..b5f1b84 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h
+++ b/src/llvm-project/clang/lib/CodeGen/CGOpenMPRuntimeGPU.h
@@ -38,19 +38,7 @@
llvm::SmallVector<llvm::Function *, 16> Work;
struct EntryFunctionState {
- llvm::BasicBlock *ExitBB = nullptr;
- };
-
- class WorkerFunctionState {
- public:
- llvm::Function *WorkerFn;
- const CGFunctionInfo &CGFI;
SourceLocation Loc;
-
- WorkerFunctionState(CodeGenModule &CGM, SourceLocation Loc);
-
- private:
- void createWorkerFunction(CodeGenModule &CGM);
};
ExecutionMode getExecutionMode() const;
@@ -60,20 +48,13 @@
/// Get barrier to synchronize all threads in a block.
void syncCTAThreads(CodeGenFunction &CGF);
- /// Emit the worker function for the current target region.
- void emitWorkerFunction(WorkerFunctionState &WST);
+ /// Helper for target directive initialization.
+ void emitKernelInit(CodeGenFunction &CGF, EntryFunctionState &EST,
+ bool IsSPMD);
- /// Helper for worker function. Emit body of worker loop.
- void emitWorkerLoop(CodeGenFunction &CGF, WorkerFunctionState &WST);
-
- /// Helper for non-SPMD target entry function. Guide the master and
- /// worker threads to their respective locations.
- void emitNonSPMDEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST,
- WorkerFunctionState &WST);
-
- /// Signal termination of OMP execution for non-SPMD target entry
- /// function.
- void emitNonSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST);
+ /// Helper for target directive finalization.
+ void emitKernelDeinit(CodeGenFunction &CGF, EntryFunctionState &EST,
+ bool IsSPMD);
/// Helper for generic variables globalization prolog.
void emitGenericVarsProlog(CodeGenFunction &CGF, SourceLocation Loc,
@@ -82,13 +63,6 @@
/// Helper for generic variables globalization epilog.
void emitGenericVarsEpilog(CodeGenFunction &CGF, bool WithSPMDCheck = false);
- /// Helper for SPMD mode target directive's entry function.
- void emitSPMDEntryHeader(CodeGenFunction &CGF, EntryFunctionState &EST,
- const OMPExecutableDirective &D);
-
- /// Signal termination of SPMD mode execution.
- void emitSPMDEntryFooter(CodeGenFunction &CGF, EntryFunctionState &EST);
-
//
// Base class overrides.
//
@@ -399,10 +373,6 @@
/// supports unified addressing
void processRequiresDirective(const OMPRequiresDecl *D) override;
- /// Returns default address space for the constant firstprivates, __constant__
- /// address space by default.
- unsigned getDefaultFirstprivateAddressSpace() const override;
-
/// Checks if the variable has associated OMPAllocateDeclAttr attribute with
/// the predefined allocator and translates it into the corresponding address
/// space.
@@ -440,15 +410,9 @@
/// The data for the single globalized variable.
struct MappedVarData {
/// Corresponding field in the global record.
- const FieldDecl *FD = nullptr;
+ llvm::Value *GlobalizedVal = nullptr;
/// Corresponding address.
Address PrivateAddr = Address::invalid();
- /// true, if only one element is required (for latprivates in SPMD mode),
- /// false, if need to create based on the warp-size.
- bool IsOnePerTeam = false;
- MappedVarData() = delete;
- MappedVarData(const FieldDecl *FD, bool IsOnePerTeam = false)
- : FD(FD), IsOnePerTeam(IsOnePerTeam) {}
};
/// The map of local variables to their addresses in the global memory.
using DeclToAddrMapTy = llvm::MapVector<const Decl *, MappedVarData>;
@@ -459,30 +423,14 @@
llvm::Optional<DeclToAddrMapTy> SecondaryLocalVarData = llvm::None;
EscapedParamsTy EscapedParameters;
llvm::SmallVector<const ValueDecl*, 4> EscapedVariableLengthDecls;
- llvm::SmallVector<llvm::Value *, 4> EscapedVariableLengthDeclsAddrs;
- const RecordDecl *GlobalRecord = nullptr;
- llvm::Optional<const RecordDecl *> SecondaryGlobalRecord = llvm::None;
- llvm::Value *GlobalRecordAddr = nullptr;
+ llvm::SmallVector<std::pair<llvm::Value *, llvm::Value *>, 4>
+ EscapedVariableLengthDeclsAddrs;
llvm::Value *IsInSPMDModeFlag = nullptr;
std::unique_ptr<CodeGenFunction::OMPMapVars> MappedParams;
};
/// Maps the function to the list of the globalized variables with their
/// addresses.
llvm::SmallDenseMap<llvm::Function *, FunctionData> FunctionGlobalizedDecls;
- /// List of records for the globalized variables in target/teams/distribute
- /// contexts. Inner records are going to be joined into the single record,
- /// while those resulting records are going to be joined into the single
- /// union. This resulting union (one per CU) is the entry point for the static
- /// memory management runtime functions.
- struct GlobalPtrSizeRecsTy {
- llvm::GlobalVariable *UseSharedMemory = nullptr;
- llvm::GlobalVariable *RecSize = nullptr;
- llvm::GlobalVariable *Buffer = nullptr;
- SourceLocation Loc;
- llvm::SmallVector<const RecordDecl *, 2> Records;
- unsigned RegionCounter = 0;
- };
- llvm::SmallVector<GlobalPtrSizeRecsTy, 8> GlobalizedRecords;
llvm::GlobalVariable *KernelTeamsReductionPtr = nullptr;
/// List of the records with the list of fields for the reductions across the
/// teams. Used to build the intermediate buffer for the fast teams
diff --git a/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp b/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp
index a1a72a9..0a3a722 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGStmt.cpp
@@ -16,6 +16,8 @@
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticSema.h"
@@ -194,12 +196,21 @@
case Stmt::SEHTryStmtClass:
EmitSEHTryStmt(cast<SEHTryStmt>(*S));
break;
+ case Stmt::OMPCanonicalLoopClass:
+ EmitOMPCanonicalLoop(cast<OMPCanonicalLoop>(S));
+ break;
case Stmt::OMPParallelDirectiveClass:
EmitOMPParallelDirective(cast<OMPParallelDirective>(*S));
break;
case Stmt::OMPSimdDirectiveClass:
EmitOMPSimdDirective(cast<OMPSimdDirective>(*S));
break;
+ case Stmt::OMPTileDirectiveClass:
+ EmitOMPTileDirective(cast<OMPTileDirective>(*S));
+ break;
+ case Stmt::OMPUnrollDirectiveClass:
+ EmitOMPUnrollDirective(cast<OMPUnrollDirective>(*S));
+ break;
case Stmt::OMPForDirectiveClass:
EmitOMPForDirective(cast<OMPForDirective>(*S));
break;
@@ -369,6 +380,15 @@
EmitOMPTargetTeamsDistributeSimdDirective(
cast<OMPTargetTeamsDistributeSimdDirective>(*S));
break;
+ case Stmt::OMPInteropDirectiveClass:
+ llvm_unreachable("Interop directive not supported yet.");
+ break;
+ case Stmt::OMPDispatchDirectiveClass:
+ llvm_unreachable("Dispatch directive not supported yet.");
+ break;
+ case Stmt::OMPMaskedDirectiveClass:
+ EmitOMPMaskedDirective(cast<OMPMaskedDirective>(*S));
+ break;
}
}
@@ -629,17 +649,30 @@
void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
EmitLabel(S.getDecl());
+
+ // IsEHa - emit eha.scope.begin if it's a side entry of a scope
+ if (getLangOpts().EHAsynch && S.isSideEntry())
+ EmitSehCppScopeBegin();
+
EmitStmt(S.getSubStmt());
}
void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
bool nomerge = false;
- for (const auto *A : S.getAttrs())
+ const CallExpr *musttail = nullptr;
+
+ for (const auto *A : S.getAttrs()) {
if (A->getKind() == attr::NoMerge) {
nomerge = true;
- break;
}
+ if (A->getKind() == attr::MustTail) {
+ const Stmt *Sub = S.getSubStmt();
+ const ReturnStmt *R = cast<ReturnStmt>(Sub);
+ musttail = cast<CallExpr>(R->getRetValue()->IgnoreParens());
+ }
+ }
SaveAndRestore<bool> save_nomerge(InNoMergeAttributedStmt, nomerge);
+ SaveAndRestore<const CallExpr *> save_musttail(MustTailCall, musttail);
EmitStmt(S.getSubStmt(), S.getAttrs());
}
@@ -791,20 +824,14 @@
// while(1) is common, avoid extra exit blocks. Be sure
// to correctly handle break/continue though.
- bool EmitBoolCondBranch = true;
- bool LoopMustProgress = false;
- if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
- if (C->isOne()) {
- EmitBoolCondBranch = false;
- FnIsMustProgress = false;
- }
- } else if (LanguageRequiresProgress())
- LoopMustProgress = true;
-
+ llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
+ bool CondIsConstInt = C != nullptr;
+ bool EmitBoolCondBranch = !CondIsConstInt || !C->isOne();
const SourceRange &R = S.getSourceRange();
LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), CGM.getCodeGenOpts(),
WhileAttrs, SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
+ SourceLocToDebugLoc(R.getEnd()),
+ checkIfLoopMustProgress(CondIsConstInt));
// As long as the condition is true, go to the loop body.
llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
@@ -812,8 +839,11 @@
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ConditionScope.requiresCleanups())
ExitBlock = createBasicBlock("while.exit");
- llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop(
- S.getCond(), getProfileCount(S.getBody()), S.getBody());
+ llvm::MDNode *Weights =
+ createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
+ if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
+ BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
+ BoolCondVal, Stmt::getLikelihood(S.getBody()));
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
if (ExitBlock != LoopExit.getBlock()) {
@@ -892,20 +922,15 @@
// "do {} while (0)" is common in macros, avoid extra blocks. Be sure
// to correctly handle break/continue though.
- bool EmitBoolCondBranch = true;
- bool LoopMustProgress = false;
- if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
- if (C->isZero())
- EmitBoolCondBranch = false;
- else if (C->isOne())
- FnIsMustProgress = false;
- } else if (LanguageRequiresProgress())
- LoopMustProgress = true;
+ llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
+ bool CondIsConstInt = C;
+ bool EmitBoolCondBranch = !C || !C->isZero();
const SourceRange &R = S.getSourceRange();
LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
+ SourceLocToDebugLoc(R.getEnd()),
+ checkIfLoopMustProgress(CondIsConstInt));
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch) {
@@ -939,43 +964,47 @@
// Start the loop with a block that tests the condition.
// If there's an increment, the continue scope will be overwritten
// later.
- JumpDest Continue = getJumpDestInCurrentScope("for.cond");
- llvm::BasicBlock *CondBlock = Continue.getBlock();
+ JumpDest CondDest = getJumpDestInCurrentScope("for.cond");
+ llvm::BasicBlock *CondBlock = CondDest.getBlock();
EmitBlock(CondBlock);
- bool LoopMustProgress = false;
Expr::EvalResult Result;
- if (LanguageRequiresProgress()) {
- if (!S.getCond()) {
- FnIsMustProgress = false;
- } else if (!S.getCond()->EvaluateAsInt(Result, getContext())) {
- LoopMustProgress = true;
- }
- }
+ bool CondIsConstInt =
+ !S.getCond() || S.getCond()->EvaluateAsInt(Result, getContext());
const SourceRange &R = S.getSourceRange();
LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs,
SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
-
- // If the for loop doesn't have an increment we can just use the
- // condition as the continue block. Otherwise we'll need to create
- // a block for it (in the current scope, i.e. in the scope of the
- // condition), and that we will become our continue block.
- if (S.getInc())
- Continue = getJumpDestInCurrentScope("for.inc");
-
- // Store the blocks to use for break and continue.
- BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
+ SourceLocToDebugLoc(R.getEnd()),
+ checkIfLoopMustProgress(CondIsConstInt));
// Create a cleanup scope for the condition variable cleanups.
LexicalScope ConditionScope(*this, S.getSourceRange());
+ // If the for loop doesn't have an increment we can just use the condition as
+ // the continue block. Otherwise, if there is no condition variable, we can
+ // form the continue block now. If there is a condition variable, we can't
+ // form the continue block until after we've emitted the condition, because
+ // the condition is in scope in the increment, but Sema's jump diagnostics
+ // ensure that there are no continues from the condition variable that jump
+ // to the loop increment.
+ JumpDest Continue;
+ if (!S.getInc())
+ Continue = CondDest;
+ else if (!S.getConditionVariable())
+ Continue = getJumpDestInCurrentScope("for.inc");
+ BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
+
if (S.getCond()) {
// If the for statement has a condition scope, emit the local variable
// declaration.
if (S.getConditionVariable()) {
EmitDecl(*S.getConditionVariable());
+
+ // We have entered the condition variable's scope, so we're now able to
+ // jump to the continue block.
+ Continue = S.getInc() ? getJumpDestInCurrentScope("for.inc") : CondDest;
+ BreakContinueStack.back().ContinueBlock = Continue;
}
llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
@@ -990,12 +1019,11 @@
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop(
- S.getCond(), getProfileCount(S.getBody()), S.getBody());
-
- if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
- if (C->isOne())
- FnIsMustProgress = false;
+ llvm::MDNode *Weights =
+ createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
+ if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
+ BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
+ BoolCondVal, Stmt::getLikelihood(S.getBody()));
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
@@ -1076,8 +1104,11 @@
// The body is executed if the expression, contextually converted
// to bool, is true.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
- llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop(
- S.getCond(), getProfileCount(S.getBody()), S.getBody());
+ llvm::MDNode *Weights =
+ createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody()));
+ if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
+ BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
+ BoolCondVal, Stmt::getLikelihood(S.getBody()));
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
if (ExitBlock != LoopExit.getBlock()) {
@@ -1145,6 +1176,38 @@
};
} // namespace
+/// If we have 'return f(...);', where both caller and callee are SwiftAsync,
+/// codegen it as 'tail call ...; ret void;'.
+static void makeTailCallIfSwiftAsync(const CallExpr *CE, CGBuilderTy &Builder,
+ const CGFunctionInfo *CurFnInfo) {
+ auto calleeQualType = CE->getCallee()->getType();
+ const FunctionType *calleeType = nullptr;
+ if (calleeQualType->isFunctionPointerType() ||
+ calleeQualType->isFunctionReferenceType() ||
+ calleeQualType->isBlockPointerType() ||
+ calleeQualType->isMemberFunctionPointerType()) {
+ calleeType = calleeQualType->getPointeeType()->castAs<FunctionType>();
+ } else if (auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
+ calleeType = ty;
+ } else if (auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
+ if (auto methodDecl = CMCE->getMethodDecl()) {
+ // getMethodDecl() doesn't handle member pointers at the moment.
+ calleeType = methodDecl->getType()->castAs<FunctionType>();
+ } else {
+ return;
+ }
+ } else {
+ return;
+ }
+ if (calleeType->getCallConv() == CallingConv::CC_SwiftAsync &&
+ (CurFnInfo->getASTCallingConvention() == CallingConv::CC_SwiftAsync)) {
+ auto CI = cast<llvm::CallInst>(&Builder.GetInsertBlock()->back());
+ CI->setTailCallKind(llvm::CallInst::TCK_MustTail);
+ Builder.CreateRetVoid();
+ Builder.ClearInsertionPoint();
+ }
+}
+
/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
@@ -1203,8 +1266,11 @@
} else if (!ReturnValue.isValid() || (RV && RV->getType()->isVoidType())) {
// Make sure not to return anything, but evaluate the expression
// for side effects.
- if (RV)
+ if (RV) {
EmitAnyExpr(RV);
+ if (auto *CE = dyn_cast<CallExpr>(RV))
+ makeTailCallIfSwiftAsync(CE, Builder, CurFnInfo);
+ }
} else if (!RV) {
// Do nothing (return value is left uninitialized)
} else if (FnRetTy->isReferenceType()) {
@@ -1351,7 +1417,7 @@
// this case.
(*SwitchWeights)[0] += ThisCount;
} else if (SwitchLikelihood)
- Weights = createBranchWeights(LH);
+ Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH);
Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights);
@@ -2031,7 +2097,8 @@
} else {
llvm::Type *Ty = ConvertType(InputType);
uint64_t Size = CGM.getDataLayout().getTypeSizeInBits(Ty);
- if (Size <= 64 && llvm::isPowerOf2_64(Size)) {
+ if ((Size <= 64 && llvm::isPowerOf2_64(Size)) ||
+ getTargetHooks().isScalarizableAsmOperand(*this, Ty)) {
Ty = llvm::IntegerType::get(getLLVMContext(), Size);
Ty = llvm::PointerType::getUnqual(Ty);
@@ -2092,7 +2159,7 @@
SmallVector<llvm::Metadata *, 8> Locs;
// Add the location of the first line to the MDNode.
Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
- CGF.Int32Ty, Str->getBeginLoc().getRawEncoding())));
+ CGF.Int64Ty, Str->getBeginLoc().getRawEncoding())));
StringRef StrVal = Str->getString();
if (!StrVal.empty()) {
const SourceManager &SM = CGF.CGM.getContext().getSourceManager();
@@ -2107,7 +2174,7 @@
SourceLocation LineLoc = Str->getLocationOfByte(
i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset);
Locs.push_back(llvm::ConstantAsMetadata::get(
- llvm::ConstantInt::get(CGF.Int32Ty, LineLoc.getRawEncoding())));
+ llvm::ConstantInt::get(CGF.Int64Ty, LineLoc.getRawEncoding())));
}
}
@@ -2115,13 +2182,15 @@
}
static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect,
- bool ReadOnly, bool ReadNone, bool NoMerge,
- const AsmStmt &S,
+ bool HasUnwindClobber, bool ReadOnly,
+ bool ReadNone, bool NoMerge, const AsmStmt &S,
const std::vector<llvm::Type *> &ResultRegTypes,
CodeGenFunction &CGF,
std::vector<llvm::Value *> &RegResults) {
- Result.addAttribute(llvm::AttributeList::FunctionIndex,
- llvm::Attribute::NoUnwind);
+ if (!HasUnwindClobber)
+ Result.addAttribute(llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoUnwind);
+
if (NoMerge)
Result.addAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoMerge);
@@ -2142,8 +2211,8 @@
getAsmSrcLocInfo(gccAsmStmt->getAsmString(), CGF));
else {
// At least put the line number on MS inline asm blobs.
- llvm::Constant *Loc = llvm::ConstantInt::get(CGF.Int32Ty,
- S.getAsmLoc().getRawEncoding());
+ llvm::Constant *Loc =
+ llvm::ConstantInt::get(CGF.Int64Ty, S.getAsmLoc().getRawEncoding());
Result.setMetadata("srcloc",
llvm::MDNode::get(CGF.getLLVMContext(),
llvm::ConstantAsMetadata::get(Loc)));
@@ -2252,23 +2321,28 @@
// If this is a register output, then make the inline asm return it
// by-value. If this is a memory result, return the value by-reference.
- bool isScalarizableAggregate =
- hasAggregateEvaluationKind(OutExpr->getType());
- if (!Info.allowsMemory() && (hasScalarEvaluationKind(OutExpr->getType()) ||
- isScalarizableAggregate)) {
+ QualType QTy = OutExpr->getType();
+ const bool IsScalarOrAggregate = hasScalarEvaluationKind(QTy) ||
+ hasAggregateEvaluationKind(QTy);
+ if (!Info.allowsMemory() && IsScalarOrAggregate) {
+
Constraints += "=" + OutputConstraint;
- ResultRegQualTys.push_back(OutExpr->getType());
+ ResultRegQualTys.push_back(QTy);
ResultRegDests.push_back(Dest);
- ResultTruncRegTypes.push_back(ConvertTypeForMem(OutExpr->getType()));
- if (Info.allowsRegister() && isScalarizableAggregate) {
- ResultTypeRequiresCast.push_back(true);
- unsigned Size = getContext().getTypeSize(OutExpr->getType());
- llvm::Type *ConvTy = llvm::IntegerType::get(getLLVMContext(), Size);
- ResultRegTypes.push_back(ConvTy);
- } else {
- ResultTypeRequiresCast.push_back(false);
- ResultRegTypes.push_back(ResultTruncRegTypes.back());
+
+ llvm::Type *Ty = ConvertTypeForMem(QTy);
+ const bool RequiresCast = Info.allowsRegister() &&
+ (getTargetHooks().isScalarizableAsmOperand(*this, Ty) ||
+ Ty->isAggregateType());
+
+ ResultTruncRegTypes.push_back(Ty);
+ ResultTypeRequiresCast.push_back(RequiresCast);
+
+ if (RequiresCast) {
+ unsigned Size = getContext().getTypeSize(QTy);
+ Ty = llvm::IntegerType::get(getLLVMContext(), Size);
}
+ ResultRegTypes.push_back(Ty);
// If this output is tied to an input, and if the input is larger, then
// we need to set the actual result type of the inline asm node to be the
// same as the input type.
@@ -2468,13 +2542,18 @@
}
Constraints += InOutConstraints;
+ bool HasUnwindClobber = false;
+
// Clobbers
for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
StringRef Clobber = S.getClobber(i);
if (Clobber == "memory")
ReadOnly = ReadNone = false;
- else if (Clobber != "cc") {
+ else if (Clobber == "unwind") {
+ HasUnwindClobber = true;
+ continue;
+ } else if (Clobber != "cc") {
Clobber = getTarget().getNormalizedGCCRegisterName(Clobber);
if (CGM.getCodeGenOpts().StackClashProtector &&
getTarget().isSPRegName(Clobber)) {
@@ -2483,6 +2562,23 @@
}
}
+ if (isa<MSAsmStmt>(&S)) {
+ if (Clobber == "eax" || Clobber == "edx") {
+ if (Constraints.find("=&A") != std::string::npos)
+ continue;
+ std::string::size_type position1 =
+ Constraints.find("={" + Clobber.str() + "}");
+ if (position1 != std::string::npos) {
+ Constraints.insert(position1 + 1, "&");
+ continue;
+ }
+ std::string::size_type position2 = Constraints.find("=A");
+ if (position2 != std::string::npos) {
+ Constraints.insert(position2 + 1, "&");
+ continue;
+ }
+ }
+ }
if (!Constraints.empty())
Constraints += ',';
@@ -2491,6 +2587,9 @@
Constraints += '}';
}
+ assert(!(HasUnwindClobber && IsGCCAsmGoto) &&
+ "unwind clobber can't be used with asm goto");
+
// Add machine specific clobbers
std::string MachineClobbers = getTarget().getClobbers();
if (!MachineClobbers.empty()) {
@@ -2513,23 +2612,28 @@
bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0;
llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ?
llvm::InlineAsm::AD_Intel : llvm::InlineAsm::AD_ATT;
- llvm::InlineAsm *IA =
- llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect,
- /* IsAlignStack */ false, AsmDialect);
+ llvm::InlineAsm *IA = llvm::InlineAsm::get(
+ FTy, AsmString, Constraints, HasSideEffect,
+ /* IsAlignStack */ false, AsmDialect, HasUnwindClobber);
std::vector<llvm::Value*> RegResults;
if (IsGCCAsmGoto) {
llvm::CallBrInst *Result =
Builder.CreateCallBr(IA, Fallthrough, Transfer, Args);
EmitBlock(Fallthrough);
- UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, ReadOnly,
- ReadNone, InNoMergeAttributedStmt, S, ResultRegTypes,
- *this, RegResults);
+ UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, false,
+ ReadOnly, ReadNone, InNoMergeAttributedStmt, S,
+ ResultRegTypes, *this, RegResults);
+ } else if (HasUnwindClobber) {
+ llvm::CallBase *Result = EmitCallOrInvoke(IA, Args, "");
+ UpdateAsmCallInst(*Result, HasSideEffect, true, ReadOnly, ReadNone,
+ InNoMergeAttributedStmt, S, ResultRegTypes, *this,
+ RegResults);
} else {
llvm::CallInst *Result =
Builder.CreateCall(IA, Args, getBundlesForFunclet(IA));
- UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, ReadOnly,
- ReadNone, InNoMergeAttributedStmt, S, ResultRegTypes,
- *this, RegResults);
+ UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, false,
+ ReadOnly, ReadNone, InNoMergeAttributedStmt, S,
+ ResultRegTypes, *this, RegResults);
}
assert(RegResults.size() == ResultRegTypes.size());
@@ -2540,11 +2644,11 @@
assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {
llvm::Value *Tmp = RegResults[i];
+ llvm::Type *TruncTy = ResultTruncRegTypes[i];
// If the result type of the LLVM IR asm doesn't match the result type of
// the expression, do the conversion.
if (ResultRegTypes[i] != ResultTruncRegTypes[i]) {
- llvm::Type *TruncTy = ResultTruncRegTypes[i];
// Truncate the integer result to the right size, note that TruncTy can be
// a pointer.
@@ -2574,6 +2678,11 @@
unsigned Size = getContext().getTypeSize(ResultRegQualTys[i]);
Address A = Builder.CreateBitCast(Dest.getAddress(*this),
ResultRegTypes[i]->getPointerTo());
+ if (getTargetHooks().isScalarizableAsmOperand(*this, TruncTy)) {
+ Builder.CreateStore(Tmp, A);
+ continue;
+ }
+
QualType Ty = getContext().getIntTypeForBitwidth(Size, /*Signed*/ false);
if (Ty.isNull()) {
const Expr *OutExpr = S.getOutputExpr(i);
diff --git a/src/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp b/src/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 5e8d98c..f6233b7 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -133,50 +133,55 @@
/// Private scope for OpenMP loop-based directives, that supports capturing
/// of used expression from loop statement.
class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
- void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) {
+ void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopBasedDirective &S) {
+ const DeclStmt *PreInits;
CodeGenFunction::OMPMapVars PreCondVars;
- llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
- for (const auto *E : S.counters()) {
- const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- EmittedAsPrivate.insert(VD->getCanonicalDecl());
- (void)PreCondVars.setVarAddr(
- CGF, VD, CGF.CreateMemTemp(VD->getType().getNonReferenceType()));
- }
- // Mark private vars as undefs.
- for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
- for (const Expr *IRef : C->varlists()) {
- const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
- if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
- (void)PreCondVars.setVarAddr(
- CGF, OrigVD,
- Address(llvm::UndefValue::get(
- CGF.ConvertTypeForMem(CGF.getContext().getPointerType(
- OrigVD->getType().getNonReferenceType()))),
- CGF.getContext().getDeclAlign(OrigVD)));
+ if (auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
+ llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
+ for (const auto *E : LD->counters()) {
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ EmittedAsPrivate.insert(VD->getCanonicalDecl());
+ (void)PreCondVars.setVarAddr(
+ CGF, VD, CGF.CreateMemTemp(VD->getType().getNonReferenceType()));
+ }
+ // Mark private vars as undefs.
+ for (const auto *C : LD->getClausesOfKind<OMPPrivateClause>()) {
+ for (const Expr *IRef : C->varlists()) {
+ const auto *OrigVD =
+ cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
+ if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
+ (void)PreCondVars.setVarAddr(
+ CGF, OrigVD,
+ Address(llvm::UndefValue::get(CGF.ConvertTypeForMem(
+ CGF.getContext().getPointerType(
+ OrigVD->getType().getNonReferenceType()))),
+ CGF.getContext().getDeclAlign(OrigVD)));
+ }
}
}
+ (void)PreCondVars.apply(CGF);
+ // Emit init, __range and __end variables for C++ range loops.
+ (void)OMPLoopBasedDirective::doForAllLoops(
+ LD->getInnermostCapturedStmt()->getCapturedStmt(),
+ /*TryImperfectlyNestedLoops=*/true, LD->getLoopsNumber(),
+ [&CGF](unsigned Cnt, const Stmt *CurStmt) {
+ if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
+ if (const Stmt *Init = CXXFor->getInit())
+ CGF.EmitStmt(Init);
+ CGF.EmitStmt(CXXFor->getRangeStmt());
+ CGF.EmitStmt(CXXFor->getEndStmt());
+ }
+ return false;
+ });
+ PreInits = cast_or_null<DeclStmt>(LD->getPreInits());
+ } else if (const auto *Tile = dyn_cast<OMPTileDirective>(&S)) {
+ PreInits = cast_or_null<DeclStmt>(Tile->getPreInits());
+ } else if (const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
+ PreInits = cast_or_null<DeclStmt>(Unroll->getPreInits());
+ } else {
+ llvm_unreachable("Unknown loop-based directive kind.");
}
- (void)PreCondVars.apply(CGF);
- // Emit init, __range and __end variables for C++ range loops.
- const Stmt *Body =
- S.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
- for (unsigned Cnt = 0; Cnt < S.getCollapsedNumber(); ++Cnt) {
- Body = OMPLoopDirective::tryToFindNextInnerLoop(
- Body, /*TryImperfectlyNestedLoops=*/true);
- if (auto *For = dyn_cast<ForStmt>(Body)) {
- Body = For->getBody();
- } else {
- assert(isa<CXXForRangeStmt>(Body) &&
- "Expected canonical for loop or range-based for loop.");
- auto *CXXFor = cast<CXXForRangeStmt>(Body);
- if (const Stmt *Init = CXXFor->getInit())
- CGF.EmitStmt(Init);
- CGF.EmitStmt(CXXFor->getRangeStmt());
- CGF.EmitStmt(CXXFor->getEndStmt());
- Body = CXXFor->getBody();
- }
- }
- if (const auto *PreInits = cast_or_null<DeclStmt>(S.getPreInits())) {
+ if (PreInits) {
for (const auto *I : PreInits->decls())
CGF.EmitVarDecl(cast<VarDecl>(*I));
}
@@ -184,7 +189,7 @@
}
public:
- OMPLoopScope(CodeGenFunction &CGF, const OMPLoopDirective &S)
+ OMPLoopScope(CodeGenFunction &CGF, const OMPLoopBasedDirective &S)
: CodeGenFunction::RunCleanupsScope(CGF) {
emitPreInitStmt(CGF, S);
}
@@ -238,11 +243,22 @@
if (const Expr *E = TG->getReductionRef())
CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()));
}
+ // Temp copy arrays for inscan reductions should not be emitted as they are
+ // not used in simd only mode.
+ llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
+ for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
+ if (C->getModifier() != OMPC_REDUCTION_inscan)
+ continue;
+ for (const Expr *E : C->copy_array_temps())
+ CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
+ }
const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
while (CS) {
for (auto &C : CS->captures()) {
if (C.capturesVariable() || C.capturesVariableByCopy()) {
auto *VD = C.getCapturedVar();
+ if (CopyArrayTemps.contains(VD))
+ continue;
assert(VD == VD->getCanonicalDecl() &&
"Canonical decl must be captured.");
DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
@@ -501,6 +517,10 @@
F->setDoesNotThrow();
F->setDoesNotRecurse();
+ // Always inline the outlined function if optimizations are enabled.
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0)
+ F->addFnAttr(llvm::Attribute::AlwaysInline);
+
// Generate the function.
CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs,
FO.UIntPtrCastRequired ? FO.Loc : FO.S->getBeginLoc(),
@@ -631,6 +651,7 @@
emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes,
WrapperCGF.CXXThisValue, WrapperFO);
llvm::SmallVector<llvm::Value *, 4> CallArgs;
+ auto *PI = F->arg_begin();
for (const auto *Arg : Args) {
llvm::Value *CallArg;
auto I = LocalAddrs.find(Arg);
@@ -639,6 +660,11 @@
I->second.second,
I->second.first ? I->second.first->getType() : Arg->getType(),
AlignmentSource::Decl);
+ if (LV.getType()->isAnyComplexType())
+ LV.setAddress(WrapperCGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ LV.getAddress(WrapperCGF),
+ PI->getType()->getPointerTo(
+ LV.getAddress(WrapperCGF).getAddressSpace())));
CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
} else {
auto EI = VLASizes.find(Arg);
@@ -652,6 +678,7 @@
}
}
CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType()));
+ ++PI;
}
CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
WrapperCGF.FinishFunction();
@@ -675,7 +702,8 @@
llvm::Value *SrcBegin = SrcAddr.getPointer();
llvm::Value *DestBegin = DestAddr.getPointer();
// Cast from pointer to array type to pointer to single element.
- llvm::Value *DestEnd = Builder.CreateGEP(DestBegin, NumElements);
+ llvm::Value *DestEnd =
+ Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements);
// The basic structure here is a while-do loop.
llvm::BasicBlock *BodyBB = createBasicBlock("omp.arraycpy.body");
llvm::BasicBlock *DoneBB = createBasicBlock("omp.arraycpy.done");
@@ -708,9 +736,11 @@
// Shift the address forward by one element.
llvm::Value *DestElementNext = Builder.CreateConstGEP1_32(
- DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
+ DestAddr.getElementType(), DestElementPHI, /*Idx0=*/1,
+ "omp.arraycpy.dest.element");
llvm::Value *SrcElementNext = Builder.CreateConstGEP1_32(
- SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
+ SrcAddr.getElementType(), SrcElementPHI, /*Idx0=*/1,
+ "omp.arraycpy.src.element");
// Check whether we've reached the end.
llvm::Value *Done =
Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
@@ -803,8 +833,7 @@
if (DeviceConstTarget && OrigVD->getType().isConstant(getContext()) &&
FD && FD->getType()->isReferenceType() &&
(!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) {
- (void)CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(*this,
- OrigVD);
+ EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
++IRef;
++InitsRef;
continue;
@@ -985,12 +1014,14 @@
// need to copy data.
CopyBegin = createBasicBlock("copyin.not.master");
CopyEnd = createBasicBlock("copyin.not.master.end");
+ // TODO: Avoid ptrtoint conversion.
+ auto *MasterAddrInt =
+ Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy);
+ auto *PrivateAddrInt =
+ Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy);
Builder.CreateCondBr(
- Builder.CreateICmpNE(
- Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy),
- Builder.CreatePtrToInt(PrivateAddr.getPointer(),
- CGM.IntPtrTy)),
- CopyBegin, CopyEnd);
+ Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
+ CopyEnd);
EmitBlock(CopyBegin);
}
const auto *SrcVD =
@@ -1755,6 +1786,31 @@
checkForLastprivateConditionalUpdate(*this, S);
}
+namespace {
+/// RAII to handle scopes for loop transformation directives.
+class OMPTransformDirectiveScopeRAII {
+ OMPLoopScope *Scope = nullptr;
+ CodeGenFunction::CGCapturedStmtInfo *CGSI = nullptr;
+ CodeGenFunction::CGCapturedStmtRAII *CapInfoRAII = nullptr;
+
+public:
+ OMPTransformDirectiveScopeRAII(CodeGenFunction &CGF, const Stmt *S) {
+ if (const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
+ Scope = new OMPLoopScope(CGF, *Dir);
+ CGSI = new CodeGenFunction::CGCapturedStmtInfo(CR_OpenMP);
+ CapInfoRAII = new CodeGenFunction::CGCapturedStmtRAII(CGF, CGSI);
+ }
+ }
+ ~OMPTransformDirectiveScopeRAII() {
+ if (!Scope)
+ return;
+ delete CapInfoRAII;
+ delete CGSI;
+ delete Scope;
+ }
+};
+} // namespace
+
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop,
int MaxLevel, int Level = 0) {
assert(Level < MaxLevel && "Too deep lookup during loop body codegen.");
@@ -1771,6 +1827,12 @@
return;
}
if (SimplifiedS == NextLoop) {
+ if (auto *Dir = dyn_cast<OMPTileDirective>(SimplifiedS))
+ SimplifiedS = Dir->getTransformedStmt();
+ if (auto *Dir = dyn_cast<OMPUnrollDirective>(SimplifiedS))
+ SimplifiedS = Dir->getTransformedStmt();
+ if (const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
+ SimplifiedS = CanonLoop->getLoopStmt();
if (const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
S = For->getBody();
} else {
@@ -1845,9 +1907,9 @@
D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
// Emit loop body.
emitBody(*this, Body,
- OMPLoopDirective::tryToFindNextInnerLoop(
+ OMPLoopBasedDirective::tryToFindNextInnerLoop(
Body, /*TryImperfectlyNestedLoops=*/true),
- D.getCollapsedNumber());
+ D.getLoopsNumber());
// Jump to the dispatcher at the end of the loop body.
if (IsInscanRegion)
@@ -1858,6 +1920,121 @@
BreakContinueStack.pop_back();
}
+using EmittedClosureTy = std::pair<llvm::Function *, llvm::Value *>;
+
+/// Emit a captured statement and return the function as well as its captured
+/// closure context.
+static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF,
+ const CapturedStmt *S) {
+ LValue CapStruct = ParentCGF.InitCapturedStruct(*S);
+ CodeGenFunction CGF(ParentCGF.CGM, /*suppressNewContext=*/true);
+ std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
+ std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, CSI.get());
+ llvm::Function *F = CGF.GenerateCapturedStmtFunction(*S);
+
+ return {F, CapStruct.getPointer(ParentCGF)};
+}
+
+/// Emit a call to a previously captured closure.
+static llvm::CallInst *
+emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap,
+ llvm::ArrayRef<llvm::Value *> Args) {
+ // Append the closure context to the argument.
+ SmallVector<llvm::Value *> EffectiveArgs;
+ EffectiveArgs.reserve(Args.size() + 1);
+ llvm::append_range(EffectiveArgs, Args);
+ EffectiveArgs.push_back(Cap.second);
+
+ return ParentCGF.Builder.CreateCall(Cap.first, EffectiveArgs);
+}
+
+llvm::CanonicalLoopInfo *
+CodeGenFunction::EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth) {
+ assert(Depth == 1 && "Nested loops with OpenMPIRBuilder not yet implemented");
+
+ EmitStmt(S);
+ assert(OMPLoopNestStack.size() >= (size_t)Depth && "Found too few loops");
+
+ // The last added loop is the outermost one.
+ return OMPLoopNestStack.back();
+}
+
+void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) {
+ const Stmt *SyntacticalLoop = S->getLoopStmt();
+ if (!getLangOpts().OpenMPIRBuilder) {
+ // Ignore if OpenMPIRBuilder is not enabled.
+ EmitStmt(SyntacticalLoop);
+ return;
+ }
+
+ LexicalScope ForScope(*this, S->getSourceRange());
+
+ // Emit init statements. The Distance/LoopVar funcs may reference variable
+ // declarations they contain.
+ const Stmt *BodyStmt;
+ if (const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
+ if (const Stmt *InitStmt = For->getInit())
+ EmitStmt(InitStmt);
+ BodyStmt = For->getBody();
+ } else if (const auto *RangeFor =
+ dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
+ if (const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
+ EmitStmt(RangeStmt);
+ if (const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
+ EmitStmt(BeginStmt);
+ if (const DeclStmt *EndStmt = RangeFor->getEndStmt())
+ EmitStmt(EndStmt);
+ if (const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
+ EmitStmt(LoopVarStmt);
+ BodyStmt = RangeFor->getBody();
+ } else
+ llvm_unreachable("Expected for-stmt or range-based for-stmt");
+
+ // Emit closure for later use. By-value captures will be captured here.
+ const CapturedStmt *DistanceFunc = S->getDistanceFunc();
+ EmittedClosureTy DistanceClosure = emitCapturedStmtFunc(*this, DistanceFunc);
+ const CapturedStmt *LoopVarFunc = S->getLoopVarFunc();
+ EmittedClosureTy LoopVarClosure = emitCapturedStmtFunc(*this, LoopVarFunc);
+
+ // Call the distance function to get the number of iterations of the loop to
+ // come.
+ QualType LogicalTy = DistanceFunc->getCapturedDecl()
+ ->getParam(0)
+ ->getType()
+ .getNonReferenceType();
+ Address CountAddr = CreateMemTemp(LogicalTy, ".count.addr");
+ emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()});
+ llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count");
+
+ // Emit the loop structure.
+ llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
+ auto BodyGen = [&, this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
+ llvm::Value *IndVar) {
+ Builder.restoreIP(CodeGenIP);
+
+ // Emit the loop body: Convert the logical iteration number to the loop
+ // variable and emit the body.
+ const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
+ LValue LCVal = EmitLValue(LoopVarRef);
+ Address LoopVarAddress = LCVal.getAddress(*this);
+ emitCapturedStmtCall(*this, LoopVarClosure,
+ {LoopVarAddress.getPointer(), IndVar});
+
+ RunCleanupsScope BodyScope(*this);
+ EmitStmt(BodyStmt);
+ };
+ llvm::CanonicalLoopInfo *CL =
+ OMPBuilder.createCanonicalLoop(Builder, BodyGen, DistVal);
+
+ // Finish up the loop.
+ Builder.restoreIP(CL->getAfterIP());
+ ForScope.ForceCleanup();
+
+ // Remember the CanonicalLoopInfo for parent AST nodes consuming it.
+ OMPLoopNestStack.push_back(CL);
+}
+
void CodeGenFunction::EmitOMPInnerLoop(
const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond,
const Expr *IncExpr,
@@ -1875,6 +2052,7 @@
const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
const Stmt *SS = ICS->getCapturedStmt();
const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(SS);
+ OMPLoopNestStack.clear();
if (AS)
LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(),
AS->getAttrs(), SourceLocToDebugLoc(R.getBegin()),
@@ -2062,8 +2240,7 @@
for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
if (!C->getNumForLoops())
continue;
- for (unsigned I = S.getCollapsedNumber(),
- E = C->getLoopNumIterations().size();
+ for (unsigned I = S.getLoopsNumber(), E = C->getLoopNumIterations().size();
I < E; ++I) {
const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I));
const auto *VD = cast<VarDecl>(DRE->getDecl());
@@ -2152,8 +2329,7 @@
}
static void emitSimdlenSafelenClause(CodeGenFunction &CGF,
- const OMPExecutableDirective &D,
- bool IsMonotonic) {
+ const OMPExecutableDirective &D) {
if (!CGF.HaveInsertPoint())
return;
if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
@@ -2164,8 +2340,7 @@
// In presence of finite 'safelen', it may be unsafe to mark all
// the memory instructions parallel, because loop-carried
// dependences of 'safelen' iterations are possible.
- if (!IsMonotonic)
- CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
+ CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
} else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
/*ignoreResult=*/true);
@@ -2178,12 +2353,11 @@
}
}
-void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D,
- bool IsMonotonic) {
+void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D) {
// Walk clauses and process safelen/lastprivate.
- LoopStack.setParallel(!IsMonotonic);
+ LoopStack.setParallel(/*Enable=*/true);
LoopStack.setVectorizeEnable();
- emitSimdlenSafelenClause(*this, D, IsMonotonic);
+ emitSimdlenSafelenClause(*this, D);
if (const auto *C = D.getSingleClause<OMPOrderClause>())
if (C->getKind() == OMPC_ORDER_concurrent)
LoopStack.setParallel(/*Enable=*/true);
@@ -2406,6 +2580,34 @@
checkForLastprivateConditionalUpdate(*this, S);
}
+void CodeGenFunction::EmitOMPTileDirective(const OMPTileDirective &S) {
+ // Emit the de-sugared statement.
+ OMPTransformDirectiveScopeRAII TileScope(*this, &S);
+ EmitStmt(S.getTransformedStmt());
+}
+
+void CodeGenFunction::EmitOMPUnrollDirective(const OMPUnrollDirective &S) {
+ // This function is only called if the unrolled loop is not consumed by any
+ // other loop-associated construct. Such a loop-associated construct will have
+ // used the transformed AST.
+
+ // Set the unroll metadata for the next emitted loop.
+ LoopStack.setUnrollState(LoopAttributes::Enable);
+
+ if (S.hasClausesOfKind<OMPFullClause>()) {
+ LoopStack.setUnrollState(LoopAttributes::Full);
+ } else if (auto *PartialClause = S.getSingleClause<OMPPartialClause>()) {
+ if (Expr *FactorExpr = PartialClause->getFactor()) {
+ uint64_t Factor =
+ FactorExpr->EvaluateKnownConstInt(getContext()).getZExtValue();
+ assert(Factor >= 1 && "Only positive factors are valid");
+ LoopStack.setUnrollCount(Factor);
+ }
+ }
+
+ EmitStmt(S.getAssociatedStmt());
+}
+
void CodeGenFunction::EmitOMPOuterLoop(
bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S,
CodeGenFunction::OMPPrivateScope &LoopScope,
@@ -2424,6 +2626,7 @@
llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond");
EmitBlock(CondBlock);
const SourceRange R = S.getSourceRange();
+ OMPLoopNestStack.clear();
LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
SourceLocToDebugLoc(R.getEnd()));
@@ -2477,7 +2680,7 @@
if (C->getKind() == OMPC_ORDER_concurrent)
CGF.LoopStack.setParallel(/*Enable=*/true);
} else {
- CGF.EmitOMPSimdInit(S, IsMonotonic);
+ CGF.EmitOMPSimdInit(S);
}
},
[&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
@@ -2507,6 +2710,7 @@
}
EmitBranch(CondBlock);
+ OMPLoopNestStack.clear();
LoopStack.pop();
// Emit the fall-through block.
EmitBlock(LoopExit.getBlock());
@@ -2986,8 +3190,7 @@
isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
bool IsMonotonic =
Ordered ||
- ((ScheduleKind.Schedule == OMPC_SCHEDULE_static ||
- ScheduleKind.Schedule == OMPC_SCHEDULE_unknown) &&
+ (ScheduleKind.Schedule == OMPC_SCHEDULE_static &&
!(ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
@@ -3000,9 +3203,9 @@
getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
emitCommonSimdLoop(
*this, S,
- [&S, IsMonotonic](CodeGenFunction &CGF, PrePostActionTy &) {
+ [&S](CodeGenFunction &CGF, PrePostActionTy &) {
if (isOpenMPSimdDirective(S.getDirectiveKind())) {
- CGF.EmitOMPSimdInit(S, IsMonotonic);
+ CGF.EmitOMPSimdInit(S);
} else if (const auto *C = S.getSingleClause<OMPOrderClause>()) {
if (C->getKind() == OMPC_ORDER_concurrent)
CGF.LoopStack.setParallel(/*Enable=*/true);
@@ -3131,53 +3334,30 @@
return {LBVal, UBVal};
}
-/// Emits the code for the directive with inscan reductions.
+/// Emits internal temp array declarations for the directive with inscan
+/// reductions.
/// The code is the following:
/// \code
/// size num_iters = <num_iters>;
/// <type> buffer[num_iters];
-/// #pragma omp ...
-/// for (i: 0..<num_iters>) {
-/// <input phase>;
-/// buffer[i] = red;
-/// }
-/// for (int k = 0; k != ceil(log2(num_iters)); ++k)
-/// for (size cnt = last_iter; cnt >= pow(2, k); --k)
-/// buffer[i] op= buffer[i-pow(2,k)];
-/// #pragma omp ...
-/// for (0..<num_iters>) {
-/// red = InclusiveScan ? buffer[i] : buffer[i-1];
-/// <scan phase>;
-/// }
/// \endcode
-static void emitScanBasedDirective(
+static void emitScanBasedDirectiveDecls(
CodeGenFunction &CGF, const OMPLoopDirective &S,
- llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen,
- llvm::function_ref<void(CodeGenFunction &)> FirstGen,
- llvm::function_ref<void(CodeGenFunction &)> SecondGen) {
+ llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen) {
llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast(
NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false);
SmallVector<const Expr *, 4> Shareds;
SmallVector<const Expr *, 4> Privates;
SmallVector<const Expr *, 4> ReductionOps;
- SmallVector<const Expr *, 4> LHSs;
- SmallVector<const Expr *, 4> RHSs;
- SmallVector<const Expr *, 4> CopyOps;
SmallVector<const Expr *, 4> CopyArrayTemps;
- SmallVector<const Expr *, 4> CopyArrayElems;
for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
assert(C->getModifier() == OMPC_REDUCTION_inscan &&
"Only inscan reductions are expected.");
Shareds.append(C->varlist_begin(), C->varlist_end());
Privates.append(C->privates().begin(), C->privates().end());
ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
- LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
- RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
- CopyOps.append(C->copy_ops().begin(), C->copy_ops().end());
CopyArrayTemps.append(C->copy_array_temps().begin(),
C->copy_array_temps().end());
- CopyArrayElems.append(C->copy_array_elems().begin(),
- C->copy_array_elems().end());
}
{
// Emit buffers for each reduction variables.
@@ -3206,6 +3386,49 @@
++Count;
}
}
+}
+
+/// Emits the code for the directive with inscan reductions.
+/// The code is the following:
+/// \code
+/// #pragma omp ...
+/// for (i: 0..<num_iters>) {
+/// <input phase>;
+/// buffer[i] = red;
+/// }
+/// #pragma omp master // in parallel region
+/// for (int k = 0; k != ceil(log2(num_iters)); ++k)
+/// for (size cnt = last_iter; cnt >= pow(2, k); --k)
+/// buffer[i] op= buffer[i-pow(2,k)];
+/// #pragma omp barrier // in parallel region
+/// #pragma omp ...
+/// for (0..<num_iters>) {
+/// red = InclusiveScan ? buffer[i] : buffer[i-1];
+/// <scan phase>;
+/// }
+/// \endcode
+static void emitScanBasedDirective(
+ CodeGenFunction &CGF, const OMPLoopDirective &S,
+ llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen,
+ llvm::function_ref<void(CodeGenFunction &)> FirstGen,
+ llvm::function_ref<void(CodeGenFunction &)> SecondGen) {
+ llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast(
+ NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false);
+ SmallVector<const Expr *, 4> Privates;
+ SmallVector<const Expr *, 4> ReductionOps;
+ SmallVector<const Expr *, 4> LHSs;
+ SmallVector<const Expr *, 4> RHSs;
+ SmallVector<const Expr *, 4> CopyArrayElems;
+ for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
+ assert(C->getModifier() == OMPC_REDUCTION_inscan &&
+ "Only inscan reductions are expected.");
+ Privates.append(C->privates().begin(), C->privates().end());
+ ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
+ LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
+ RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
+ CopyArrayElems.append(C->copy_array_elems().begin(),
+ C->copy_array_elems().end());
+ }
CodeGenFunction::ParentLoopDirectiveForScanRegion ScanRegion(CGF, S);
{
// Emit loop with input phase:
@@ -3218,90 +3441,108 @@
CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
FirstGen(CGF);
}
- // Emit prefix reduction:
- // for (int k = 0; k <= ceil(log2(n)); ++k)
- llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
- llvm::BasicBlock *LoopBB = CGF.createBasicBlock("omp.outer.log.scan.body");
- llvm::BasicBlock *ExitBB = CGF.createBasicBlock("omp.outer.log.scan.exit");
- llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
- llvm::Value *Arg =
- CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
- llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
- F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
- LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
- LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
- llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
- OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
- auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getBeginLoc());
- CGF.EmitBlock(LoopBB);
- auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
- // size pow2k = 1;
- auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
- Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
- Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
- // for (size i = n - 1; i >= 2 ^ k; --i)
- // tmp[i] op= tmp[i-pow2k];
- llvm::BasicBlock *InnerLoopBB =
- CGF.createBasicBlock("omp.inner.log.scan.body");
- llvm::BasicBlock *InnerExitBB =
- CGF.createBasicBlock("omp.inner.log.scan.exit");
- llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
- CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
- CGF.EmitBlock(InnerLoopBB);
- auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
- IVal->addIncoming(NMin1, LoopBB);
- {
- CodeGenFunction::OMPPrivateScope PrivScope(CGF);
- auto *ILHS = LHSs.begin();
- auto *IRHS = RHSs.begin();
- for (const Expr *CopyArrayElem : CopyArrayElems) {
- const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
- const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
- Address LHSAddr = Address::invalid();
- {
- CodeGenFunction::OpaqueValueMapping IdxMapping(
- CGF,
- cast<OpaqueValueExpr>(
- cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
- RValue::get(IVal));
- LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(CGF);
+ // #pragma omp barrier // in parallel region
+ auto &&CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
+ &ReductionOps,
+ &Privates](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ // Emit prefix reduction:
+ // #pragma omp master // in parallel region
+ // for (int k = 0; k <= ceil(log2(n)); ++k)
+ llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
+ llvm::BasicBlock *LoopBB = CGF.createBasicBlock("omp.outer.log.scan.body");
+ llvm::BasicBlock *ExitBB = CGF.createBasicBlock("omp.outer.log.scan.exit");
+ llvm::Function *F =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
+ llvm::Value *Arg =
+ CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
+ llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
+ F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
+ LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
+ LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
+ llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
+ OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
+ auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getBeginLoc());
+ CGF.EmitBlock(LoopBB);
+ auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
+ // size pow2k = 1;
+ auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
+ Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
+ Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
+ // for (size i = n - 1; i >= 2 ^ k; --i)
+ // tmp[i] op= tmp[i-pow2k];
+ llvm::BasicBlock *InnerLoopBB =
+ CGF.createBasicBlock("omp.inner.log.scan.body");
+ llvm::BasicBlock *InnerExitBB =
+ CGF.createBasicBlock("omp.inner.log.scan.exit");
+ llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
+ CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
+ CGF.EmitBlock(InnerLoopBB);
+ auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
+ IVal->addIncoming(NMin1, LoopBB);
+ {
+ CodeGenFunction::OMPPrivateScope PrivScope(CGF);
+ auto *ILHS = LHSs.begin();
+ auto *IRHS = RHSs.begin();
+ for (const Expr *CopyArrayElem : CopyArrayElems) {
+ const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
+ const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
+ Address LHSAddr = Address::invalid();
+ {
+ CodeGenFunction::OpaqueValueMapping IdxMapping(
+ CGF,
+ cast<OpaqueValueExpr>(
+ cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
+ RValue::get(IVal));
+ LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(CGF);
+ }
+ PrivScope.addPrivate(LHSVD, [LHSAddr]() { return LHSAddr; });
+ Address RHSAddr = Address::invalid();
+ {
+ llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
+ CodeGenFunction::OpaqueValueMapping IdxMapping(
+ CGF,
+ cast<OpaqueValueExpr>(
+ cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
+ RValue::get(OffsetIVal));
+ RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(CGF);
+ }
+ PrivScope.addPrivate(RHSVD, [RHSAddr]() { return RHSAddr; });
+ ++ILHS;
+ ++IRHS;
}
- PrivScope.addPrivate(LHSVD, [LHSAddr]() { return LHSAddr; });
- Address RHSAddr = Address::invalid();
- {
- llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
- CodeGenFunction::OpaqueValueMapping IdxMapping(
- CGF,
- cast<OpaqueValueExpr>(
- cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
- RValue::get(OffsetIVal));
- RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(CGF);
- }
- PrivScope.addPrivate(RHSVD, [RHSAddr]() { return RHSAddr; });
- ++ILHS;
- ++IRHS;
+ PrivScope.Privatize();
+ CGF.CGM.getOpenMPRuntime().emitReduction(
+ CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
+ {/*WithNowait=*/true, /*SimpleReduction=*/true, OMPD_unknown});
}
- PrivScope.Privatize();
- CGF.CGM.getOpenMPRuntime().emitReduction(
- CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
- {/*WithNowait=*/true, /*SimpleReduction=*/true, OMPD_unknown});
+ llvm::Value *NextIVal =
+ CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
+ IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
+ CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
+ CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
+ CGF.EmitBlock(InnerExitBB);
+ llvm::Value *Next =
+ CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
+ Counter->addIncoming(Next, CGF.Builder.GetInsertBlock());
+ // pow2k <<= 1;
+ llvm::Value *NextPow2K =
+ CGF.Builder.CreateShl(Pow2K, 1, "", /*HasNUW=*/true);
+ Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
+ llvm::Value *Cmp = CGF.Builder.CreateICmpNE(Next, LogVal);
+ CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
+ auto DL1 = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getEndLoc());
+ CGF.EmitBlock(ExitBB);
+ };
+ if (isOpenMPParallelDirective(S.getDirectiveKind())) {
+ CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
+ CGF.CGM.getOpenMPRuntime().emitBarrierCall(
+ CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
+ /*ForceSimpleCall=*/true);
+ } else {
+ RegionCodeGenTy RCG(CodeGen);
+ RCG(CGF);
}
- llvm::Value *NextIVal =
- CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
- IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
- CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
- CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
- CGF.EmitBlock(InnerExitBB);
- llvm::Value *Next =
- CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
- Counter->addIncoming(Next, CGF.Builder.GetInsertBlock());
- // pow2k <<= 1;
- llvm::Value *NextPow2K = CGF.Builder.CreateShl(Pow2K, 1, "", /*HasNUW=*/true);
- Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
- llvm::Value *Cmp = CGF.Builder.CreateICmpNE(Next, LogVal);
- CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
- auto DL1 = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getEndLoc());
- CGF.EmitBlock(ExitBB);
CGF.OMPFirstScanLoop = false;
SecondGen(CGF);
@@ -3338,6 +3579,8 @@
emitForLoopBounds,
emitDispatchForLoopBounds);
};
+ if (!isOpenMPParallelDirective(S.getDirectiveKind()))
+ emitScanBasedDirectiveDecls(CGF, S, NumIteratorsGen);
emitScanBasedDirective(CGF, S, NumIteratorsGen, FirstGen, SecondGen);
} else {
CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, S.getDirectiveKind(),
@@ -3349,10 +3592,38 @@
return HasLastprivates;
}
+static bool isSupportedByOpenMPIRBuilder(const OMPForDirective &S) {
+ if (S.hasCancel())
+ return false;
+ for (OMPClause *C : S.clauses())
+ if (!isa<OMPNowaitClause>(C))
+ return false;
+
+ return true;
+}
+
void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
bool HasLastprivates = false;
- auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
- PrePostActionTy &) {
+ bool UseOMPIRBuilder =
+ CGM.getLangOpts().OpenMPIRBuilder && isSupportedByOpenMPIRBuilder(S);
+ auto &&CodeGen = [this, &S, &HasLastprivates,
+ UseOMPIRBuilder](CodeGenFunction &CGF, PrePostActionTy &) {
+ // Use the OpenMPIRBuilder if enabled.
+ if (UseOMPIRBuilder) {
+ // Emit the associated statement and get its loop representation.
+ const Stmt *Inner = S.getRawStmt();
+ llvm::CanonicalLoopInfo *CLI =
+ EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
+
+ bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
+ llvm::OpenMPIRBuilder &OMPBuilder =
+ CGM.getOpenMPRuntime().getOMPBuilder();
+ llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
+ AllocaInsertPt->getParent(), AllocaInsertPt->getIterator());
+ OMPBuilder.createWorkshareLoop(Builder, CLI, AllocaIP, NeedsBarrier);
+ return;
+ }
+
HasLastprivates = emitWorksharingDirective(CGF, S, S.hasCancel());
};
{
@@ -3363,9 +3634,11 @@
S.hasCancel());
}
- // Emit an implicit barrier at the end.
- if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
- CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
+ if (!UseOMPIRBuilder) {
+ // Emit an implicit barrier at the end.
+ if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
+ CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
+ }
// Check for outer lastprivate conditional update.
checkForLastprivateConditionalUpdate(*this, S);
}
@@ -3428,11 +3701,11 @@
CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
// Generate condition for loop.
BinaryOperator *Cond = BinaryOperator::Create(
- C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, OK_Ordinary,
+ C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_PRValue, OK_Ordinary,
S.getBeginLoc(), FPOptionsOverride());
// Increment for loop counter.
UnaryOperator *Inc = UnaryOperator::Create(
- C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
+ C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_PRValue, OK_Ordinary,
S.getBeginLoc(), true, FPOptionsOverride());
auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
// Iterate through all sections and emit a switch construct:
@@ -3546,6 +3819,64 @@
}
void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
+ if (CGM.getLangOpts().OpenMPIRBuilder) {
+ llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
+ using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+ using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
+
+ auto FiniCB = [this](InsertPointTy IP) {
+ OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
+ };
+
+ const CapturedStmt *ICS = S.getInnermostCapturedStmt();
+ const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
+ const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
+ llvm::SmallVector<BodyGenCallbackTy, 4> SectionCBVector;
+ if (CS) {
+ for (const Stmt *SubStmt : CS->children()) {
+ auto SectionCB = [this, SubStmt](InsertPointTy AllocaIP,
+ InsertPointTy CodeGenIP,
+ llvm::BasicBlock &FiniBB) {
+ OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP,
+ FiniBB);
+ OMPBuilderCBHelpers::EmitOMPRegionBody(*this, SubStmt, CodeGenIP,
+ FiniBB);
+ };
+ SectionCBVector.push_back(SectionCB);
+ }
+ } else {
+ auto SectionCB = [this, CapturedStmt](InsertPointTy AllocaIP,
+ InsertPointTy CodeGenIP,
+ llvm::BasicBlock &FiniBB) {
+ OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB);
+ OMPBuilderCBHelpers::EmitOMPRegionBody(*this, CapturedStmt, CodeGenIP,
+ FiniBB);
+ };
+ SectionCBVector.push_back(SectionCB);
+ }
+
+ // Privatization callback that performs appropriate action for
+ // shared/private/firstprivate/lastprivate/copyin/... variables.
+ //
+ // TODO: This defaults to shared right now.
+ auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
+ llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
+ // The next line is appropriate only for variables (Val) with the
+ // data-sharing attribute "shared".
+ ReplVal = &Val;
+
+ return CodeGenIP;
+ };
+
+ CGCapturedStmtInfo CGSI(*ICS, CR_OpenMP);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
+ llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
+ AllocaInsertPt->getParent(), AllocaInsertPt->getIterator());
+ Builder.restoreIP(OMPBuilder.createSections(
+ Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
+ S.getSingleClause<OMPNowaitClause>()));
+ return;
+ }
{
auto LPCRegion =
CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
@@ -3562,6 +3893,29 @@
}
void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
+ if (CGM.getLangOpts().OpenMPIRBuilder) {
+ llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
+ using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+
+ const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
+ auto FiniCB = [this](InsertPointTy IP) {
+ OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
+ };
+
+ auto BodyGenCB = [SectionRegionBodyStmt, this](InsertPointTy AllocaIP,
+ InsertPointTy CodeGenIP,
+ llvm::BasicBlock &FiniBB) {
+ OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB);
+ OMPBuilderCBHelpers::EmitOMPRegionBody(*this, SectionRegionBodyStmt,
+ CodeGenIP, FiniBB);
+ };
+
+ LexicalScope Scope(*this, S.getSourceRange());
+ EmitStopPoint(&S);
+ Builder.restoreIP(OMPBuilder.createSection(Builder, BodyGenCB, FiniCB));
+
+ return;
+ }
LexicalScope Scope(*this, S.getSourceRange());
EmitStopPoint(&S);
EmitStmt(S.getAssociatedStmt());
@@ -3650,6 +4004,55 @@
emitMaster(*this, S);
}
+static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
+ auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ CGF.EmitStmt(S.getRawStmt());
+ };
+ Expr *Filter = nullptr;
+ if (const auto *FilterClause = S.getSingleClause<OMPFilterClause>())
+ Filter = FilterClause->getThreadID();
+ CGF.CGM.getOpenMPRuntime().emitMaskedRegion(CGF, CodeGen, S.getBeginLoc(),
+ Filter);
+}
+
+void CodeGenFunction::EmitOMPMaskedDirective(const OMPMaskedDirective &S) {
+ if (CGM.getLangOpts().OpenMPIRBuilder) {
+ llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
+ using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+
+ const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
+ const Expr *Filter = nullptr;
+ if (const auto *FilterClause = S.getSingleClause<OMPFilterClause>())
+ Filter = FilterClause->getThreadID();
+ llvm::Value *FilterVal = Filter
+ ? EmitScalarExpr(Filter, CGM.Int32Ty)
+ : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0);
+
+ auto FiniCB = [this](InsertPointTy IP) {
+ OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
+ };
+
+ auto BodyGenCB = [MaskedRegionBodyStmt, this](InsertPointTy AllocaIP,
+ InsertPointTy CodeGenIP,
+ llvm::BasicBlock &FiniBB) {
+ OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB);
+ OMPBuilderCBHelpers::EmitOMPRegionBody(*this, MaskedRegionBodyStmt,
+ CodeGenIP, FiniBB);
+ };
+
+ LexicalScope Scope(*this, S.getSourceRange());
+ EmitStopPoint(&S);
+ Builder.restoreIP(
+ OMPBuilder.createMasked(Builder, BodyGenCB, FiniCB, FilterVal));
+
+ return;
+ }
+ LexicalScope Scope(*this, S.getSourceRange());
+ EmitStopPoint(&S);
+ emitMasked(*this, S);
+}
+
void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
if (CGM.getLangOpts().OpenMPIRBuilder) {
llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
@@ -3712,6 +4115,19 @@
(void)emitWorksharingDirective(CGF, S, S.hasCancel());
};
{
+ if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
+ [](const OMPReductionClause *C) {
+ return C->getModifier() == OMPC_REDUCTION_inscan;
+ })) {
+ const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
+ CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
+ CGCapturedStmtInfo CGSI(CR_OpenMP);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
+ OMPLoopScope LoopScope(CGF, S);
+ return CGF.EmitScalarExpr(S.getNumIterations());
+ };
+ emitScanBasedDirectiveDecls(*this, S, NumIteratorsGen);
+ }
auto LPCRegion =
CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
@@ -3730,6 +4146,19 @@
(void)emitWorksharingDirective(CGF, S, /*HasCancel=*/false);
};
{
+ if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
+ [](const OMPReductionClause *C) {
+ return C->getModifier() == OMPC_REDUCTION_inscan;
+ })) {
+ const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
+ CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
+ CGCapturedStmtInfo CGSI(CR_OpenMP);
+ CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
+ OMPLoopScope LoopScope(CGF, S);
+ return CGF.EmitScalarExpr(S.getNumIterations());
+ };
+ emitScanBasedDirectiveDecls(*this, S, NumIteratorsGen);
+ }
auto LPCRegion =
CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
emitCommonOMPParallelDirective(*this, S, OMPD_for_simd, CodeGen,
@@ -3892,7 +4321,7 @@
}
}
// Get list of lastprivate variables (for taskloops).
- llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
+ llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
auto IRef = C->varlist_begin();
auto ID = C->destination_exprs().begin();
@@ -3903,8 +4332,8 @@
Data.LastprivateCopies.push_back(IInit);
}
LastprivateDstsOrigs.insert(
- {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
- cast<DeclRefExpr>(*IRef)});
+ std::make_pair(cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
+ cast<DeclRefExpr>(*IRef)));
++IRef;
++ID;
}
@@ -3938,15 +4367,14 @@
auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
CapturedRegion](CodeGenFunction &CGF,
PrePostActionTy &Action) {
- llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, std::pair<Address, Address>>
+ llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
+ std::pair<Address, Address>>
UntiedLocalVars;
// Set proper addresses for generated private copies.
OMPPrivateScope Scope(CGF);
llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> FirstprivatePtrs;
if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
!Data.LastprivateVars.empty() || !Data.PrivateLocals.empty()) {
- llvm::FunctionType *CopyFnTy = llvm::FunctionType::get(
- CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true);
enum { PrivatesParam = 2, CopyFnParam = 3 };
llvm::Value *CopyFn = CGF.Builder.CreateLoad(
CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
@@ -3955,13 +4383,16 @@
// Map privates.
llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
llvm::SmallVector<llvm::Value *, 16> CallArgs;
+ llvm::SmallVector<llvm::Type *, 4> ParamTypes;
CallArgs.push_back(PrivatesPtr);
+ ParamTypes.push_back(PrivatesPtr->getType());
for (const Expr *E : Data.PrivateVars) {
const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Address PrivatePtr = CGF.CreateMemTemp(
CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr");
PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
+ ParamTypes.push_back(PrivatePtr.getType());
}
for (const Expr *E : Data.FirstprivateVars) {
const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
@@ -3971,6 +4402,7 @@
PrivatePtrs.emplace_back(VD, PrivatePtr);
FirstprivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
+ ParamTypes.push_back(PrivatePtr.getType());
}
for (const Expr *E : Data.LastprivateVars) {
const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
@@ -3979,6 +4411,7 @@
".lastpriv.ptr.addr");
PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
+ ParamTypes.push_back(PrivatePtr.getType());
}
for (const VarDecl *VD : Data.PrivateLocals) {
QualType Ty = VD->getType().getNonReferenceType();
@@ -3988,9 +4421,19 @@
Ty = CGF.getContext().getPointerType(Ty);
Address PrivatePtr = CGF.CreateMemTemp(
CGF.getContext().getPointerType(Ty), ".local.ptr.addr");
- UntiedLocalVars.try_emplace(VD, PrivatePtr, Address::invalid());
+ auto Result = UntiedLocalVars.insert(
+ std::make_pair(VD, std::make_pair(PrivatePtr, Address::invalid())));
+ // If key exists update in place.
+ if (Result.second == false)
+ *Result.first = std::make_pair(
+ VD, std::make_pair(PrivatePtr, Address::invalid()));
CallArgs.push_back(PrivatePtr.getPointer());
+ ParamTypes.push_back(PrivatePtr.getType());
}
+ auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
+ ParamTypes, /*isVarArg=*/false);
+ CopyFn = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CopyFn, CopyFnTy->getPointerTo());
CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
for (const auto &Pair : LastprivateDstsOrigs) {
@@ -4015,14 +4458,14 @@
if (isAllocatableDecl(Pair.first)) {
llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
Address Replacement(Ptr, CGF.getPointerAlign());
- Pair.getSecond().first = Replacement;
+ Pair.second.first = Replacement;
Ptr = CGF.Builder.CreateLoad(Replacement);
Replacement = Address(Ptr, CGF.getContext().getDeclAlign(Pair.first));
- Pair.getSecond().second = Replacement;
+ Pair.second.second = Replacement;
} else {
llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
Address Replacement(Ptr, CGF.getContext().getDeclAlign(Pair.first));
- Pair.getSecond().first = Replacement;
+ Pair.second.first = Replacement;
}
}
}
@@ -4156,7 +4599,7 @@
PrivateVD->setInitStyle(VarDecl::CInit);
PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue,
InitRef, /*BasePath=*/nullptr,
- VK_RValue, FPOptionsOverride()));
+ VK_PRValue, FPOptionsOverride()));
Data.FirstprivateVars.emplace_back(OrigRef);
Data.FirstprivateCopies.emplace_back(PrivateRef);
Data.FirstprivateInits.emplace_back(InitRef);
@@ -4238,8 +4681,6 @@
// Set proper addresses for generated private copies.
OMPPrivateScope Scope(CGF);
if (!Data.FirstprivateVars.empty()) {
- llvm::FunctionType *CopyFnTy = llvm::FunctionType::get(
- CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true);
enum { PrivatesParam = 2, CopyFnParam = 3 };
llvm::Value *CopyFn = CGF.Builder.CreateLoad(
CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
@@ -4248,7 +4689,9 @@
// Map privates.
llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
llvm::SmallVector<llvm::Value *, 16> CallArgs;
+ llvm::SmallVector<llvm::Type *, 4> ParamTypes;
CallArgs.push_back(PrivatesPtr);
+ ParamTypes.push_back(PrivatesPtr->getType());
for (const Expr *E : Data.FirstprivateVars) {
const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Address PrivatePtr =
@@ -4256,7 +4699,12 @@
".firstpriv.ptr.addr");
PrivatePtrs.emplace_back(VD, PrivatePtr);
CallArgs.push_back(PrivatePtr.getPointer());
+ ParamTypes.push_back(PrivatePtr.getType());
}
+ auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
+ ParamTypes, /*isVarArg=*/false);
+ CopyFn = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ CopyFn, CopyFnTy->getPointerTo());
CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
for (const auto &Pair : PrivatePtrs) {
@@ -4779,7 +5227,7 @@
*this, S,
[&S](CodeGenFunction &CGF, PrePostActionTy &) {
if (isOpenMPSimdDirective(S.getDirectiveKind()))
- CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true);
+ CGF.EmitOMPSimdInit(S);
},
[&S, &LoopScope, Cond, IncExpr, LoopExit, &CodeGenLoop,
StaticChunked](CodeGenFunction &CGF, PrePostActionTy &) {
@@ -4859,6 +5307,8 @@
CGF.CapturedStmtInfo = &CapStmtInfo;
llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S, Loc);
Fn->setDoesNotRecurse();
+ if (CGM.getCodeGenOpts().OptimizationLevel != 0)
+ Fn->addFnAttr(llvm::Attribute::AlwaysInline);
return Fn;
}
@@ -5281,32 +5731,35 @@
// Emit post-update store to 'v' of old/new 'x' value.
CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc);
CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
- // OpenMP, 2.17.7, atomic Construct
- // If the write, update, or capture clause is specified and the release,
- // acq_rel, or seq_cst clause is specified then the strong flush on entry to
- // the atomic operation is also a release flush.
- // If the read or capture clause is specified and the acquire, acq_rel, or
- // seq_cst clause is specified then the strong flush on exit from the atomic
- // operation is also an acquire flush.
- switch (AO) {
- case llvm::AtomicOrdering::Release:
- CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
- llvm::AtomicOrdering::Release);
- break;
- case llvm::AtomicOrdering::Acquire:
- CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
- llvm::AtomicOrdering::Acquire);
- break;
- case llvm::AtomicOrdering::AcquireRelease:
- case llvm::AtomicOrdering::SequentiallyConsistent:
- CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
- llvm::AtomicOrdering::AcquireRelease);
- break;
- case llvm::AtomicOrdering::Monotonic:
- break;
- case llvm::AtomicOrdering::NotAtomic:
- case llvm::AtomicOrdering::Unordered:
- llvm_unreachable("Unexpected ordering.");
+ // OpenMP 5.1 removes the required flush for capture clause.
+ if (CGF.CGM.getLangOpts().OpenMP < 51) {
+ // OpenMP, 2.17.7, atomic Construct
+ // If the write, update, or capture clause is specified and the release,
+ // acq_rel, or seq_cst clause is specified then the strong flush on entry to
+ // the atomic operation is also a release flush.
+ // If the read or capture clause is specified and the acquire, acq_rel, or
+ // seq_cst clause is specified then the strong flush on exit from the atomic
+ // operation is also an acquire flush.
+ switch (AO) {
+ case llvm::AtomicOrdering::Release:
+ CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
+ llvm::AtomicOrdering::Release);
+ break;
+ case llvm::AtomicOrdering::Acquire:
+ CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
+ llvm::AtomicOrdering::Acquire);
+ break;
+ case llvm::AtomicOrdering::AcquireRelease:
+ case llvm::AtomicOrdering::SequentiallyConsistent:
+ CGF.CGM.getOpenMPRuntime().emitFlush(
+ CGF, llvm::None, Loc, llvm::AtomicOrdering::AcquireRelease);
+ break;
+ case llvm::AtomicOrdering::Monotonic:
+ break;
+ case llvm::AtomicOrdering::NotAtomic:
+ case llvm::AtomicOrdering::Unordered:
+ llvm_unreachable("Unexpected ordering.");
+ }
}
}
@@ -5341,6 +5794,9 @@
case OMPC_in_reduction:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
+ case OMPC_full:
+ case OMPC_partial:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
@@ -5399,7 +5855,14 @@
case OMPC_exclusive:
case OMPC_uses_allocators:
case OMPC_affinity:
- default:
+ case OMPC_init:
+ case OMPC_inbranch:
+ case OMPC_notinbranch:
+ case OMPC_link:
+ case OMPC_use:
+ case OMPC_novariants:
+ case OMPC_nocontext:
+ case OMPC_filter:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}
@@ -5431,7 +5894,7 @@
C->getClauseKind() != OMPC_acq_rel &&
C->getClauseKind() != OMPC_acquire &&
C->getClauseKind() != OMPC_release &&
- C->getClauseKind() != OMPC_relaxed) {
+ C->getClauseKind() != OMPC_relaxed && C->getClauseKind() != OMPC_hint) {
Kind = C->getClauseKind();
break;
}
@@ -5554,6 +6017,7 @@
CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
+ CGF.EnsureInsertPoint();
}
void CodeGenFunction::EmitOMPTargetDeviceFunction(CodeGenModule &CGM,
@@ -5970,7 +6434,9 @@
llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
// TODO: This check is necessary as we only generate `omp parallel` through
// the OpenMPIRBuilder for now.
- if (S.getCancelRegion() == OMPD_parallel) {
+ if (S.getCancelRegion() == OMPD_parallel ||
+ S.getCancelRegion() == OMPD_sections ||
+ S.getCancelRegion() == OMPD_section) {
llvm::Value *IfCondition = nullptr;
if (IfCond)
IfCondition = EmitScalarExpr(IfCond,
@@ -6695,7 +7161,7 @@
for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
if (!C->getNumForLoops())
continue;
- for (unsigned I = LD->getCollapsedNumber(),
+ for (unsigned I = LD->getLoopsNumber(),
E = C->getLoopNumIterations().size();
I < E; ++I) {
if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
@@ -6714,7 +7180,8 @@
if (D.getDirectiveKind() == OMPD_atomic ||
D.getDirectiveKind() == OMPD_critical ||
D.getDirectiveKind() == OMPD_section ||
- D.getDirectiveKind() == OMPD_master) {
+ D.getDirectiveKind() == OMPD_master ||
+ D.getDirectiveKind() == OMPD_masked) {
EmitStmt(D.getAssociatedStmt());
} else {
auto LPCRegion =
diff --git a/src/llvm-project/clang/lib/CodeGen/CGVTables.cpp b/src/llvm-project/clang/lib/CodeGen/CGVTables.cpp
index bef9a29..9eb6508 100644
--- a/src/llvm-project/clang/lib/CodeGen/CGVTables.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CGVTables.cpp
@@ -427,7 +427,8 @@
unsigned CallingConv;
llvm::AttributeList Attrs;
CGM.ConstructAttributeList(Callee.getCallee()->getName(), *CurFnInfo, GD,
- Attrs, CallingConv, /*AttrOnCallSite=*/true);
+ Attrs, CallingConv, /*AttrOnCallSite=*/true,
+ /*IsThunk=*/false);
Call->setAttributes(Attrs);
Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
@@ -531,7 +532,7 @@
OldThunkFn->setName(StringRef());
ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
Name.str(), &CGM.getModule());
- CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
+ CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn, /*IsThunk=*/false);
// If needed, replace the old thunk with a bitcast.
if (!OldThunkFn->use_empty()) {
@@ -727,22 +728,7 @@
case VTableComponent::CK_FunctionPointer:
case VTableComponent::CK_CompleteDtorPointer:
case VTableComponent::CK_DeletingDtorPointer: {
- GlobalDecl GD;
-
- // Get the right global decl.
- switch (component.getKind()) {
- default:
- llvm_unreachable("Unexpected vtable component kind");
- case VTableComponent::CK_FunctionPointer:
- GD = component.getFunctionDecl();
- break;
- case VTableComponent::CK_CompleteDtorPointer:
- GD = GlobalDecl(component.getDestructorDecl(), Dtor_Complete);
- break;
- case VTableComponent::CK_DeletingDtorPointer:
- GD = GlobalDecl(component.getDestructorDecl(), Dtor_Deleting);
- break;
- }
+ GlobalDecl GD = component.getGlobalDecl();
if (CGM.getLangOpts().CUDA) {
// Emit NULL for methods we can't codegen on this
diff --git a/src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp b/src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp
index 778d4df..b30bd11 100644
--- a/src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp
@@ -60,22 +60,19 @@
bool handleDiagnostics(const DiagnosticInfo &DI) override;
bool isAnalysisRemarkEnabled(StringRef PassName) const override {
- return (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
- CodeGenOpts.OptimizationRemarkAnalysisPattern->match(PassName));
+ return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(PassName);
}
bool isMissedOptRemarkEnabled(StringRef PassName) const override {
- return (CodeGenOpts.OptimizationRemarkMissedPattern &&
- CodeGenOpts.OptimizationRemarkMissedPattern->match(PassName));
+ return CodeGenOpts.OptimizationRemarkMissed.patternMatches(PassName);
}
bool isPassedOptRemarkEnabled(StringRef PassName) const override {
- return (CodeGenOpts.OptimizationRemarkPattern &&
- CodeGenOpts.OptimizationRemarkPattern->match(PassName));
+ return CodeGenOpts.OptimizationRemark.patternMatches(PassName);
}
bool isAnyRemarkEnabled() const override {
- return (CodeGenOpts.OptimizationRemarkAnalysisPattern ||
- CodeGenOpts.OptimizationRemarkMissedPattern ||
- CodeGenOpts.OptimizationRemarkPattern);
+ return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() ||
+ CodeGenOpts.OptimizationRemarkMissed.hasValidPattern() ||
+ CodeGenOpts.OptimizationRemark.hasValidPattern();
}
private:
@@ -304,14 +301,7 @@
if (!getModule())
return;
- // Install an inline asm handler so that diagnostics get printed through
- // our diagnostics hooks.
LLVMContext &Ctx = getModule()->getContext();
- LLVMContext::InlineAsmDiagHandlerTy OldHandler =
- Ctx.getInlineAsmDiagnosticHandler();
- void *OldContext = Ctx.getInlineAsmDiagnosticContext();
- Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this);
-
std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler =
Ctx.getDiagnosticHandler();
Ctx.setDiagnosticHandler(std::make_unique<ClangDiagnosticHandler>(
@@ -342,11 +332,9 @@
EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef());
EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts,
- LangOpts, C.getTargetInfo().getDataLayout(),
+ LangOpts, C.getTargetInfo().getDataLayoutString(),
getModule(), Action, std::move(AsmOutStream));
- Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
-
Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler));
if (OptRecordFile)
@@ -380,12 +368,6 @@
Gen->HandleVTable(RD);
}
- static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
- unsigned LocCookie) {
- SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
- ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
- }
-
/// Get the best possible source location to represent a diagnostic that
/// may have associated debug info.
const FullSourceLoc
@@ -393,14 +375,13 @@
bool &BadDebugInfo, StringRef &Filename,
unsigned &Line, unsigned &Column) const;
- void InlineAsmDiagHandler2(const llvm::SMDiagnostic &,
- SourceLocation LocCookie);
-
void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI);
/// Specialized handler for InlineAsm diagnostic.
/// \return True if the diagnostic has been successfully reported, false
/// otherwise.
bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D);
+ /// Specialized handler for diagnostics reported using SMDiagnostic.
+ void SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &D);
/// Specialized handler for StackSize diagnostic.
/// \return True if the diagnostic has been successfully reported, false
/// otherwise.
@@ -459,64 +440,6 @@
return FullSourceLoc(NewLoc, CSM);
}
-
-/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an
-/// error parsing inline asm. The SMDiagnostic indicates the error relative to
-/// the temporary memory buffer that the inline asm parser has set up.
-void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
- SourceLocation LocCookie) {
- // There are a couple of different kinds of errors we could get here. First,
- // we re-format the SMDiagnostic in terms of a clang diagnostic.
-
- // Strip "error: " off the start of the message string.
- StringRef Message = D.getMessage();
- if (Message.startswith("error: "))
- Message = Message.substr(7);
-
- // If the SMDiagnostic has an inline asm source location, translate it.
- FullSourceLoc Loc;
- if (D.getLoc() != SMLoc())
- Loc = ConvertBackendLocation(D, Context->getSourceManager());
-
- unsigned DiagID;
- switch (D.getKind()) {
- case llvm::SourceMgr::DK_Error:
- DiagID = diag::err_fe_inline_asm;
- break;
- case llvm::SourceMgr::DK_Warning:
- DiagID = diag::warn_fe_inline_asm;
- break;
- case llvm::SourceMgr::DK_Note:
- DiagID = diag::note_fe_inline_asm;
- break;
- case llvm::SourceMgr::DK_Remark:
- llvm_unreachable("remarks unexpected");
- }
- // If this problem has clang-level source location information, report the
- // issue in the source with a note showing the instantiated
- // code.
- if (LocCookie.isValid()) {
- Diags.Report(LocCookie, DiagID).AddString(Message);
-
- if (D.getLoc().isValid()) {
- DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
- // Convert the SMDiagnostic ranges into SourceRange and attach them
- // to the diagnostic.
- for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) {
- unsigned Column = D.getColumnNo();
- B << SourceRange(Loc.getLocWithOffset(Range.first - Column),
- Loc.getLocWithOffset(Range.second - Column));
- }
- }
- return;
- }
-
- // Otherwise, report the backend issue as occurring in the generated .s file.
- // If Loc is invalid, we still need to report the issue, it just gets no
- // location info.
- Diags.Report(Loc, DiagID).AddString(Message);
-}
-
#define ComputeDiagID(Severity, GroupName, DiagID) \
do { \
switch (Severity) { \
@@ -553,6 +476,65 @@
} \
} while (false)
+void BackendConsumer::SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &DI) {
+ const llvm::SMDiagnostic &D = DI.getSMDiag();
+
+ unsigned DiagID;
+ if (DI.isInlineAsmDiag())
+ ComputeDiagID(DI.getSeverity(), inline_asm, DiagID);
+ else
+ ComputeDiagID(DI.getSeverity(), source_mgr, DiagID);
+
+ // This is for the empty BackendConsumer that uses the clang diagnostic
+ // handler for IR input files.
+ if (!Context) {
+ D.print(nullptr, llvm::errs());
+ Diags.Report(DiagID).AddString("cannot compile inline asm");
+ return;
+ }
+
+ // There are a couple of different kinds of errors we could get here.
+ // First, we re-format the SMDiagnostic in terms of a clang diagnostic.
+
+ // Strip "error: " off the start of the message string.
+ StringRef Message = D.getMessage();
+ (void)Message.consume_front("error: ");
+
+ // If the SMDiagnostic has an inline asm source location, translate it.
+ FullSourceLoc Loc;
+ if (D.getLoc() != SMLoc())
+ Loc = ConvertBackendLocation(D, Context->getSourceManager());
+
+ // If this problem has clang-level source location information, report the
+ // issue in the source with a note showing the instantiated
+ // code.
+ if (DI.isInlineAsmDiag()) {
+ SourceLocation LocCookie =
+ SourceLocation::getFromRawEncoding(DI.getLocCookie());
+ if (LocCookie.isValid()) {
+ Diags.Report(LocCookie, DiagID).AddString(Message);
+
+ if (D.getLoc().isValid()) {
+ DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
+ // Convert the SMDiagnostic ranges into SourceRange and attach them
+ // to the diagnostic.
+ for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) {
+ unsigned Column = D.getColumnNo();
+ B << SourceRange(Loc.getLocWithOffset(Range.first - Column),
+ Loc.getLocWithOffset(Range.second - Column));
+ }
+ }
+ return;
+ }
+ }
+
+ // Otherwise, report the backend issue as occurring in the generated .s file.
+ // If Loc is invalid, we still need to report the issue, it just gets no
+ // location info.
+ Diags.Report(Loc, DiagID).AddString(Message);
+ return;
+}
+
bool
BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) {
unsigned DiagID;
@@ -589,7 +571,9 @@
// FIXME: Shouldn't need to truncate to uint32_t
Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()),
diag::warn_fe_frame_larger_than)
- << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND);
+ << static_cast<uint32_t>(D.getStackSize())
+ << static_cast<uint32_t>(D.getStackLimit())
+ << Decl::castToDeclContext(ND);
return true;
}
@@ -722,15 +706,13 @@
if (D.isPassed()) {
// Optimization remarks are active only if the -Rpass flag has a regular
// expression that matches the name of the pass name in \p D.
- if (CodeGenOpts.OptimizationRemarkPattern &&
- CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName()))
+ if (CodeGenOpts.OptimizationRemark.patternMatches(D.getPassName()))
EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark);
} else if (D.isMissed()) {
// Missed optimization remarks are active only if the -Rpass-missed
// flag has a regular expression that matches the name of the pass
// name in \p D.
- if (CodeGenOpts.OptimizationRemarkMissedPattern &&
- CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName()))
+ if (CodeGenOpts.OptimizationRemarkMissed.patternMatches(D.getPassName()))
EmitOptimizationMessage(
D, diag::remark_fe_backend_optimization_remark_missed);
} else {
@@ -741,8 +723,7 @@
ShouldAlwaysPrint = ORA->shouldAlwaysPrint();
if (ShouldAlwaysPrint ||
- (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
- CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
+ CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
EmitOptimizationMessage(
D, diag::remark_fe_backend_optimization_remark_analysis);
}
@@ -755,8 +736,7 @@
// regular expression that matches the name of the pass name in \p D.
if (D.shouldAlwaysPrint() ||
- (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
- CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
+ CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
EmitOptimizationMessage(
D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute);
}
@@ -768,8 +748,7 @@
// regular expression that matches the name of the pass name in \p D.
if (D.shouldAlwaysPrint() ||
- (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
- CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
+ CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
EmitOptimizationMessage(
D, diag::remark_fe_backend_optimization_remark_analysis_aliasing);
}
@@ -791,6 +770,9 @@
return;
ComputeDiagID(Severity, inline_asm, DiagID);
break;
+ case llvm::DK_SrcMgr:
+ SrcMgrDiagHandler(cast<DiagnosticInfoSrcMgr>(DI));
+ return;
case llvm::DK_StackSize:
if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI)))
return;
@@ -905,6 +887,10 @@
return VMContext;
}
+CodeGenerator *CodeGenAction::getCodeGenerator() const {
+ return BEConsumer->getCodeGenerator();
+}
+
static std::unique_ptr<raw_pwrite_stream>
GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
switch (Action) {
@@ -987,30 +973,6 @@
return std::move(Result);
}
-static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM,
- void *Context,
- unsigned LocCookie) {
- SM.print(nullptr, llvm::errs());
-
- auto Diags = static_cast<DiagnosticsEngine *>(Context);
- unsigned DiagID;
- switch (SM.getKind()) {
- case llvm::SourceMgr::DK_Error:
- DiagID = diag::err_fe_inline_asm;
- break;
- case llvm::SourceMgr::DK_Warning:
- DiagID = diag::warn_fe_inline_asm;
- break;
- case llvm::SourceMgr::DK_Note:
- DiagID = diag::note_fe_inline_asm;
- break;
- case llvm::SourceMgr::DK_Remark:
- llvm_unreachable("remarks unexpected");
- }
-
- Diags->Report(DiagID).AddString("cannot compile inline asm");
-}
-
std::unique_ptr<llvm::Module>
CodeGenAction::loadModule(MemoryBufferRef MBRef) {
CompilerInstance &CI = getCompilerInstance();
@@ -1113,7 +1075,14 @@
EmbedBitcode(TheModule.get(), CodeGenOpts, *MainFile);
LLVMContext &Ctx = TheModule->getContext();
- Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, &Diagnostics);
+
+ // Restore any diagnostic handler previously set before returning from this
+ // function.
+ struct RAII {
+ LLVMContext &Ctx;
+ std::unique_ptr<DiagnosticHandler> PrevHandler = Ctx.getDiagnosticHandler();
+ ~RAII() { Ctx.setDiagnosticHandler(std::move(PrevHandler)); }
+ } _{Ctx};
// Set clang diagnostic handler. To do this we need to create a fake
// BackendConsumer.
@@ -1142,7 +1111,7 @@
EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts,
TargetOpts, CI.getLangOpts(),
- CI.getTarget().getDataLayout(), TheModule.get(), BA,
+ CI.getTarget().getDataLayoutString(), TheModule.get(), BA,
std::move(OS));
if (OptRecordFile)
OptRecordFile->keep();
diff --git a/src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp b/src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp
index b393c88..a238445 100644
--- a/src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -75,6 +75,7 @@
shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) {
if (!suppressNewContext)
CGM.getCXXABI().getMangleContext().startNewFunction();
+ EHStack.setCGF(this);
SetFastMathFlags(CurFPFeatures);
SetFPModel();
@@ -91,8 +92,8 @@
// seems to be a reasonable spot. We do it here, as opposed to the deletion
// time of the CodeGenModule, because we have to ensure the IR has not yet
// been "emitted" to the outside, thus, modifications are still sensible.
- if (CGM.getLangOpts().OpenMPIRBuilder)
- CGM.getOpenMPRuntime().getOMPBuilder().finalize();
+ if (CGM.getLangOpts().OpenMPIRBuilder && CurFn)
+ CGM.getOpenMPRuntime().getOMPBuilder().finalize(CurFn);
}
// Map the LangOption for exception behavior into
@@ -174,7 +175,7 @@
auto mergeFnAttrValue = [&](StringRef Name, bool Value) {
auto OldValue =
- CGF.CurFn->getFnAttribute(Name).getValueAsString() == "true";
+ CGF.CurFn->getFnAttribute(Name).getValueAsBool();
auto NewValue = OldValue & Value;
if (OldValue != NewValue)
CGF.CurFn->addFnAttr(Name, llvm::toStringRef(NewValue));
@@ -452,13 +453,13 @@
if (CGM.getCodeGenOpts().EmitDeclMetadata)
EmitDeclMetadata();
- for (SmallVectorImpl<std::pair<llvm::Instruction *, llvm::Value *> >::iterator
- I = DeferredReplacements.begin(),
- E = DeferredReplacements.end();
- I != E; ++I) {
- I->first->replaceAllUsesWith(I->second);
- I->first->eraseFromParent();
+ for (const auto &R : DeferredReplacements) {
+ if (llvm::Value *Old = R.first) {
+ Old->replaceAllUsesWith(R.second);
+ cast<llvm::Instruction>(Old)->eraseFromParent();
+ }
}
+ DeferredReplacements.clear();
// Eliminate CleanupDestSlot alloca by replacing it with SSA values and
// PHIs if the current function is a coroutine. We don't do it for all
@@ -495,6 +496,13 @@
// function.
CurFn->addFnAttr("min-legal-vector-width", llvm::utostr(LargestVectorWidth));
+ // Add vscale attribute if appropriate.
+ if (getLangOpts().ArmSveVectorBits) {
+ unsigned VScale = getLangOpts().ArmSveVectorBits / 128;
+ CurFn->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(getLLVMContext(),
+ VScale, VScale));
+ }
+
// If we generated an unreachable return block, delete it now.
if (ReturnBlock.isValid() && ReturnBlock.getBlock()->use_empty()) {
Builder.ClearInsertionPoint();
@@ -702,23 +710,23 @@
DidCallStackSave = false;
CurCodeDecl = D;
- if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
- if (FD->usesSEHTry())
- CurSEHParent = FD;
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (FD && FD->usesSEHTry())
+ CurSEHParent = FD;
CurFuncDecl = (D ? D->getNonClosureContext() : nullptr);
FnRetTy = RetTy;
CurFn = Fn;
CurFnInfo = &FnInfo;
assert(CurFn->isDeclaration() && "Function already has body?");
- // If this function has been blacklisted for any of the enabled sanitizers,
+ // If this function is ignored for any of the enabled sanitizers,
// disable the sanitizer for the function.
do {
#define SANITIZER(NAME, ID) \
if (SanOpts.empty()) \
break; \
if (SanOpts.has(SanitizerKind::ID)) \
- if (CGM.isInSanitizerBlacklist(SanitizerKind::ID, Fn, Loc)) \
+ if (CGM.isInNoSanitizeList(SanitizerKind::ID, Fn, Loc)) \
SanOpts.set(SanitizerKind::ID, false);
#include "clang/Basic/Sanitizers.def"
@@ -726,8 +734,10 @@
} while (0);
if (D) {
- // Apply the no_sanitize* attributes to SanOpts.
+ bool NoSanitizeCoverage = false;
+
for (auto Attr : D->specific_attrs<NoSanitizeAttr>()) {
+ // Apply the no_sanitize* attributes to SanOpts.
SanitizerMask mask = Attr->getMask();
SanOpts.Mask &= ~mask;
if (mask & SanitizerKind::Address)
@@ -738,7 +748,14 @@
SanOpts.set(SanitizerKind::KernelHWAddress, false);
if (mask & SanitizerKind::KernelHWAddress)
SanOpts.set(SanitizerKind::HWAddress, false);
+
+ // SanitizeCoverage is not handled by SanOpts.
+ if (Attr->hasCoverage())
+ NoSanitizeCoverage = true;
}
+
+ if (NoSanitizeCoverage && CGM.getCodeGenOpts().hasSanitizeCoverage())
+ Fn->addFnAttr(llvm::Attribute::NoSanitizeCoverage);
}
// Apply sanitizer attributes to the function.
@@ -786,10 +803,9 @@
// are not aware of how to move the extra UBSan instructions across the split
// coroutine boundaries.
if (D && SanOpts.has(SanitizerKind::Null))
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- if (FD->getBody() &&
- FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass)
- SanOpts.Mask &= ~SanitizerKind::Null;
+ if (FD && FD->getBody() &&
+ FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass)
+ SanOpts.Mask &= ~SanitizerKind::Null;
// Apply xray attributes to the function (as a string, for now)
bool AlwaysXRayAttr = false;
@@ -859,8 +875,8 @@
}
// Add no-jump-tables value.
- Fn->addFnAttr("no-jump-tables",
- llvm::toStringRef(CGM.getCodeGenOpts().NoUseJumpTables));
+ if (CGM.getCodeGenOpts().NoUseJumpTables)
+ Fn->addFnAttr("no-jump-tables", "true");
// Add no-inline-line-tables value.
if (CGM.getCodeGenOpts().NoInlineLineTables)
@@ -876,32 +892,30 @@
if (D && D->hasAttr<CFICanonicalJumpTableAttr>())
Fn->addFnAttr("cfi-canonical-jump-table");
- if (getLangOpts().OpenCL) {
+ if (D && D->hasAttr<NoProfileFunctionAttr>())
+ Fn->addFnAttr(llvm::Attribute::NoProfile);
+
+ if (FD && getLangOpts().OpenCL) {
// Add metadata for a kernel function.
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
- EmitOpenCLKernelMetadata(FD, Fn);
+ EmitOpenCLKernelMetadata(FD, Fn);
}
// If we are checking function types, emit a function type signature as
// prologue data.
- if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) {
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
- if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) {
- // Remove any (C++17) exception specifications, to allow calling e.g. a
- // noexcept function through a non-noexcept pointer.
- auto ProtoTy =
- getContext().getFunctionTypeWithExceptionSpec(FD->getType(),
- EST_None);
- llvm::Constant *FTRTTIConst =
- CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true);
- llvm::Constant *FTRTTIConstEncoded =
- EncodeAddrForUseInPrologue(Fn, FTRTTIConst);
- llvm::Constant *PrologueStructElems[] = {PrologueSig,
- FTRTTIConstEncoded};
- llvm::Constant *PrologueStructConst =
- llvm::ConstantStruct::getAnon(PrologueStructElems, /*Packed=*/true);
- Fn->setPrologueData(PrologueStructConst);
- }
+ if (FD && getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function)) {
+ if (llvm::Constant *PrologueSig = getPrologueSignature(CGM, FD)) {
+ // Remove any (C++17) exception specifications, to allow calling e.g. a
+ // noexcept function through a non-noexcept pointer.
+ auto ProtoTy = getContext().getFunctionTypeWithExceptionSpec(
+ FD->getType(), EST_None);
+ llvm::Constant *FTRTTIConst =
+ CGM.GetAddrOfRTTIDescriptor(ProtoTy, /*ForEH=*/true);
+ llvm::Constant *FTRTTIConstEncoded =
+ EncodeAddrForUseInPrologue(Fn, FTRTTIConst);
+ llvm::Constant *PrologueStructElems[] = {PrologueSig, FTRTTIConstEncoded};
+ llvm::Constant *PrologueStructConst =
+ llvm::ConstantStruct::getAnon(PrologueStructElems, /*Packed=*/true);
+ Fn->setPrologueData(PrologueStructConst);
}
}
@@ -928,14 +942,12 @@
// kernels cannot include RTTI information, exception classes,
// recursive code, virtual functions or make use of C++ libraries that
// are not compiled for the device.
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
- if ((getLangOpts().CPlusPlus && FD->isMain()) || getLangOpts().OpenCL ||
- getLangOpts().SYCLIsDevice ||
- (getLangOpts().CUDA && FD->hasAttr<CUDAGlobalAttr>()))
- Fn->addFnAttr(llvm::Attribute::NoRecurse);
- }
+ if (FD && ((getLangOpts().CPlusPlus && FD->isMain()) ||
+ getLangOpts().OpenCL || getLangOpts().SYCLIsDevice ||
+ (getLangOpts().CUDA && FD->hasAttr<CUDAGlobalAttr>())))
+ Fn->addFnAttr(llvm::Attribute::NoRecurse);
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (FD) {
Builder.setIsFPConstrained(FD->hasAttr<StrictFPAttr>());
if (FD->hasAttr<StrictFPAttr>())
Fn->addFnAttr(llvm::Attribute::StrictFP);
@@ -943,10 +955,9 @@
// If a custom alignment is used, force realigning to this alignment on
// any main function which certainly will need it.
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
- if ((FD->isMain() || FD->isMSVCRTEntryPoint()) &&
- CGM.getCodeGenOpts().StackAlignment)
- Fn->addFnAttr("stackrealign");
+ if (FD && ((FD->isMain() || FD->isMSVCRTEntryPoint()) &&
+ CGM.getCodeGenOpts().StackAlignment))
+ Fn->addFnAttr("stackrealign");
llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
@@ -973,7 +984,7 @@
// such as 'this' and 'vtt', show up in the debug info. Preserve the calling
// convention.
CallingConv CC = CallingConv::CC_C;
- if (auto *FD = dyn_cast_or_null<FunctionDecl>(D))
+ if (FD)
if (const auto *SrcFnTy = FD->getType()->getAs<FunctionType>())
CC = SrcFnTy->getCallConv();
SmallVector<QualType, 16> ArgTypes;
@@ -1033,6 +1044,10 @@
Fn->addFnAttr("packed-stack");
}
+ if (CGM.getCodeGenOpts().WarnStackSize != UINT_MAX)
+ Fn->addFnAttr("warn-stack-size",
+ std::to_string(CGM.getCodeGenOpts().WarnStackSize));
+
if (RetTy->isVoidType()) {
// Void type; nothing to return.
ReturnValue = Address::invalid();
@@ -1060,9 +1075,12 @@
unsigned Idx = CurFnInfo->getReturnInfo().getInAllocaFieldIndex();
llvm::Function::arg_iterator EI = CurFn->arg_end();
--EI;
- llvm::Value *Addr = Builder.CreateStructGEP(nullptr, &*EI, Idx);
+ llvm::Value *Addr = Builder.CreateStructGEP(
+ EI->getType()->getPointerElementType(), &*EI, Idx);
+ llvm::Type *Ty =
+ cast<llvm::GetElementPtrInst>(Addr)->getResultElementType();
ReturnValuePointer = Address(Addr, getPointerAlign());
- Addr = Builder.CreateAlignedLoad(Addr, getPointerAlign(), "agg.result");
+ Addr = Builder.CreateAlignedLoad(Ty, Addr, getPointerAlign(), "agg.result");
ReturnValue = Address(Addr, CGM.getNaturalTypeAlignment(RetTy));
} else {
ReturnValue = CreateIRTemp(RetTy, "retval");
@@ -1177,9 +1195,6 @@
void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
incrementProfileCounter(Body);
- if (CPlusPlusWithProgress())
- FnIsMustProgress = true;
-
if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
else
@@ -1187,7 +1202,7 @@
// This is checked after emitting the function body so we know if there
// are any permitted infinite loops.
- if (FnIsMustProgress)
+ if (checkIfFunctionMustProgress())
CurFn->addFnAttr(llvm::Attribute::MustProgress);
}
@@ -1272,19 +1287,6 @@
return ResTy;
}
-static bool
-shouldUseUndefinedBehaviorReturnOptimization(const FunctionDecl *FD,
- const ASTContext &Context) {
- QualType T = FD->getReturnType();
- // Avoid the optimization for functions that return a record type with a
- // trivial destructor or another trivially copyable type.
- if (const RecordType *RT = T.getCanonicalType()->getAs<RecordType>()) {
- if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
- return !ClassDecl->hasTrivialDestructor();
- }
- return !T.isTriviallyCopyableType(Context);
-}
-
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -1294,8 +1296,14 @@
QualType ResTy = BuildFunctionArgList(GD, Args);
// Check if we should generate debug info for this function.
- if (FD->hasAttr<NoDebugAttr>())
- DebugInfo = nullptr; // disable debug info indefinitely for this function
+ if (FD->hasAttr<NoDebugAttr>()) {
+ // Clear non-distinct debug info that was possibly attached to the function
+ // due to an earlier declaration without the nodebug attribute
+ if (Fn)
+ Fn->setSubprogram(nullptr);
+ // Disable debug info indefinitely for this function
+ DebugInfo = nullptr;
+ }
// The function might not have a body if we're generating thunks for a
// function declaration.
@@ -1321,14 +1329,25 @@
Stmt *Body = FD->getBody();
- // Initialize helper which will detect jumps which can cause invalid lifetime
- // markers.
- if (Body && ShouldEmitLifetimeMarkers)
- Bypasses.Init(Body);
+ if (Body) {
+ // Coroutines always emit lifetime markers.
+ if (isa<CoroutineBodyStmt>(Body))
+ ShouldEmitLifetimeMarkers = true;
+
+ // Initialize helper which will detect jumps which can cause invalid
+ // lifetime markers.
+ if (ShouldEmitLifetimeMarkers)
+ Bypasses.Init(Body);
+ }
// Emit the standard function prologue.
StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
+ // Save parameters for coroutine function.
+ if (Body && isa_and_nonnull<CoroutineBodyStmt>(Body))
+ for (const auto *ParamDecl : FD->parameters())
+ FnArgs.push_back(ParamDecl);
+
// Generate the body of the function.
PGO.assignRegionCounters(GD, CurFn);
if (isa<CXXDestructorDecl>(FD))
@@ -1365,7 +1384,7 @@
!FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) {
bool ShouldEmitUnreachable =
CGM.getCodeGenOpts().StrictReturn ||
- shouldUseUndefinedBehaviorReturnOptimization(FD, getContext());
+ !CGM.MayDropFunctionReturn(FD->getASTContext(), FD->getReturnType());
if (SanOpts.has(SanitizerKind::Return)) {
SanitizerScope SanScope(this);
llvm::Value *IsFalse = Builder.getFalse();
@@ -1774,10 +1793,19 @@
return;
}
+ // Emit the code with the fully general case.
+ llvm::Value *CondV;
+ {
+ ApplyDebugLocation DL(*this, Cond);
+ CondV = EvaluateExprAsBool(Cond);
+ }
+
+ llvm::MDNode *Weights = nullptr;
+ llvm::MDNode *Unpredictable = nullptr;
+
// If the branch has a condition wrapped by __builtin_unpredictable,
// create metadata that specifies that the branch is unpredictable.
// Don't bother if not optimizing because that metadata would not be used.
- llvm::MDNode *Unpredictable = nullptr;
auto *Call = dyn_cast<CallExpr>(Cond->IgnoreImpCasts());
if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
auto *FD = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
@@ -1787,18 +1815,17 @@
}
}
- llvm::MDNode *Weights = createBranchWeights(LH);
- if (!Weights) {
+ // If there is a Likelihood knowledge for the cond, lower it.
+ // Note that if not optimizing this won't emit anything.
+ llvm::Value *NewCondV = emitCondLikelihoodViaExpectIntrinsic(CondV, LH);
+ if (CondV != NewCondV)
+ CondV = NewCondV;
+ else {
+ // Otherwise, lower profile counts. Note that we do this even at -O0.
uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
}
- // Emit the code with the fully general case.
- llvm::Value *CondV;
- {
- ApplyDebugLocation DL(*this, Cond);
- CondV = EvaluateExprAsBool(Cond);
- }
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
}
@@ -1826,8 +1853,8 @@
Address begin =
Builder.CreateElementBitCast(dest, CGF.Int8Ty, "vla.begin");
- llvm::Value *end =
- Builder.CreateInBoundsGEP(begin.getPointer(), sizeInChars, "vla.end");
+ llvm::Value *end = Builder.CreateInBoundsGEP(
+ begin.getElementType(), begin.getPointer(), sizeInChars, "vla.end");
llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock();
llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop");
@@ -2034,9 +2061,9 @@
addr = Builder.CreateElementBitCast(addr, baseType, "array.begin");
} else {
// Create the actual GEP.
- addr = Address(Builder.CreateInBoundsGEP(addr.getPointer(),
- gepIndices, "array.begin"),
- addr.getAlignment());
+ addr = Address(Builder.CreateInBoundsGEP(
+ addr.getElementType(), addr.getPointer(), gepIndices, "array.begin"),
+ addr.getAlignment());
}
baseType = eltType;
@@ -2642,35 +2669,26 @@
return llvm::DebugLoc();
}
-static Optional<std::pair<uint32_t, uint32_t>>
-getLikelihoodWeights(Stmt::Likelihood LH) {
+llvm::Value *
+CodeGenFunction::emitCondLikelihoodViaExpectIntrinsic(llvm::Value *Cond,
+ Stmt::Likelihood LH) {
switch (LH) {
- case Stmt::LH_Unlikely:
- return std::pair<uint32_t, uint32_t>(llvm::UnlikelyBranchWeight,
- llvm::LikelyBranchWeight);
case Stmt::LH_None:
- return None;
+ return Cond;
case Stmt::LH_Likely:
- return std::pair<uint32_t, uint32_t>(llvm::LikelyBranchWeight,
- llvm::UnlikelyBranchWeight);
+ case Stmt::LH_Unlikely:
+ // Don't generate llvm.expect on -O0 as the backend won't use it for
+ // anything.
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ return Cond;
+ llvm::Type *CondTy = Cond->getType();
+ assert(CondTy->isIntegerTy(1) && "expecting condition to be a boolean");
+ llvm::Function *FnExpect =
+ CGM.getIntrinsic(llvm::Intrinsic::expect, CondTy);
+ llvm::Value *ExpectedValueOfCond =
+ llvm::ConstantInt::getBool(CondTy, LH == Stmt::LH_Likely);
+ return Builder.CreateCall(FnExpect, {Cond, ExpectedValueOfCond},
+ Cond->getName() + ".expval");
}
llvm_unreachable("Unknown Likelihood");
}
-
-llvm::MDNode *CodeGenFunction::createBranchWeights(Stmt::Likelihood LH) const {
- Optional<std::pair<uint32_t, uint32_t>> LHW = getLikelihoodWeights(LH);
- if (!LHW)
- return nullptr;
-
- llvm::MDBuilder MDHelper(CGM.getLLVMContext());
- return MDHelper.createBranchWeights(LHW->first, LHW->second);
-}
-
-llvm::MDNode *CodeGenFunction::createProfileOrBranchWeightsForLoop(
- const Stmt *Cond, uint64_t LoopCount, const Stmt *Body) const {
- llvm::MDNode *Weights = createProfileWeightsForLoop(Cond, LoopCount);
- if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
- Weights = createBranchWeights(Stmt::getLikelihood(Body));
-
- return Weights;
-}
diff --git a/src/llvm-project/clang/lib/CodeGen/CodeGenFunction.h b/src/llvm-project/clang/lib/CodeGen/CodeGenFunction.h
index 95c0b7b..4e087ce 100644
--- a/src/llvm-project/clang/lib/CodeGen/CodeGenFunction.h
+++ b/src/llvm-project/clang/lib/CodeGen/CodeGenFunction.h
@@ -50,6 +50,7 @@
class SwitchInst;
class Twine;
class Value;
+class CanonicalLoopInfo;
}
namespace clang {
@@ -276,6 +277,20 @@
// because of jumps.
VarBypassDetector Bypasses;
+ /// List of recently emitted OMPCanonicalLoops.
+ ///
+ /// Since OMPCanonicalLoops are nested inside other statements (in particular
+ /// CapturedStmt generated by OMPExecutableDirective and non-perfectly nested
+ /// loops), we cannot directly call OMPEmitOMPCanonicalLoop and receive its
+ /// llvm::CanonicalLoopInfo. Instead, we call EmitStmt and any
+ /// OMPEmitOMPCanonicalLoop called by it will add its CanonicalLoopInfo to
+ /// this stack when done. Entering a new loop requires clearing this list; it
+ /// either means we start parsing a new loop nest (in which case the previous
+ /// loop nest goes out of scope) or a second loop in the same level in which
+ /// case it would be ambiguous into which of the two (or more) loops the loop
+ /// nest would extend.
+ SmallVector<llvm::CanonicalLoopInfo *, 4> OMPLoopNestStack;
+
// CodeGen lambda for loops and support for ordered clause
typedef llvm::function_ref<void(CodeGenFunction &, const OMPLoopDirective &,
JumpDest)>
@@ -310,6 +325,9 @@
QualType FnRetTy;
llvm::Function *CurFn = nullptr;
+ /// Save Parameter Decl for coroutine.
+ llvm::SmallVector<const ParmVarDecl *, 4> FnArgs;
+
// Holds coroutine data if the current function is a coroutine. We use a
// wrapper to manage its lifetime, so that we don't have to define CGCoroData
// in this header.
@@ -502,21 +520,32 @@
/// True if the current statement has nomerge attribute.
bool InNoMergeAttributedStmt = false;
- /// True if the current function should be marked mustprogress.
- bool FnIsMustProgress = false;
+ // The CallExpr within the current statement that the musttail attribute
+ // applies to. nullptr if there is no 'musttail' on the current statement.
+ const CallExpr *MustTailCall = nullptr;
- /// True if the C++ Standard Requires Progress.
- bool CPlusPlusWithProgress() {
+ /// Returns true if a function must make progress, which means the
+ /// mustprogress attribute can be added.
+ bool checkIfFunctionMustProgress() {
if (CGM.getCodeGenOpts().getFiniteLoops() ==
CodeGenOptions::FiniteLoopsKind::Never)
return false;
- return getLangOpts().CPlusPlus11 || getLangOpts().CPlusPlus14 ||
- getLangOpts().CPlusPlus17 || getLangOpts().CPlusPlus20;
+ // C++11 and later guarantees that a thread eventually will do one of the
+ // following (6.9.2.3.1 in C++11):
+ // - terminate,
+ // - make a call to a library I/O function,
+ // - perform an access through a volatile glvalue, or
+ // - perform a synchronization operation or an atomic operation.
+ //
+ // Hence each function is 'mustprogress' in C++11 or later.
+ return getLangOpts().CPlusPlus11;
}
- /// True if the C Standard Requires Progress.
- bool CWithProgress() {
+ /// Returns true if a loop must make progress, which means the mustprogress
+ /// attribute can be added. \p HasConstantCond indicates whether the branch
+ /// condition is a known constant.
+ bool checkIfLoopMustProgress(bool HasConstantCond) {
if (CGM.getCodeGenOpts().getFiniteLoops() ==
CodeGenOptions::FiniteLoopsKind::Always)
return true;
@@ -524,13 +553,19 @@
CodeGenOptions::FiniteLoopsKind::Never)
return false;
- return getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x;
- }
+ // If the containing function must make progress, loops also must make
+ // progress (as in C++11 and later).
+ if (checkIfFunctionMustProgress())
+ return true;
- /// True if the language standard requires progress in functions or
- /// in infinite loops with non-constant conditionals.
- bool LanguageRequiresProgress() {
- return CWithProgress() || CPlusPlusWithProgress();
+ // Now apply rules for plain C (see 6.8.5.6 in C11).
+ // Loops with constant conditions do not have to make progress in any C
+ // version.
+ if (HasConstantCond)
+ return false;
+
+ // Loops with non-constant conditions must make progress in C11 and later.
+ return getLangOpts().C11;
}
const CodeGen::CGBlockInfo *BlockInfo = nullptr;
@@ -550,6 +585,8 @@
llvm::Instruction *CurrentFuncletPad = nullptr;
class CallLifetimeEnd final : public EHScopeStack::Cleanup {
+ bool isRedundantBeforeReturn() override { return true; }
+
llvm::Value *Addr;
llvm::Value *Size;
@@ -1430,8 +1467,9 @@
};
OpenMPCancelExitStack OMPCancelStack;
- /// Calculate branch weights for the likelihood attribute
- llvm::MDNode *createBranchWeights(Stmt::Likelihood LH) const;
+ /// Lower the Likelihood knowledge about the \p Cond via llvm.expect intrin.
+ llvm::Value *emitCondLikelihoodViaExpectIntrinsic(llvm::Value *Cond,
+ Stmt::Likelihood LH);
CodeGenPGO PGO;
@@ -1442,13 +1480,6 @@
llvm::MDNode *createProfileWeightsForLoop(const Stmt *Cond,
uint64_t LoopCount) const;
- /// Calculate the branch weight for PGO data or the likelihood attribute.
- /// The function tries to get the weight of \ref createProfileWeightsForLoop.
- /// If that fails it gets the weight of \ref createBranchWeights.
- llvm::MDNode *createProfileOrBranchWeightsForLoop(const Stmt *Cond,
- uint64_t LoopCount,
- const Stmt *Body) const;
-
public:
/// Increment the profiler's counter for the given statement by \p StepV.
/// If \p StepV is null, the default increment is 1.
@@ -1877,8 +1908,9 @@
/// function attribute.
unsigned LargestVectorWidth = 0;
- /// True if we need emit the life-time markers.
- const bool ShouldEmitLifetimeMarkers;
+ /// True if we need emit the life-time markers. This is initially set in
+ /// the constructor, but could be overwritten to true if this is a coroutine.
+ bool ShouldEmitLifetimeMarkers;
/// Add OpenCL kernel arg metadata and the kernel attribute metadata to
/// the function metadata.
@@ -2835,7 +2867,12 @@
void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
Address Ptr);
- llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr);
+ void EmitSehCppScopeBegin();
+ void EmitSehCppScopeEnd();
+ void EmitSehTryScopeBegin();
+ void EmitSehTryScopeEnd();
+
+ llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr);
void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E);
@@ -3185,6 +3222,8 @@
void EmitSEHLeaveStmt(const SEHLeaveStmt &S);
void EnterSEHTryStmt(const SEHTryStmt &S);
void ExitSEHTryStmt(const SEHTryStmt &S);
+ void VolatilizeTryBlocks(llvm::BasicBlock *BB,
+ llvm::SmallPtrSet<llvm::BasicBlock *, 10> &V);
void pushSEHCleanup(CleanupKind kind,
llvm::Function *FinallyFunc);
@@ -3401,12 +3440,15 @@
void EmitOMPParallelDirective(const OMPParallelDirective &S);
void EmitOMPSimdDirective(const OMPSimdDirective &S);
+ void EmitOMPTileDirective(const OMPTileDirective &S);
+ void EmitOMPUnrollDirective(const OMPUnrollDirective &S);
void EmitOMPForDirective(const OMPForDirective &S);
void EmitOMPForSimdDirective(const OMPForSimdDirective &S);
void EmitOMPSectionsDirective(const OMPSectionsDirective &S);
void EmitOMPSectionDirective(const OMPSectionDirective &S);
void EmitOMPSingleDirective(const OMPSingleDirective &S);
void EmitOMPMasterDirective(const OMPMasterDirective &S);
+ void EmitOMPMaskedDirective(const OMPMaskedDirective &S);
void EmitOMPCriticalDirective(const OMPCriticalDirective &S);
void EmitOMPParallelForDirective(const OMPParallelForDirective &S);
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S);
@@ -3510,6 +3552,18 @@
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
CodeGenModule &CGM, StringRef ParentName,
const OMPTargetTeamsDistributeParallelForDirective &S);
+
+ /// Emit the Stmt \p S and return its topmost canonical loop, if any.
+ /// TODO: The \p Depth paramter is not yet implemented and must be 1. In the
+ /// future it is meant to be the number of loops expected in the loop nests
+ /// (usually specified by the "collapse" clause) that are collapsed to a
+ /// single loop by this function.
+ llvm::CanonicalLoopInfo *EmitOMPCollapsedCanonicalLoopNest(const Stmt *S,
+ int Depth);
+
+ /// Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
+ void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S);
+
/// Emit inner loop of the worksharing/simd construct.
///
/// \param S Directive, for which the inner loop must be emitted.
@@ -3546,7 +3600,7 @@
const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr);
/// Helpers for the OpenMP loop directives.
- void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false);
+ void EmitOMPSimdInit(const OMPLoopDirective &D);
void EmitOMPSimdFinal(
const OMPLoopDirective &D,
const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen);
@@ -3886,12 +3940,14 @@
/// LLVM arguments and the types they were derived from.
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee,
ReturnValueSlot ReturnValue, const CallArgList &Args,
- llvm::CallBase **callOrInvoke, SourceLocation Loc);
+ llvm::CallBase **callOrInvoke, bool IsMustTail,
+ SourceLocation Loc);
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee,
ReturnValueSlot ReturnValue, const CallArgList &Args,
- llvm::CallBase **callOrInvoke = nullptr) {
+ llvm::CallBase **callOrInvoke = nullptr,
+ bool IsMustTail = false) {
return EmitCall(CallInfo, Callee, ReturnValue, Args, callOrInvoke,
- SourceLocation());
+ IsMustTail, SourceLocation());
}
RValue EmitCall(QualType FnType, const CGCallee &Callee, const CallExpr *E,
ReturnValueSlot ReturnValue, llvm::Value *Chain = nullptr);
@@ -4128,6 +4184,8 @@
llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
const CallExpr *E);
llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
+ llvm::Value *EmitRISCVBuiltinExpr(unsigned BuiltinID, const CallExpr *E,
+ ReturnValueSlot ReturnValue);
bool ProcessOrderScopeAMDGCN(llvm::Value *Order, llvm::Value *Scope,
llvm::AtomicOrdering &AO,
llvm::SyncScope::ID &SSID);
@@ -4213,6 +4271,8 @@
void EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values);
+ void EmitARCNoopIntrinsicUse(ArrayRef<llvm::Value *> values);
+
static Destroyer destroyARCStrongImprecise;
static Destroyer destroyARCStrongPrecise;
static Destroyer destroyARCWeak;
@@ -4304,6 +4364,11 @@
llvm::Function *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor,
llvm::Constant *Addr);
+ llvm::Function *createTLSAtExitStub(const VarDecl &VD,
+ llvm::FunctionCallee Dtor,
+ llvm::Constant *Addr,
+ llvm::FunctionCallee &AtExit);
+
/// Call atexit() with a function that passes the given argument to
/// the given function.
void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::FunctionCallee fn,
@@ -4342,8 +4407,9 @@
/// variables.
void GenerateCXXGlobalCleanUpFunc(
llvm::Function *Fn,
- const std::vector<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
- llvm::Constant *>> &DtorsOrStermFinalizers);
+ ArrayRef<std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
+ llvm::Constant *>>
+ DtorsOrStermFinalizers);
void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
const VarDecl *D,
@@ -4534,8 +4600,8 @@
void deferPlaceholderReplacement(llvm::Instruction *Old, llvm::Value *New);
- llvm::SmallVector<std::pair<llvm::Instruction *, llvm::Value *>, 4>
- DeferredReplacements;
+ llvm::SmallVector<std::pair<llvm::WeakTrackingVH, llvm::Value *>, 4>
+ DeferredReplacements;
/// Set the address of a local variable.
void setAddrOfLocalVar(const VarDecl *VD, Address Addr) {
@@ -4641,7 +4707,6 @@
struct MultiVersionResolverOption {
llvm::Function *Function;
- FunctionDecl *FD;
struct Conds {
StringRef Architecture;
llvm::SmallVector<StringRef, 8> Features;
@@ -4775,7 +4840,8 @@
// Otherwise, it should be an alloca instruction, as set up in save().
auto alloca = cast<llvm::AllocaInst>(value.getPointer());
- return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlign());
+ return CGF.Builder.CreateAlignedLoad(alloca->getAllocatedType(), alloca,
+ alloca->getAlign());
}
} // end namespace CodeGen
diff --git a/src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
index 9c9bd4e..49a1396 100644
--- a/src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
@@ -75,7 +75,7 @@
static const char AnnotationSection[] = "llvm.metadata";
static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
- switch (CGM.getTarget().getCXXABI().getKind()) {
+ switch (CGM.getContext().getCXXABIKind()) {
case TargetCXXABI::AppleARM64:
case TargetCXXABI::Fuchsia:
case TargetCXXABI::GenericAArch64:
@@ -180,6 +180,34 @@
// CoverageMappingModuleGen object.
if (CodeGenOpts.CoverageMapping)
CoverageMapping.reset(new CoverageMappingModuleGen(*this, *CoverageInfo));
+
+ // Generate the module name hash here if needed.
+ if (CodeGenOpts.UniqueInternalLinkageNames &&
+ !getModule().getSourceFileName().empty()) {
+ std::string Path = getModule().getSourceFileName();
+ // Check if a path substitution is needed from the MacroPrefixMap.
+ for (const auto &Entry : LangOpts.MacroPrefixMap)
+ if (Path.rfind(Entry.first, 0) != std::string::npos) {
+ Path = Entry.second + Path.substr(Entry.first.size());
+ break;
+ }
+ llvm::MD5 Md5;
+ Md5.update(Path);
+ llvm::MD5::MD5Result R;
+ Md5.final(R);
+ SmallString<32> Str;
+ llvm::MD5::stringifyResult(R, Str);
+ // Convert MD5hash to Decimal. Demangler suffixes can either contain
+ // numbers or characters but not both.
+ llvm::APInt IntHash(128, Str.str(), 16);
+ // Prepend "__uniq" before the hash for tools like profilers to understand
+ // that this symbol is of internal linkage type. The "__uniq" is the
+ // pre-determined prefix that is used to tell tools that this symbol was
+ // created with -funique-internal-linakge-symbols and the tools can strip or
+ // keep the prefix as needed.
+ ModuleNameHash = (Twine(".__uniq.") +
+ Twine(toString(IntHash, /* Radix = */ 10, /* Signed = */false))).str();
+ }
}
CodeGenModule::~CodeGenModule() {}
@@ -459,10 +487,8 @@
if (ObjCRuntime)
if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction())
AddGlobalCtor(ObjCInitFunction);
- if (Context.getLangOpts().CUDA && !Context.getLangOpts().CUDAIsDevice &&
- CUDARuntime) {
- if (llvm::Function *CudaCtorFunction =
- CUDARuntime->makeModuleCtorFunction())
+ if (Context.getLangOpts().CUDA && CUDARuntime) {
+ if (llvm::Function *CudaCtorFunction = CUDARuntime->finalizeModule())
AddGlobalCtor(CudaCtorFunction);
}
if (OpenMPRuntime) {
@@ -485,6 +511,7 @@
EmitGlobalAnnotations();
EmitStaticExternCAliases();
EmitDeferredUnusedCoverageMappings();
+ CodeGenPGO(*this).setValueProfilingFlag(getModule());
if (CoverageMapping)
CoverageMapping->emit();
if (CodeGenOpts.SanitizeCfiCrossDso) {
@@ -496,6 +523,22 @@
!Context.getTargetInfo().getTriple().isOSEmscripten()) {
EmitMainVoidAlias();
}
+
+ // Emit reference of __amdgpu_device_library_preserve_asan_functions to
+ // preserve ASAN functions in bitcode libraries.
+ if (LangOpts.Sanitize.has(SanitizerKind::Address) && getTriple().isAMDGPU()) {
+ auto *FT = llvm::FunctionType::get(VoidTy, {});
+ auto *F = llvm::Function::Create(
+ FT, llvm::GlobalValue::ExternalLinkage,
+ "__amdgpu_device_library_preserve_asan_functions", &getModule());
+ auto *Var = new llvm::GlobalVariable(
+ getModule(), FT->getPointerTo(),
+ /*isConstant=*/true, llvm::GlobalValue::WeakAnyLinkage, F,
+ "__amdgpu_device_library_preserve_asan_functions_ptr", nullptr,
+ llvm::GlobalVariable::NotThreadLocal);
+ addCompilerUsedGlobal(Var);
+ }
+
emitLLVMUsed();
if (SanStats)
SanStats->finish();
@@ -533,6 +576,9 @@
CodeGenOpts.DwarfVersion);
}
+ if (CodeGenOpts.Dwarf64)
+ getModule().addModuleFlag(llvm::Module::Max, "DWARF64", 1);
+
if (Context.getLangOpts().SemanticInterposition)
// Require various optimization to respect semantic interposition.
getModule().setSemanticInterposition(1);
@@ -551,6 +597,10 @@
// Function ID tables for Control Flow Guard (cfguard=1).
getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1);
}
+ if (CodeGenOpts.EHContGuard) {
+ // Function ID tables for EH Continuation Guard.
+ getModule().addModuleFlag(llvm::Module::Warning, "ehcontguard", 1);
+ }
if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) {
// We don't support LTO with 2 with different StrictVTablePointers
// FIXME: we could support it by stripping all the information introduced
@@ -664,6 +714,16 @@
llvm::DenormalMode::IEEE);
}
+ if (LangOpts.EHAsynch)
+ getModule().addModuleFlag(llvm::Module::Warning, "eh-asynch", 1);
+
+ // Indicate whether this Module was compiled with -fopenmp
+ if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd)
+ getModule().addModuleFlag(llvm::Module::Max, "openmp", LangOpts.OpenMP);
+ if (getLangOpts().OpenMPIsDevice)
+ getModule().addModuleFlag(llvm::Module::Max, "openmp-device",
+ LangOpts.OpenMP);
+
// Emit OpenCL specific module metadata: OpenCL/SPIR version.
if (LangOpts.OpenCL) {
EmitOpenCLMetadata();
@@ -708,6 +768,20 @@
if (CodeGenOpts.NoPLT)
getModule().setRtLibUseGOT();
+ if (CodeGenOpts.UnwindTables)
+ getModule().setUwtable();
+
+ switch (CodeGenOpts.getFramePointer()) {
+ case CodeGenOptions::FramePointerKind::None:
+ // 0 ("none") is the default.
+ break;
+ case CodeGenOptions::FramePointerKind::NonLeaf:
+ getModule().setFramePointer(llvm::FramePointerKind::NonLeaf);
+ break;
+ case CodeGenOptions::FramePointerKind::All:
+ getModule().setFramePointer(llvm::FramePointerKind::All);
+ break;
+ }
SimplifyPersonality();
@@ -726,6 +800,17 @@
if (!getCodeGenOpts().RecordCommandLine.empty())
EmitCommandLineMetadata();
+ if (!getCodeGenOpts().StackProtectorGuard.empty())
+ getModule().setStackProtectorGuard(getCodeGenOpts().StackProtectorGuard);
+ if (!getCodeGenOpts().StackProtectorGuardReg.empty())
+ getModule().setStackProtectorGuardReg(
+ getCodeGenOpts().StackProtectorGuardReg);
+ if (getCodeGenOpts().StackProtectorGuardOffset != INT_MAX)
+ getModule().setStackProtectorGuardOffset(
+ getCodeGenOpts().StackProtectorGuardOffset);
+ if (getCodeGenOpts().StackAlignment)
+ getModule().setOverrideStackAlignment(getCodeGenOpts().StackAlignment);
+
getTargetCodeGenInfo().emitTargetMetadata(*this, MangledDeclNames);
EmitBackendOptionsMetadata(getCodeGenOpts());
@@ -926,8 +1011,13 @@
// In MinGW, variables without DLLImport can still be automatically
// imported from a DLL by the linker; don't mark variables that
// potentially could come from another DLL as DSO local.
+
+ // With EmulatedTLS, TLS variables can be autoimported from other DLLs
+ // (and this actually happens in the public interface of libstdc++), so
+ // such variables can't be marked as DSO local. (Native TLS variables
+ // can't be dllimported at all, though.)
if (GV->isDeclarationForLinker() && isa<llvm::GlobalVariable>(GV) &&
- !GV->isThreadLocal())
+ (!GV->isThreadLocal() || CGM.getCodeGenOpts().EmulatedTLS))
return false;
}
@@ -945,27 +1035,21 @@
if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO()))
return true;
- const auto &CGOpts = CGM.getCodeGenOpts();
- llvm::Reloc::Model RM = CGOpts.RelocationModel;
- const auto &LOpts = CGM.getLangOpts();
-
- if (TT.isOSBinFormatMachO()) {
- if (RM == llvm::Reloc::Static)
- return true;
- return GV->isStrongDefinitionForLinker();
- }
-
// Only handle COFF and ELF for now.
if (!TT.isOSBinFormatELF())
return false;
+ // If this is not an executable, don't assume anything is local.
+ const auto &CGOpts = CGM.getCodeGenOpts();
+ llvm::Reloc::Model RM = CGOpts.RelocationModel;
+ const auto &LOpts = CGM.getLangOpts();
if (RM != llvm::Reloc::Static && !LOpts.PIE) {
// On ELF, if -fno-semantic-interposition is specified and the target
// supports local aliases, there will be neither CC1
// -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
- // dso_local if using a local alias is preferable (can avoid GOT
- // indirection).
- if (!GV->canBenefitFromLocalAlias())
+ // dso_local on the function if using a local alias is preferable (can avoid
+ // PLT indirection).
+ if (!(isa<llvm::Function>(GV) && GV->canBenefitFromLocalAlias()))
return false;
return !(CGM.getLangOpts().SemanticInterposition ||
CGM.getLangOpts().HalfNoSemanticInterposition);
@@ -1142,13 +1226,25 @@
}
}
-static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD,
+// Returns true if GD is a function decl with internal linkage and
+// needs a unique suffix after the mangled name.
+static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
+ CodeGenModule &CGM) {
+ const Decl *D = GD.getDecl();
+ return !CGM.getModuleNameHash().empty() && isa<FunctionDecl>(D) &&
+ (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
+}
+
+static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
const NamedDecl *ND,
bool OmitMultiVersionMangling = false) {
SmallString<256> Buffer;
llvm::raw_svector_ostream Out(Buffer);
MangleContext &MC = CGM.getCXXABI().getMangleContext();
- if (MC.shouldMangleDeclName(ND))
+ if (!CGM.getModuleNameHash().empty())
+ MC.needsUniqueInternalLinkageNames();
+ bool ShouldMangle = MC.shouldMangleDeclName(ND);
+ if (ShouldMangle)
MC.mangleName(GD.getWithDecl(ND), Out);
else {
IdentifierInfo *II = ND->getIdentifier();
@@ -1166,6 +1262,20 @@
}
}
+ // Check if the module name hash should be appended for internal linkage
+ // symbols. This should come before multi-version target suffixes are
+ // appended. This is to keep the name and module hash suffix of the
+ // internal linkage function together. The unique suffix should only be
+ // added when name mangling is done to make sure that the final name can
+ // be properly demangled. For example, for C functions without prototypes,
+ // name mangling is not done and the unique suffix should not be appeneded
+ // then.
+ if (ShouldMangle && isUniqueInternalLinkageDecl(GD, CGM)) {
+ assert(CGM.getCodeGenOpts().UniqueInternalLinkageNames &&
+ "Hash computed when not explicitly requested");
+ Out << CGM.getModuleNameHash();
+ }
+
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
if (FD->isMultiVersion() && !OmitMultiVersionMangling) {
switch (FD->getMultiVersionKind()) {
@@ -1183,6 +1293,11 @@
}
}
+ // Make unique name for device side static file-scope variable for HIP.
+ if (CGM.getContext().shouldExternalizeStaticVar(ND) &&
+ CGM.getLangOpts().GPURelocatableDeviceCode &&
+ CGM.getLangOpts().CUDAIsDevice && !CGM.getLangOpts().CUID.empty())
+ CGM.printPostfixForExternalizedStaticVar(Out);
return std::string(Out.str());
}
@@ -1240,9 +1355,16 @@
}
}
- auto FoundName = MangledDeclNames.find(CanonicalGD);
- if (FoundName != MangledDeclNames.end())
- return FoundName->second;
+ // In CUDA/HIP device compilation with -fgpu-rdc, the mangled name of a
+ // static device variable depends on whether the variable is referenced by
+ // a host or device host function. Therefore the mangled name cannot be
+ // cached.
+ if (!LangOpts.CUDAIsDevice ||
+ !getContext().mayExternalizeStaticVar(GD.getDecl())) {
+ auto FoundName = MangledDeclNames.find(CanonicalGD);
+ if (FoundName != MangledDeclNames.end())
+ return FoundName->second;
+ }
// Keep the first result in the case of a mangling collision.
const auto *ND = cast<NamedDecl>(GD.getDecl());
@@ -1387,10 +1509,11 @@
void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl GD,
const CGFunctionInfo &Info,
- llvm::Function *F) {
+ llvm::Function *F, bool IsThunk) {
unsigned CallingConv;
llvm::AttributeList PAL;
- ConstructAttributeList(F->getName(), Info, GD, PAL, CallingConv, false);
+ ConstructAttributeList(F->getName(), Info, GD, PAL, CallingConv,
+ /*AttrOnCallSite=*/false, IsThunk);
F->setAttributes(PAL);
F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
}
@@ -1475,6 +1598,39 @@
QualType ty = parm->getType();
std::string typeQuals;
+ // Get image and pipe access qualifier:
+ if (ty->isImageType() || ty->isPipeType()) {
+ const Decl *PDecl = parm;
+ if (auto *TD = dyn_cast<TypedefType>(ty))
+ PDecl = TD->getDecl();
+ const OpenCLAccessAttr *A = PDecl->getAttr<OpenCLAccessAttr>();
+ if (A && A->isWriteOnly())
+ accessQuals.push_back(llvm::MDString::get(VMContext, "write_only"));
+ else if (A && A->isReadWrite())
+ accessQuals.push_back(llvm::MDString::get(VMContext, "read_write"));
+ else
+ accessQuals.push_back(llvm::MDString::get(VMContext, "read_only"));
+ } else
+ accessQuals.push_back(llvm::MDString::get(VMContext, "none"));
+
+ // Get argument name.
+ argNames.push_back(llvm::MDString::get(VMContext, parm->getName()));
+
+ auto getTypeSpelling = [&](QualType Ty) {
+ auto typeName = Ty.getUnqualifiedType().getAsString(Policy);
+
+ if (Ty.isCanonical()) {
+ StringRef typeNameRef = typeName;
+ // Turn "unsigned type" to "utype"
+ if (typeNameRef.consume_front("unsigned "))
+ return std::string("u") + typeNameRef.str();
+ if (typeNameRef.consume_front("signed "))
+ return typeNameRef.str();
+ }
+
+ return typeName;
+ };
+
if (ty->isPointerType()) {
QualType pointeeTy = ty->getPointeeType();
@@ -1484,26 +1640,10 @@
ArgInfoAddressSpace(pointeeTy.getAddressSpace()))));
// Get argument type name.
- std::string typeName =
- pointeeTy.getUnqualifiedType().getAsString(Policy) + "*";
-
- // Turn "unsigned type" to "utype"
- std::string::size_type pos = typeName.find("unsigned");
- if (pointeeTy.isCanonical() && pos != std::string::npos)
- typeName.erase(pos + 1, 8);
-
- argTypeNames.push_back(llvm::MDString::get(VMContext, typeName));
-
+ std::string typeName = getTypeSpelling(pointeeTy) + "*";
std::string baseTypeName =
- pointeeTy.getUnqualifiedType().getCanonicalType().getAsString(
- Policy) +
- "*";
-
- // Turn "unsigned type" to "utype"
- pos = baseTypeName.find("unsigned");
- if (pos != std::string::npos)
- baseTypeName.erase(pos + 1, 8);
-
+ getTypeSpelling(pointeeTy.getCanonicalType()) + "*";
+ argTypeNames.push_back(llvm::MDString::get(VMContext, typeName));
argBaseTypeNames.push_back(
llvm::MDString::get(VMContext, baseTypeName));
@@ -1525,30 +1665,9 @@
llvm::ConstantAsMetadata::get(CGF->Builder.getInt32(AddrSpc)));
// Get argument type name.
- std::string typeName;
- if (isPipe)
- typeName = ty.getCanonicalType()
- ->castAs<PipeType>()
- ->getElementType()
- .getAsString(Policy);
- else
- typeName = ty.getUnqualifiedType().getAsString(Policy);
-
- // Turn "unsigned type" to "utype"
- std::string::size_type pos = typeName.find("unsigned");
- if (ty.isCanonical() && pos != std::string::npos)
- typeName.erase(pos + 1, 8);
-
- std::string baseTypeName;
- if (isPipe)
- baseTypeName = ty.getCanonicalType()
- ->castAs<PipeType>()
- ->getElementType()
- .getCanonicalType()
- .getAsString(Policy);
- else
- baseTypeName =
- ty.getUnqualifiedType().getCanonicalType().getAsString(Policy);
+ ty = isPipe ? ty->castAs<PipeType>()->getElementType() : ty;
+ std::string typeName = getTypeSpelling(ty);
+ std::string baseTypeName = getTypeSpelling(ty.getCanonicalType());
// Remove access qualifiers on images
// (as they are inseparable from type in clang implementation,
@@ -1560,38 +1679,13 @@
}
argTypeNames.push_back(llvm::MDString::get(VMContext, typeName));
-
- // Turn "unsigned type" to "utype"
- pos = baseTypeName.find("unsigned");
- if (pos != std::string::npos)
- baseTypeName.erase(pos + 1, 8);
-
argBaseTypeNames.push_back(
llvm::MDString::get(VMContext, baseTypeName));
if (isPipe)
typeQuals = "pipe";
}
-
argTypeQuals.push_back(llvm::MDString::get(VMContext, typeQuals));
-
- // Get image and pipe access qualifier:
- if (ty->isImageType() || ty->isPipeType()) {
- const Decl *PDecl = parm;
- if (auto *TD = dyn_cast<TypedefType>(ty))
- PDecl = TD->getDecl();
- const OpenCLAccessAttr *A = PDecl->getAttr<OpenCLAccessAttr>();
- if (A && A->isWriteOnly())
- accessQuals.push_back(llvm::MDString::get(VMContext, "write_only"));
- else if (A && A->isReadWrite())
- accessQuals.push_back(llvm::MDString::get(VMContext, "read_write"));
- else
- accessQuals.push_back(llvm::MDString::get(VMContext, "read_only"));
- } else
- accessQuals.push_back(llvm::MDString::get(VMContext, "none"));
-
- // Get argument name.
- argNames.push_back(llvm::MDString::get(VMContext, parm->getName()));
}
Fn->setMetadata("kernel_arg_addr_space",
@@ -1836,13 +1930,13 @@
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
if (D && D->hasAttr<UsedAttr>())
- addUsedGlobal(GV);
+ addUsedOrCompilerUsedGlobal(GV);
if (CodeGenOpts.KeepStaticConsts && D && isa<VarDecl>(D)) {
const auto *VD = cast<VarDecl>(D);
if (VD->getType().isConstQualified() &&
VD->getStorageDuration() == SD_Static)
- addUsedGlobal(GV);
+ addUsedOrCompilerUsedGlobal(GV);
}
}
@@ -1912,6 +2006,8 @@
if (D) {
if (auto *GV = dyn_cast<llvm::GlobalVariable>(GO)) {
+ if (D->hasAttr<RetainAttr>())
+ addUsedGlobal(GV);
if (auto *SA = D->getAttr<PragmaClangBSSSectionAttr>())
GV->addAttribute("bss-section", SA->getName());
if (auto *SA = D->getAttr<PragmaClangDataSectionAttr>())
@@ -1923,6 +2019,8 @@
}
if (auto *F = dyn_cast<llvm::Function>(GO)) {
+ if (D->hasAttr<RetainAttr>())
+ addUsedGlobal(F);
if (auto *SA = D->getAttr<PragmaClangTextSectionAttr>())
if (!D->getAttr<SectionAttr>())
F->addFnAttr("implicit-section-name", SA->getName());
@@ -1954,7 +2052,7 @@
llvm::Function *F,
const CGFunctionInfo &FI) {
const Decl *D = GD.getDecl();
- SetLLVMFunctionAttributes(GD, FI, F);
+ SetLLVMFunctionAttributes(GD, FI, F, /*IsThunk=*/false);
SetLLVMFunctionAttributesForDefinition(D, F);
F->setLinkage(llvm::Function::InternalLinkage);
@@ -2008,7 +2106,8 @@
const auto *FD = cast<FunctionDecl>(GD.getDecl());
if (!IsIncompleteFunction)
- SetLLVMFunctionAttributes(GD, getTypes().arrangeGlobalDeclaration(GD), F);
+ SetLLVMFunctionAttributes(GD, getTypes().arrangeGlobalDeclaration(GD), F,
+ IsThunk);
// Add the Returned attribute for "this", except for iOS 5 and earlier
// where substantial code, including the libstdc++ dylib, was compiled with
@@ -2103,6 +2202,15 @@
LLVMCompilerUsed.emplace_back(GV);
}
+void CodeGenModule::addUsedOrCompilerUsedGlobal(llvm::GlobalValue *GV) {
+ assert((isa<llvm::Function>(GV) || !GV->isDeclaration()) &&
+ "Only globals with definition can force usage.");
+ if (getTriple().isOSBinFormatELF())
+ LLVMCompilerUsed.emplace_back(GV);
+ else
+ LLVMUsed.emplace_back(GV);
+}
+
static void emitUsed(CodeGenModule &CGM, StringRef Name,
std::vector<llvm::WeakTrackingVH> &List) {
// Don't create llvm.used if there is no need.
@@ -2299,8 +2407,10 @@
}
// Emit CUDA/HIP static device variables referenced by host code only.
- if (getLangOpts().CUDA)
- for (auto V : getContext().CUDAStaticDeviceVarReferencedByHost)
+ // Note we should not clear CUDADeviceVarODRUsedByHost since it is still
+ // needed for further handling.
+ if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice)
+ for (const auto *V : getContext().CUDADeviceVarODRUsedByHost)
DeferredDeclsToEmit.push_back(V);
// Stop if we're out of both deferred vtables and deferred declarations.
@@ -2485,29 +2595,28 @@
Annotations.push_back(EmitAnnotateAttr(GV, I, D->getLocation()));
}
-bool CodeGenModule::isInSanitizerBlacklist(SanitizerMask Kind,
- llvm::Function *Fn,
- SourceLocation Loc) const {
- const auto &SanitizerBL = getContext().getSanitizerBlacklist();
- // Blacklist by function name.
- if (SanitizerBL.isBlacklistedFunction(Kind, Fn->getName()))
+bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn,
+ SourceLocation Loc) const {
+ const auto &NoSanitizeL = getContext().getNoSanitizeList();
+ // NoSanitize by function name.
+ if (NoSanitizeL.containsFunction(Kind, Fn->getName()))
return true;
- // Blacklist by location.
+ // NoSanitize by location.
if (Loc.isValid())
- return SanitizerBL.isBlacklistedLocation(Kind, Loc);
+ return NoSanitizeL.containsLocation(Kind, Loc);
// If location is unknown, this may be a compiler-generated function. Assume
// it's located in the main file.
auto &SM = Context.getSourceManager();
if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- return SanitizerBL.isBlacklistedFile(Kind, MainFile->getName());
+ return NoSanitizeL.containsFile(Kind, MainFile->getName());
}
return false;
}
-bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,
- SourceLocation Loc, QualType Ty,
- StringRef Category) const {
- // For now globals can be blacklisted only in ASan and KASan.
+bool CodeGenModule::isInNoSanitizeList(llvm::GlobalVariable *GV,
+ SourceLocation Loc, QualType Ty,
+ StringRef Category) const {
+ // For now globals can be ignored only in ASan and KASan.
const SanitizerMask EnabledAsanMask =
LangOpts.Sanitize.Mask &
(SanitizerKind::Address | SanitizerKind::KernelAddress |
@@ -2515,22 +2624,22 @@
SanitizerKind::MemTag);
if (!EnabledAsanMask)
return false;
- const auto &SanitizerBL = getContext().getSanitizerBlacklist();
- if (SanitizerBL.isBlacklistedGlobal(EnabledAsanMask, GV->getName(), Category))
+ const auto &NoSanitizeL = getContext().getNoSanitizeList();
+ if (NoSanitizeL.containsGlobal(EnabledAsanMask, GV->getName(), Category))
return true;
- if (SanitizerBL.isBlacklistedLocation(EnabledAsanMask, Loc, Category))
+ if (NoSanitizeL.containsLocation(EnabledAsanMask, Loc, Category))
return true;
// Check global type.
if (!Ty.isNull()) {
// Drill down the array types: if global variable of a fixed type is
- // blacklisted, we also don't instrument arrays of them.
+ // not sanitized, we also don't instrument arrays of them.
while (auto AT = dyn_cast<ArrayType>(Ty.getTypePtr()))
Ty = AT->getElementType();
Ty = Ty.getCanonicalType().getUnqualifiedType();
- // We allow to blacklist only record types (classes, structs etc.)
+ // Only record types (classes, structs etc.) are ignored.
if (Ty->isRecordType()) {
std::string TypeStr = Ty.getAsString(getContext().getPrintingPolicy());
- if (SanitizerBL.isBlacklistedType(EnabledAsanMask, TypeStr, Category))
+ if (NoSanitizeL.containsType(EnabledAsanMask, TypeStr, Category))
return true;
}
}
@@ -2607,19 +2716,24 @@
}
bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
+ // In OpenMP 5.0 variables and function may be marked as
+ // device_type(host/nohost) and we should not emit them eagerly unless we sure
+ // that they must be emitted on the host/device. To be sure we need to have
+ // seen a declare target with an explicit mentioning of the function, we know
+ // we have if the level of the declare target attribute is -1. Note that we
+ // check somewhere else if we should emit this at all.
+ if (LangOpts.OpenMP >= 50 && !LangOpts.OpenMPSimd) {
+ llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
+ OMPDeclareTargetDeclAttr::getActiveAttr(Global);
+ if (!ActiveAttr || (*ActiveAttr)->getLevel() != (unsigned)-1)
+ return false;
+ }
+
if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
// Implicit template instantiations may change linkage if they are later
// explicitly instantiated, so they should not be emitted eagerly.
return false;
- // In OpenMP 5.0 function may be marked as device_type(nohost) and we should
- // not emit them eagerly unless we sure that the function must be emitted on
- // the host.
- if (LangOpts.OpenMP >= 50 && !LangOpts.OpenMPSimd &&
- !LangOpts.OpenMPIsDevice &&
- !OMPDeclareTargetDeclAttr::getDeviceType(FD) &&
- !FD->isUsed(/*CheckUsedAttr=*/false) && !FD->isReferenced())
- return false;
}
if (const auto *VD = dyn_cast<VarDecl>(Global))
if (Context.getInlineVariableDefinitionKind(VD) ==
@@ -2739,9 +2853,7 @@
GlobalDecl(cast<FunctionDecl>(VD)),
/*ForVTable=*/false);
else
- Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
- llvm::PointerType::getUnqual(DeclTy),
- nullptr);
+ Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), DeclTy, 0, nullptr);
auto *F = cast<llvm::GlobalValue>(Aliasee);
F->setLinkage(llvm::Function::ExternalWeakLinkage);
@@ -3031,7 +3143,7 @@
if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr<AlwaysInlineAttr>())
return false;
- if (F->hasAttr<DLLImportAttr>()) {
+ if (F->hasAttr<DLLImportAttr>() && !F->hasAttr<AlwaysInlineAttr>()) {
// Check whether it would be safe to inline this dllimport function.
DLLImportFunctionVisitor Visitor;
Visitor.TraverseFunctionDecl(const_cast<FunctionDecl*>(F));
@@ -3141,7 +3253,9 @@
}
void CodeGenModule::emitMultiVersionFunctions() {
- for (GlobalDecl GD : MultiVersionFuncs) {
+ std::vector<GlobalDecl> MVFuncsToEmit;
+ MultiVersionFuncs.swap(MVFuncsToEmit);
+ for (GlobalDecl GD : MVFuncsToEmit) {
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
getContext().forEachMultiversionedFunctionVersion(
@@ -3195,6 +3309,17 @@
CodeGenFunction CGF(*this);
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
}
+
+ // Ensure that any additions to the deferred decls list caused by emitting a
+ // variant are emitted. This can happen when the variant itself is inline and
+ // calls a function without linkage.
+ if (!MVFuncsToEmit.empty())
+ EmitDeferred();
+
+ // Ensure that any additions to the multiversion funcs list from either the
+ // deferred decls or the multiversion functions themselves are emitted.
+ if (!MultiVersionFuncs.empty())
+ emitMultiVersionFunctions();
}
void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
@@ -3269,7 +3394,7 @@
++Index;
}
- llvm::sort(
+ llvm::stable_sort(
Options, [](const CodeGenFunction::MultiVersionResolverOption &LHS,
const CodeGenFunction::MultiVersionResolverOption &RHS) {
return CodeGenFunction::GetX86CpuSupportsMask(LHS.Conditions.Features) >
@@ -3575,9 +3700,19 @@
}
StringRef MangledName = getMangledName(GD);
- return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer,
- /*IsThunk=*/false, llvm::AttributeList(),
- IsForDefinition);
+ auto *F = GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer,
+ /*IsThunk=*/false, llvm::AttributeList(),
+ IsForDefinition);
+ // Returns kernel handle for HIP kernel stub function.
+ if (LangOpts.CUDA && !LangOpts.CUDAIsDevice &&
+ cast<FunctionDecl>(GD.getDecl())->hasAttr<CUDAGlobalAttr>()) {
+ auto *Handle = getCUDARuntime().getKernelHandle(
+ cast<llvm::Function>(F->stripPointerCasts()), GD);
+ if (IsForDefinition)
+ return F;
+ return llvm::ConstantExpr::getBitCast(Handle, Ty->getPointerTo());
+ }
+ return F;
}
static const FunctionDecl *
@@ -3586,8 +3721,8 @@
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
IdentifierInfo &CII = C.Idents.get(Name);
- for (const auto &Result : DC->lookup(&CII))
- if (const auto FD = dyn_cast<FunctionDecl>(Result))
+ for (const auto *Result : DC->lookup(&CII))
+ if (const auto *FD = dyn_cast<FunctionDecl>(Result))
return FD;
if (!C.getLangOpts().CPlusPlus)
@@ -3601,15 +3736,15 @@
for (const auto &N : {"__cxxabiv1", "std"}) {
IdentifierInfo &NS = C.Idents.get(N);
- for (const auto &Result : DC->lookup(&NS)) {
- NamespaceDecl *ND = dyn_cast<NamespaceDecl>(Result);
- if (auto LSD = dyn_cast<LinkageSpecDecl>(Result))
- for (const auto &Result : LSD->lookup(&NS))
+ for (const auto *Result : DC->lookup(&NS)) {
+ const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(Result);
+ if (auto *LSD = dyn_cast<LinkageSpecDecl>(Result))
+ for (const auto *Result : LSD->lookup(&NS))
if ((ND = dyn_cast<NamespaceDecl>(Result)))
break;
if (ND)
- for (const auto &Result : ND->lookup(&CXXII))
+ for (const auto *Result : ND->lookup(&CXXII))
if (const auto *FD = dyn_cast<FunctionDecl>(Result))
return FD;
}
@@ -3680,9 +3815,9 @@
}
/// GetOrCreateLLVMGlobal - If the specified mangled name is not in the module,
-/// create and return an llvm GlobalVariable with the specified type. If there
-/// is something in the module with the specified name, return it potentially
-/// bitcasted to the right type.
+/// create and return an llvm GlobalVariable with the specified type and address
+/// space. If there is something in the module with the specified name, return
+/// it potentially bitcasted to the right type.
///
/// If D is non-null, it specifies a decl that correspond to this. This is used
/// to set the attributes on the global when it is first created.
@@ -3691,9 +3826,8 @@
/// type Ty will be returned, not conversion of a variable with the same
/// mangled name but some other type.
llvm::Constant *
-CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
- llvm::PointerType *Ty,
- const VarDecl *D,
+CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
+ unsigned AddrSpace, const VarDecl *D,
ForDefinition_t IsForDefinition) {
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
@@ -3710,7 +3844,7 @@
if (LangOpts.OpenMP && !LangOpts.OpenMPSimd && D)
getOpenMPRuntime().registerTargetGlobalVariable(D, Entry);
- if (Entry->getType() == Ty)
+ if (Entry->getValueType() == Ty && Entry->getAddressSpace() == AddrSpace)
return Entry;
// If there are two attempts to define the same mangled name, issue an
@@ -3734,22 +3868,24 @@
}
// Make sure the result is of the correct type.
- if (Entry->getType()->getAddressSpace() != Ty->getAddressSpace())
- return llvm::ConstantExpr::getAddrSpaceCast(Entry, Ty);
+ if (Entry->getType()->getAddressSpace() != AddrSpace) {
+ return llvm::ConstantExpr::getAddrSpaceCast(Entry,
+ Ty->getPointerTo(AddrSpace));
+ }
// (If global is requested for a definition, we always need to create a new
// global, not just return a bitcast.)
if (!IsForDefinition)
- return llvm::ConstantExpr::getBitCast(Entry, Ty);
+ return llvm::ConstantExpr::getBitCast(Entry, Ty->getPointerTo(AddrSpace));
}
- auto AddrSpace = GetGlobalVarAddressSpace(D);
- auto TargetAddrSpace = getContext().getTargetAddressSpace(AddrSpace);
+ auto DAddrSpace = GetGlobalVarAddressSpace(D);
+ auto TargetAddrSpace = getContext().getTargetAddressSpace(DAddrSpace);
auto *GV = new llvm::GlobalVariable(
- getModule(), Ty->getElementType(), false,
- llvm::GlobalValue::ExternalLinkage, nullptr, MangledName, nullptr,
- llvm::GlobalVariable::NotThreadLocal, TargetAddrSpace);
+ getModule(), Ty, false, llvm::GlobalValue::ExternalLinkage, nullptr,
+ MangledName, nullptr, llvm::GlobalVariable::NotThreadLocal,
+ TargetAddrSpace);
// If we already created a global with the same mangled name (but different
// type) before, take its name and remove it from its parent.
@@ -3860,17 +3996,23 @@
}
}
- if (GV->isDeclaration())
+ if (GV->isDeclaration()) {
getTargetCodeGenInfo().setTargetAttributes(D, GV, *this);
+ // External HIP managed variables needed to be recorded for transformation
+ // in both device and host compilations.
+ if (getLangOpts().CUDA && D && D->hasAttr<HIPManagedAttr>() &&
+ D->hasExternalStorage())
+ getCUDARuntime().handleVarRegistration(D, *GV);
+ }
LangAS ExpectedAS =
D ? D->getType().getAddressSpace()
: (LangOpts.OpenCL ? LangAS::opencl_global : LangAS::Default);
- assert(getContext().getTargetAddressSpace(ExpectedAS) ==
- Ty->getPointerAddressSpace());
- if (AddrSpace != ExpectedAS)
- return getTargetCodeGenInfo().performAddrSpaceCast(*this, GV, AddrSpace,
- ExpectedAS, Ty);
+ assert(getContext().getTargetAddressSpace(ExpectedAS) == AddrSpace);
+ if (DAddrSpace != ExpectedAS) {
+ return getTargetCodeGenInfo().performAddrSpaceCast(
+ *this, GV, DAddrSpace, ExpectedAS, Ty->getPointerTo(AddrSpace));
+ }
return GV;
}
@@ -3958,11 +4100,10 @@
if (!Ty)
Ty = getTypes().ConvertTypeForMem(ASTTy);
- llvm::PointerType *PTy =
- llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy));
-
StringRef MangledName = getMangledName(D);
- return GetOrCreateLLVMGlobal(MangledName, PTy, D, IsForDefinition);
+ return GetOrCreateLLVMGlobal(MangledName, Ty,
+ getContext().getTargetAddressSpace(ASTTy), D,
+ IsForDefinition);
}
/// CreateRuntimeVariable - Create a new runtime global variable with the
@@ -3970,12 +4111,11 @@
llvm::Constant *
CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty,
StringRef Name) {
- auto PtrTy =
+ auto AddrSpace =
getContext().getLangOpts().OpenCL
- ? llvm::PointerType::get(
- Ty, getContext().getTargetAddressSpace(LangAS::opencl_global))
- : llvm::PointerType::getUnqual(Ty);
- auto *Ret = GetOrCreateLLVMGlobal(Name, PtrTy, nullptr);
+ ? getContext().getTargetAddressSpace(LangAS::opencl_global)
+ : 0;
+ auto *Ret = GetOrCreateLLVMGlobal(Name, Ty, AddrSpace, nullptr);
setDSOLocal(cast<llvm::GlobalValue>(Ret->stripPointerCasts()));
return Ret;
}
@@ -4025,6 +4165,10 @@
return AddrSpace;
}
+ if (LangOpts.SYCLIsDevice &&
+ (!D || D->getType().getAddressSpace() == LangAS::Default))
+ return LangAS::sycl_global;
+
if (LangOpts.CUDA && LangOpts.CUDAIsDevice) {
if (D && D->hasAttr<CUDAConstantAttr>())
return LangAS::cuda_constant;
@@ -4046,10 +4190,12 @@
return getTargetCodeGenInfo().getGlobalVarAddressSpace(*this, D);
}
-LangAS CodeGenModule::getStringLiteralAddressSpace() const {
+LangAS CodeGenModule::GetGlobalConstantAddressSpace() const {
// OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
if (LangOpts.OpenCL)
return LangAS::opencl_constant;
+ if (LangOpts.SYCLIsDevice)
+ return LangAS::sycl_global;
if (auto AS = getTarget().getConstantAddressSpace())
return AS.getValue();
return LangAS::Default;
@@ -4068,13 +4214,12 @@
llvm::GlobalVariable *GV) {
llvm::Constant *Cast = GV;
if (!CGM.getLangOpts().OpenCL) {
- if (auto AS = CGM.getTarget().getConstantAddressSpace()) {
- if (AS != LangAS::Default)
- Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast(
- CGM, GV, AS.getValue(), LangAS::Default,
- GV->getValueType()->getPointerTo(
- CGM.getContext().getTargetAddressSpace(LangAS::Default)));
- }
+ auto AS = CGM.GetGlobalConstantAddressSpace();
+ if (AS != LangAS::Default)
+ Cast = CGM.getTargetCodeGenInfo().performAddrSpaceCast(
+ CGM, GV, AS, LangAS::Default,
+ GV->getValueType()->getPointerTo(
+ CGM.getContext().getTargetAddressSpace(LangAS::Default)));
}
return Cast;
}
@@ -4164,7 +4309,7 @@
OpenMPRuntime->emitTargetGlobalVariable(D))
return;
- llvm::Constant *Init = nullptr;
+ llvm::TrackingVH<llvm::Constant> Init;
bool NeedsGlobalCtor = false;
bool NeedsGlobalDtor =
D->needsDestruction(getContext()) == QualType::DK_cxx_destructor;
@@ -4181,22 +4326,20 @@
getLangOpts().CUDAIsDevice && D->hasAttr<CUDASharedAttr>();
// Shadows of initialized device-side global variables are also left
// undefined.
+ // Managed Variables should be initialized on both host side and device side.
bool IsCUDAShadowVar =
!getLangOpts().CUDAIsDevice && !D->hasAttr<HIPManagedAttr>() &&
(D->hasAttr<CUDAConstantAttr>() || D->hasAttr<CUDADeviceAttr>() ||
D->hasAttr<CUDASharedAttr>());
bool IsCUDADeviceShadowVar =
- getLangOpts().CUDAIsDevice &&
+ getLangOpts().CUDAIsDevice && !D->hasAttr<HIPManagedAttr>() &&
(D->getType()->isCUDADeviceBuiltinSurfaceType() ||
- D->getType()->isCUDADeviceBuiltinTextureType() ||
- D->hasAttr<HIPManagedAttr>());
- // HIP pinned shadow of initialized host-side global variables are also
- // left undefined.
+ D->getType()->isCUDADeviceBuiltinTextureType());
if (getLangOpts().CUDA &&
(IsCUDASharedVar || IsCUDAShadowVar || IsCUDADeviceShadowVar))
- Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy));
+ Init = llvm::UndefValue::get(getTypes().ConvertTypeForMem(ASTTy));
else if (D->hasAttr<LoaderUninitializedAttr>())
- Init = llvm::UndefValue::get(getTypes().ConvertType(ASTTy));
+ Init = llvm::UndefValue::get(getTypes().ConvertTypeForMem(ASTTy));
else if (!InitExpr) {
// This is a tentative definition; tentative definitions are
// implicitly initialized with { 0 }.
@@ -4212,9 +4355,8 @@
} else {
initializedGlobalDecl = GlobalDecl(D);
emitter.emplace(*this);
- Init = emitter->tryEmitForInitializer(*InitDecl);
-
- if (!Init) {
+ llvm::Constant *Initializer = emitter->tryEmitForInitializer(*InitDecl);
+ if (!Initializer) {
QualType T = InitExpr->getType();
if (D->getType()->isReferenceType())
T = D->getType();
@@ -4227,6 +4369,7 @@
Init = llvm::UndefValue::get(getTypes().ConvertType(T));
}
} else {
+ Init = Initializer;
// We don't need an initializer, so remove the entry for the delayed
// initializer position (just in case this entry was delayed) if we
// also don't need to register a destructor.
@@ -4268,7 +4411,8 @@
// Replace all uses of the old global with the new global
llvm::Constant *NewPtrForOldDecl =
- llvm::ConstantExpr::getBitCast(GV, Entry->getType());
+ llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(GV,
+ Entry->getType());
Entry->replaceAllUsesWith(NewPtrForOldDecl);
// Erase the old global, since it is no longer used.
@@ -4297,60 +4441,9 @@
(D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>()))
GV->setExternallyInitialized(true);
} else {
- // Host-side shadows of external declarations of device-side
- // global variables become internal definitions. These have to
- // be internal in order to prevent name conflicts with global
- // host variables with the same name in a different TUs.
- if (D->hasAttr<CUDADeviceAttr>() || D->hasAttr<CUDAConstantAttr>()) {
- Linkage = llvm::GlobalValue::InternalLinkage;
- // Shadow variables and their properties must be registered with CUDA
- // runtime. Skip Extern global variables, which will be registered in
- // the TU where they are defined.
- //
- // Don't register a C++17 inline variable. The local symbol can be
- // discarded and referencing a discarded local symbol from outside the
- // comdat (__cuda_register_globals) is disallowed by the ELF spec.
- // TODO: Reject __device__ constexpr and __device__ inline in Sema.
- if (!D->hasExternalStorage() && !D->isInline())
- getCUDARuntime().registerDeviceVar(D, *GV, !D->hasDefinition(),
- D->hasAttr<CUDAConstantAttr>());
- } else if (D->hasAttr<CUDASharedAttr>()) {
- // __shared__ variables are odd. Shadows do get created, but
- // they are not registered with the CUDA runtime, so they
- // can't really be used to access their device-side
- // counterparts. It's not clear yet whether it's nvcc's bug or
- // a feature, but we've got to do the same for compatibility.
- Linkage = llvm::GlobalValue::InternalLinkage;
- } else if (D->getType()->isCUDADeviceBuiltinSurfaceType() ||
- D->getType()->isCUDADeviceBuiltinTextureType()) {
- // Builtin surfaces and textures and their template arguments are
- // also registered with CUDA runtime.
- Linkage = llvm::GlobalValue::InternalLinkage;
- const ClassTemplateSpecializationDecl *TD =
- cast<ClassTemplateSpecializationDecl>(
- D->getType()->getAs<RecordType>()->getDecl());
- const TemplateArgumentList &Args = TD->getTemplateArgs();
- if (TD->hasAttr<CUDADeviceBuiltinSurfaceTypeAttr>()) {
- assert(Args.size() == 2 &&
- "Unexpected number of template arguments of CUDA device "
- "builtin surface type.");
- auto SurfType = Args[1].getAsIntegral();
- if (!D->hasExternalStorage())
- getCUDARuntime().registerDeviceSurf(D, *GV, !D->hasDefinition(),
- SurfType.getSExtValue());
- } else {
- assert(Args.size() == 3 &&
- "Unexpected number of template arguments of CUDA device "
- "builtin texture type.");
- auto TexType = Args[1].getAsIntegral();
- auto Normalized = Args[2].getAsIntegral();
- if (!D->hasExternalStorage())
- getCUDARuntime().registerDeviceTex(D, *GV, !D->hasDefinition(),
- TexType.getSExtValue(),
- Normalized.getZExtValue());
- }
- }
+ getCUDARuntime().internalizeDeviceSideVar(D, Linkage);
}
+ getCUDARuntime().handleVarRegistration(D, *GV);
}
GV->setInitializer(Init);
@@ -4436,9 +4529,8 @@
if (getCodeGenOpts().hasReducedDebugInfo()) {
QualType ASTTy = D->getType();
llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
- llvm::PointerType *PTy =
- llvm::PointerType::get(Ty, getContext().getTargetAddressSpace(ASTTy));
- llvm::Constant *GV = GetOrCreateLLVMGlobal(D->getName(), PTy, D);
+ llvm::Constant *GV = GetOrCreateLLVMGlobal(
+ D->getName(), Ty, getContext().getTargetAddressSpace(ASTTy), D);
DI->EmitExternalVariable(
cast<llvm::GlobalVariable>(GV->stripPointerCasts()), D);
}
@@ -4610,7 +4702,6 @@
llvm::Type *newRetTy = newFn->getReturnType();
SmallVector<llvm::Value*, 4> newArgs;
- SmallVector<llvm::OperandBundleDef, 1> newBundles;
for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end();
ui != ue; ) {
@@ -4667,6 +4758,7 @@
newArgs.append(callSite->arg_begin(), callSite->arg_begin() + argNo);
// Copy over any operand bundles.
+ SmallVector<llvm::OperandBundleDef, 1> newBundles;
callSite->getOperandBundlesAsDefs(newBundles);
llvm::CallBase *newCall;
@@ -4810,8 +4902,7 @@
/*ForVTable=*/false);
LT = getFunctionLinkage(GD);
} else {
- Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
- llvm::PointerType::getUnqual(DeclTy),
+ Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), DeclTy, 0,
/*D=*/nullptr);
if (const auto *VD = dyn_cast<VarDecl>(GD.getDecl()))
LT = getLLVMLinkageVarDefinition(VD, D->getType().isConstQualified());
@@ -5027,7 +5118,7 @@
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
const VarDecl *VD = nullptr;
- for (const auto &Result : DC->lookup(&II))
+ for (const auto *Result : DC->lookup(&II))
if ((VD = dyn_cast<VarDecl>(Result)))
break;
@@ -5239,7 +5330,7 @@
CodeGenModule &CGM, StringRef GlobalName,
CharUnits Alignment) {
unsigned AddrSpace = CGM.getContext().getTargetAddressSpace(
- CGM.getStringLiteralAddressSpace());
+ CGM.GetGlobalConstantAddressSpace());
llvm::Module &M = CGM.getModule();
// Create a global variable for this string
@@ -5366,8 +5457,21 @@
CharUnits Align = getContext().getTypeAlignInChars(MaterializedType);
- if (llvm::Constant *Slot = MaterializedGlobalTemporaryMap[E])
- return ConstantAddress(Slot, Align);
+ auto InsertResult = MaterializedGlobalTemporaryMap.insert({E, nullptr});
+ if (!InsertResult.second) {
+ // We've seen this before: either we already created it or we're in the
+ // process of doing so.
+ if (!InsertResult.first->second) {
+ // We recursively re-entered this function, probably during emission of
+ // the initializer. Create a placeholder. We'll clean this up in the
+ // outer call, at the end of this function.
+ llvm::Type *Type = getTypes().ConvertTypeForMem(MaterializedType);
+ InsertResult.first->second = new llvm::GlobalVariable(
+ getModule(), Type, false, llvm::GlobalVariable::InternalLinkage,
+ nullptr);
+ }
+ return ConstantAddress(InsertResult.first->second, Align);
+ }
// FIXME: If an externally-visible declaration extends multiple temporaries,
// we need to give each temporary the same name in every translation unit (and
@@ -5446,7 +5550,17 @@
*this, GV, AddrSpace, LangAS::Default,
Type->getPointerTo(
getContext().getTargetAddressSpace(LangAS::Default)));
- MaterializedGlobalTemporaryMap[E] = CV;
+
+ // Update the map with the new temporary. If we created a placeholder above,
+ // replace it with the new global now.
+ llvm::Constant *&Entry = MaterializedGlobalTemporaryMap[E];
+ if (Entry) {
+ Entry->replaceAllUsesWith(
+ llvm::ConstantExpr::getBitCast(CV, Entry->getType()));
+ llvm::cast<llvm::GlobalVariable>(Entry)->eraseFromParent();
+ }
+ Entry = CV;
+
return ConstantAddress(CV, Align);
}
@@ -5649,6 +5763,10 @@
if (CGDebugInfo *DI = getModuleDebugInfo())
DI->EmitUsingDecl(cast<UsingDecl>(*D));
break;
+ case Decl::UsingEnum: // using enum X; [C++]
+ if (CGDebugInfo *DI = getModuleDebugInfo())
+ DI->EmitUsingEnumDecl(cast<UsingEnumDecl>(*D));
+ break;
case Decl::NamespaceAlias:
if (CGDebugInfo *DI = getModuleDebugInfo())
DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(*D));
@@ -5747,6 +5865,9 @@
// File-scope asm is ignored during device-side OpenMP compilation.
if (LangOpts.OpenMPIsDevice)
break;
+ // File-scope asm is ignored during device-side SYCL compilation.
+ if (LangOpts.SYCLIsDevice)
+ break;
auto *AD = cast<FileScopeAsmDecl>(D);
getModule().appendModuleInlineAsm(AD->getAsmString()->getString());
break;
@@ -5804,6 +5925,7 @@
break;
case Decl::OMPAllocate:
+ EmitOMPAllocateDecl(cast<OMPAllocateDecl>(D));
break;
case Decl::OMPDeclareReduction:
@@ -5973,7 +6095,7 @@
IdentifierInfo *Name = I.first;
llvm::GlobalValue *Val = I.second;
if (Val && !getModule().getNamedValue(Name->getName()))
- addUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val));
+ addCompilerUsedGlobal(llvm::GlobalAlias::create(Name->getName(), Val));
}
}
@@ -6222,9 +6344,8 @@
llvm::Constant *C = ConstantEmitter(CGF).emitAbstract(E, E->getType());
auto *SamplerT = getOpenCLRuntime().getSamplerType(E->getType().getTypePtr());
auto *FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false);
- auto *Call = CGF.Builder.CreateCall(
+ auto *Call = CGF.EmitRuntimeCall(
CreateRuntimeFunction(FTy, "__translate_sampler_initializer"), {C});
- Call->setCallingConv(Call->getCalledFunction()->getCallingConv());
return Call;
}
@@ -6324,3 +6445,8 @@
}
return false;
}
+
+void CodeGenModule::printPostfixForExternalizedStaticVar(
+ llvm::raw_ostream &OS) const {
+ OS << ".static." << getContext().getCUIDHash();
+}
diff --git a/src/llvm-project/clang/lib/CodeGen/CodeGenModule.h b/src/llvm-project/clang/lib/CodeGen/CodeGenModule.h
index 618e2f8..47dc6f4 100644
--- a/src/llvm-project/clang/lib/CodeGen/CodeGenModule.h
+++ b/src/llvm-project/clang/lib/CodeGen/CodeGenModule.h
@@ -25,9 +25,10 @@
#include "clang/Basic/ABI.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
-#include "clang/Basic/SanitizerBlacklist.h"
+#include "clang/Basic/NoSanitizeList.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/XRayLists.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -72,7 +73,6 @@
class LangOptions;
class CodeGenOptions;
class HeaderSearchOptions;
-class PreprocessorOptions;
class DiagnosticsEngine;
class AnnotateAttr;
class CXXDestructorDecl;
@@ -103,17 +103,17 @@
ForDefinition = true
};
-struct OrderGlobalInits {
+struct OrderGlobalInitsOrStermFinalizers {
unsigned int priority;
unsigned int lex_order;
- OrderGlobalInits(unsigned int p, unsigned int l)
+ OrderGlobalInitsOrStermFinalizers(unsigned int p, unsigned int l)
: priority(p), lex_order(l) {}
- bool operator==(const OrderGlobalInits &RHS) const {
+ bool operator==(const OrderGlobalInitsOrStermFinalizers &RHS) const {
return priority == RHS.priority && lex_order == RHS.lex_order;
}
- bool operator<(const OrderGlobalInits &RHS) const {
+ bool operator<(const OrderGlobalInitsOrStermFinalizers &RHS) const {
return std::tie(priority, lex_order) <
std::tie(RHS.priority, RHS.lex_order);
}
@@ -210,6 +210,9 @@
/// void clang.arc.use(...);
llvm::Function *clang_arc_use;
+
+ /// void clang.arc.noop.use(...);
+ llvm::Function *clang_arc_noop_use;
};
/// This class records statistics on instrumentation based profiling.
@@ -308,6 +311,7 @@
const TargetInfo &Target;
std::unique_ptr<CGCXXABI> ABI;
llvm::LLVMContext &VMContext;
+ std::string ModuleNameHash = "";
std::unique_ptr<CodeGenTBAA> TBAA;
@@ -453,7 +457,8 @@
/// that we don't re-emit the initializer.
llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
- typedef std::pair<OrderGlobalInits, llvm::Function*> GlobalInitData;
+ typedef std::pair<OrderGlobalInitsOrStermFinalizers, llvm::Function *>
+ GlobalInitData;
struct GlobalInitPriorityCmp {
bool operator()(const GlobalInitData &LHS,
@@ -469,10 +474,26 @@
/// Global destructor functions and arguments that need to run on termination.
/// When UseSinitAndSterm is set, it instead contains sterm finalizer
/// functions, which also run on unloading a shared library.
- std::vector<
- std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH, llvm::Constant *>>
+ typedef std::tuple<llvm::FunctionType *, llvm::WeakTrackingVH,
+ llvm::Constant *>
+ CXXGlobalDtorsOrStermFinalizer_t;
+ SmallVector<CXXGlobalDtorsOrStermFinalizer_t, 8>
CXXGlobalDtorsOrStermFinalizers;
+ typedef std::pair<OrderGlobalInitsOrStermFinalizers, llvm::Function *>
+ StermFinalizerData;
+
+ struct StermFinalizerPriorityCmp {
+ bool operator()(const StermFinalizerData &LHS,
+ const StermFinalizerData &RHS) const {
+ return LHS.first.priority < RHS.first.priority;
+ }
+ };
+
+ /// Global variables with sterm finalizers whose order of initialization is
+ /// set by init_priority attribute.
+ SmallVector<StermFinalizerData, 8> PrioritizedCXXStermFinalizers;
+
/// The complete set of modules that has been imported.
llvm::SetVector<clang::Module *> ImportedModules;
@@ -583,6 +604,8 @@
/// Return true iff an Objective-C runtime has been configured.
bool hasObjCRuntime() { return !!ObjCRuntime; }
+ const std::string &getModuleNameHash() const { return ModuleNameHash; }
+
/// Return a reference to the configured OpenCL runtime.
CGOpenCLRuntime &getOpenCLRuntime() {
assert(OpenCLRuntime != nullptr);
@@ -832,6 +855,13 @@
/// space, target-specific global or constant address space may be returned.
LangAS GetGlobalVarAddressSpace(const VarDecl *D);
+ /// Return the AST address space of constant literal, which is used to emit
+ /// the constant literal as global variable in LLVM IR.
+ /// Note: This is not necessarily the address space of the constant literal
+ /// in AST. For address space agnostic language, e.g. C++, constant literal
+ /// in AST is always in default address space.
+ LangAS GetGlobalConstantAddressSpace() const;
+
/// Return the llvm::Constant for the address of the given global variable.
/// If Ty is non-null and if the global doesn't exist, then it will be created
/// with the specified type instead of whatever the normal requested type
@@ -843,13 +873,6 @@
ForDefinition_t IsForDefinition
= NotForDefinition);
- /// Return the AST address space of string literal, which is used to emit
- /// the string literal as global variable in LLVM IR.
- /// Note: This is not necessarily the address space of the string literal
- /// in AST. For address space agnostic language, e.g. C++, string literal
- /// in AST is always in default address space.
- LangAS getStringLiteralAddressSpace() const;
-
/// Return the address of the given function. If Ty is non-null, then this
/// function will use the specified type if it has to create it.
llvm::Constant *GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty = nullptr,
@@ -1051,6 +1074,9 @@
/// Add a global to a list to be added to the llvm.compiler.used metadata.
void addCompilerUsedGlobal(llvm::GlobalValue *GV);
+ /// Add a global to a list to be added to the llvm.compiler.used metadata.
+ void addUsedOrCompilerUsedGlobal(llvm::GlobalValue *GV);
+
/// Add a destructor and object to add to the C++ global destructor function.
void AddCXXDtorEntry(llvm::FunctionCallee DtorFn, llvm::Constant *Object) {
CXXGlobalDtorsOrStermFinalizers.emplace_back(DtorFn.getFunctionType(),
@@ -1069,6 +1095,14 @@
AddGlobalDtor(StermFinalizer, Priority);
}
+ void AddCXXPrioritizedStermFinalizerEntry(llvm::Function *StermFinalizer,
+ int Priority) {
+ OrderGlobalInitsOrStermFinalizers Key(Priority,
+ PrioritizedCXXStermFinalizers.size());
+ PrioritizedCXXStermFinalizers.push_back(
+ std::make_pair(Key, StermFinalizer));
+ }
+
/// Create or return a runtime function declaration with the specified type
/// and name. If \p AssumeConvergent is true, the call will have the
/// convergent attribute added.
@@ -1130,7 +1164,7 @@
/// Set the LLVM function attributes (sext, zext, etc).
void SetLLVMFunctionAttributes(GlobalDecl GD, const CGFunctionInfo &Info,
- llvm::Function *F);
+ llvm::Function *F, bool IsThunk);
/// Set the LLVM function attributes which only apply to a function
/// definition.
@@ -1166,7 +1200,7 @@
void ConstructAttributeList(StringRef Name, const CGFunctionInfo &Info,
CGCalleeInfo CalleeInfo,
llvm::AttributeList &Attrs, unsigned &CallingConv,
- bool AttrOnCallSite);
+ bool AttrOnCallSite, bool IsThunk);
/// Adds attributes to F according to our CodeGenOptions and LangOptions, as
/// though we had emitted it ourselves. We remove any attributes on F that
@@ -1264,12 +1298,11 @@
/// annotations are emitted during finalization of the LLVM code.
void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
- bool isInSanitizerBlacklist(SanitizerMask Kind, llvm::Function *Fn,
- SourceLocation Loc) const;
+ bool isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn,
+ SourceLocation Loc) const;
- bool isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc,
- QualType Ty,
- StringRef Category = StringRef()) const;
+ bool isInNoSanitizeList(llvm::GlobalVariable *GV, SourceLocation Loc,
+ QualType Ty, StringRef Category = StringRef()) const;
/// Imbue XRay attributes to a function, applying the always/never attribute
/// lists in the process. Returns true if we did imbue attributes this way,
@@ -1323,6 +1356,10 @@
/// \param D Requires declaration
void EmitOMPRequiresDecl(const OMPRequiresDecl *D);
+ /// Emit a code for the allocate directive.
+ /// \param D The allocate declaration
+ void EmitOMPAllocateDecl(const OMPAllocateDecl *D);
+
/// Returns whether the given record has hidden LTO visibility and therefore
/// may participate in (single-module) CFI and whole-program vtable
/// optimization.
@@ -1369,6 +1406,10 @@
void CreateFunctionTypeMetadataForIcall(const FunctionDecl *FD,
llvm::Function *F);
+ /// Whether this function's return type has no side effects, and thus may
+ /// be trivially discarded if it is unused.
+ bool MayDropFunctionReturn(const ASTContext &Context, QualType ReturnType);
+
/// Returns whether this module needs the "all-vtables" type identifier.
bool NeedAllVtablesTypeId() const;
@@ -1420,6 +1461,10 @@
TBAAAccessInfo *TBAAInfo = nullptr);
bool stopAutoInit();
+ /// Print the postfix for externalized static variable for single source
+ /// offloading languages CUDA and HIP.
+ void printPostfixForExternalizedStaticVar(llvm::raw_ostream &OS) const;
+
private:
llvm::Constant *GetOrCreateLLVMFunction(
StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable,
@@ -1432,11 +1477,10 @@
const FunctionDecl *FD);
void UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD);
- llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName,
- llvm::PointerType *PTy,
- const VarDecl *D,
- ForDefinition_t IsForDefinition
- = NotForDefinition);
+ llvm::Constant *
+ GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
+ unsigned AddrSpace, const VarDecl *D,
+ ForDefinition_t IsForDefinition = NotForDefinition);
bool GetCPUAndFeaturesAttributes(GlobalDecl GD,
llvm::AttrBuilder &AttrBuilder);
diff --git a/src/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp b/src/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp
index 08ae877..d828ac0 100644
--- a/src/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -811,10 +811,10 @@
if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base)
return;
+ CGM.ClearUnusedCoverageMapping(D);
if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
return;
- CGM.ClearUnusedCoverageMapping(D);
setFuncName(Fn);
mapRegionCounters(D);
@@ -962,6 +962,12 @@
makeArrayRef(Args));
}
+void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {
+ if (CGM.getCodeGenOpts().hasProfileClangInstr())
+ M.addModuleFlag(llvm::Module::Warning, "EnableValueProfiling",
+ uint32_t(EnableValueProfiling));
+}
+
// This method either inserts a call to the profile run-time during
// instrumentation or puts profile data into metadata for PGO use.
void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
diff --git a/src/llvm-project/clang/lib/CodeGen/CodeGenPGO.h b/src/llvm-project/clang/lib/CodeGen/CodeGenPGO.h
index 906c5e4..f740692 100644
--- a/src/llvm-project/clang/lib/CodeGen/CodeGenPGO.h
+++ b/src/llvm-project/clang/lib/CodeGen/CodeGenPGO.h
@@ -87,6 +87,10 @@
// Insert instrumentation or attach profile metadata at value sites
void valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
llvm::Instruction *ValueSite, llvm::Value *ValuePtr);
+
+ // Set a module flag indicating if value profiling is enabled.
+ void setValueProfilingFlag(llvm::Module &M);
+
private:
void setFuncName(llvm::Function *Fn);
void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);
diff --git a/src/llvm-project/clang/lib/CodeGen/CodeGenTypes.cpp b/src/llvm-project/clang/lib/CodeGen/CodeGenTypes.cpp
index 7537ac1..9cb4294 100644
--- a/src/llvm-project/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -601,7 +601,16 @@
llvm::FixedVectorType::get(ConvertType(Context.BoolTy), Size); \
break;
#include "clang/Basic/PPCTypes.def"
- case BuiltinType::Dependent:
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
+ {
+ ASTContext::BuiltinVectorTypeInfo Info =
+ Context.getBuiltinVectorTypeInfo(cast<BuiltinType>(Ty));
+ return llvm::ScalableVectorType::get(ConvertType(Info.ElementType),
+ Info.EC.getKnownMinValue() *
+ Info.NumVectors);
+ }
+ case BuiltinType::Dependent:
#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) \
case BuiltinType::Id:
diff --git a/src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp b/src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp
index 5c25c20..8a11da6 100644
--- a/src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -104,26 +104,21 @@
/// The region's ending location.
Optional<SourceLocation> LocEnd;
- /// Whether this region should be emitted after its parent is emitted.
- bool DeferRegion;
-
/// Whether this region is a gap region. The count from a gap region is set
/// as the line execution count if there are no other regions on the line.
bool GapRegion;
public:
SourceMappingRegion(Counter Count, Optional<SourceLocation> LocStart,
- Optional<SourceLocation> LocEnd, bool DeferRegion = false,
- bool GapRegion = false)
- : Count(Count), LocStart(LocStart), LocEnd(LocEnd),
- DeferRegion(DeferRegion), GapRegion(GapRegion) {}
+ Optional<SourceLocation> LocEnd, bool GapRegion = false)
+ : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {
+ }
SourceMappingRegion(Counter Count, Optional<Counter> FalseCount,
Optional<SourceLocation> LocStart,
- Optional<SourceLocation> LocEnd, bool DeferRegion = false,
- bool GapRegion = false)
+ Optional<SourceLocation> LocEnd, bool GapRegion = false)
: Count(Count), FalseCount(FalseCount), LocStart(LocStart),
- LocEnd(LocEnd), DeferRegion(DeferRegion), GapRegion(GapRegion) {}
+ LocEnd(LocEnd), GapRegion(GapRegion) {}
const Counter &getCounter() const { return Count; }
@@ -155,10 +150,6 @@
return *LocEnd;
}
- bool isDeferred() const { return DeferRegion; }
-
- void setDeferred(bool Deferred) { DeferRegion = Deferred; }
-
bool isGap() const { return GapRegion; }
void setGap(bool Gap) { GapRegion = Gap; }
@@ -544,10 +535,6 @@
/// A stack of currently live regions.
std::vector<SourceMappingRegion> RegionStack;
- /// The currently deferred region: its end location and count can be set once
- /// its parent has been popped from the region stack.
- Optional<SourceMappingRegion> DeferredRegion;
-
CounterExpressionBuilder Builder;
/// A location in the most recently visited file or macro.
@@ -556,8 +543,11 @@
/// expressions cross file or macro boundaries.
SourceLocation MostRecentLocation;
- /// Location of the last terminated region.
- Optional<std::pair<SourceLocation, size_t>> LastTerminatedRegion;
+ /// Whether the visitor at a terminate statement.
+ bool HasTerminateStmt = false;
+
+ /// Gap region counter after terminate statement.
+ Counter GapRegionCounter;
/// Return a counter for the subtraction of \c RHS from \c LHS
Counter subtractCounters(Counter LHS, Counter RHS) {
@@ -590,77 +580,13 @@
if (StartLoc && !FalseCount.hasValue()) {
MostRecentLocation = *StartLoc;
- completeDeferred(Count, MostRecentLocation);
}
- RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc,
- FalseCount.hasValue());
+ RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc);
return RegionStack.size() - 1;
}
- /// Complete any pending deferred region by setting its end location and
- /// count, and then pushing it onto the region stack.
- size_t completeDeferred(Counter Count, SourceLocation DeferredEndLoc) {
- size_t Index = RegionStack.size();
- if (!DeferredRegion)
- return Index;
-
- // Consume the pending region.
- SourceMappingRegion DR = DeferredRegion.getValue();
- DeferredRegion = None;
-
- // If the region ends in an expansion, find the expansion site.
- FileID StartFile = SM.getFileID(DR.getBeginLoc());
- if (SM.getFileID(DeferredEndLoc) != StartFile) {
- if (isNestedIn(DeferredEndLoc, StartFile)) {
- do {
- DeferredEndLoc = getIncludeOrExpansionLoc(DeferredEndLoc);
- } while (StartFile != SM.getFileID(DeferredEndLoc));
- } else {
- return Index;
- }
- }
-
- // The parent of this deferred region ends where the containing decl ends,
- // so the region isn't useful.
- if (DR.getBeginLoc() == DeferredEndLoc)
- return Index;
-
- // If we're visiting statements in non-source order (e.g switch cases or
- // a loop condition) we can't construct a sensible deferred region.
- if (!SpellingRegion(SM, DR.getBeginLoc(), DeferredEndLoc).isInSourceOrder())
- return Index;
-
- DR.setGap(true);
- DR.setCounter(Count);
- DR.setEndLoc(DeferredEndLoc);
- handleFileExit(DeferredEndLoc);
- RegionStack.push_back(DR);
- return Index;
- }
-
- /// Complete a deferred region created after a terminated region at the
- /// top-level.
- void completeTopLevelDeferredRegion(Counter Count,
- SourceLocation DeferredEndLoc) {
- if (DeferredRegion || !LastTerminatedRegion)
- return;
-
- if (LastTerminatedRegion->second != RegionStack.size())
- return;
-
- SourceLocation Start = LastTerminatedRegion->first;
- if (SM.getFileID(Start) != SM.getMainFileID())
- return;
-
- SourceMappingRegion DR = RegionStack.back();
- DR.setStartLoc(Start);
- DR.setDeferred(false);
- DeferredRegion = DR;
- completeDeferred(Count, DeferredEndLoc);
- }
-
size_t locationDepth(SourceLocation Loc) {
size_t Depth = 0;
while (Loc.isValid()) {
@@ -676,7 +602,6 @@
/// function's \c SourceRegions.
void popRegions(size_t ParentIndex) {
assert(RegionStack.size() >= ParentIndex && "parent not in stack");
- bool ParentOfDeferredRegion = false;
while (RegionStack.size() > ParentIndex) {
SourceMappingRegion &Region = RegionStack.back();
if (Region.hasStartLoc()) {
@@ -746,32 +671,9 @@
assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
assert(SpellingRegion(SM, Region).isInSourceOrder());
SourceRegions.push_back(Region);
-
- if (ParentOfDeferredRegion) {
- ParentOfDeferredRegion = false;
-
- // If there's an existing deferred region, keep the old one, because
- // it means there are two consecutive returns (or a similar pattern).
- if (!DeferredRegion.hasValue() &&
- // File IDs aren't gathered within macro expansions, so it isn't
- // useful to try and create a deferred region inside of one.
- !EndLoc.isMacroID())
- DeferredRegion =
- SourceMappingRegion(Counter::getZero(), EndLoc, None);
}
- } else if (Region.isDeferred()) {
- assert(!ParentOfDeferredRegion && "Consecutive deferred regions");
- ParentOfDeferredRegion = true;
- }
RegionStack.pop_back();
-
- // If the zero region pushed after the last terminated region no longer
- // exists, clear its cached information.
- if (LastTerminatedRegion &&
- RegionStack.size() < LastTerminatedRegion->second)
- LastTerminatedRegion = None;
}
- assert(!ParentOfDeferredRegion && "Deferred region with no parent");
}
/// Return the currently active region.
@@ -955,8 +857,6 @@
handleFileExit(StartLoc);
if (!Region.hasStartLoc())
Region.setStartLoc(StartLoc);
-
- completeDeferred(Region.getCounter(), StartLoc);
}
/// Mark \c S as a terminator, starting a zero region.
@@ -967,30 +867,56 @@
if (!Region.hasEndLoc())
Region.setEndLoc(EndLoc);
pushRegion(Counter::getZero());
- auto &ZeroRegion = getRegion();
- ZeroRegion.setDeferred(true);
- LastTerminatedRegion = {EndLoc, RegionStack.size()};
+ HasTerminateStmt = true;
}
/// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
Optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
SourceLocation BeforeLoc) {
+ // If AfterLoc is in function-like macro, use the right parenthesis
+ // location.
+ if (AfterLoc.isMacroID()) {
+ FileID FID = SM.getFileID(AfterLoc);
+ const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
+ if (EI->isFunctionMacroExpansion())
+ AfterLoc = EI->getExpansionLocEnd();
+ }
+
+ size_t StartDepth = locationDepth(AfterLoc);
+ size_t EndDepth = locationDepth(BeforeLoc);
+ while (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) {
+ bool UnnestStart = StartDepth >= EndDepth;
+ bool UnnestEnd = EndDepth >= StartDepth;
+ if (UnnestEnd) {
+ assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
+ BeforeLoc));
+
+ BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
+ assert(BeforeLoc.isValid());
+ EndDepth--;
+ }
+ if (UnnestStart) {
+ assert(SM.isWrittenInSameFile(AfterLoc,
+ getEndOfFileOrMacro(AfterLoc)));
+
+ AfterLoc = getIncludeOrExpansionLoc(AfterLoc);
+ assert(AfterLoc.isValid());
+ AfterLoc = getPreciseTokenLocEnd(AfterLoc);
+ assert(AfterLoc.isValid());
+ StartDepth--;
+ }
+ }
+ AfterLoc = getPreciseTokenLocEnd(AfterLoc);
// If the start and end locations of the gap are both within the same macro
// file, the range may not be in source order.
if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
return None;
- if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc))
+ if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc) ||
+ !SpellingRegion(SM, AfterLoc, BeforeLoc).isInSourceOrder())
return None;
return {{AfterLoc, BeforeLoc}};
}
- /// Find the source range after \p AfterStmt and before \p BeforeStmt.
- Optional<SourceRange> findGapAreaBetween(const Stmt *AfterStmt,
- const Stmt *BeforeStmt) {
- return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)),
- getStart(BeforeStmt));
- }
-
/// Emit a gap region between \p StartLoc and \p EndLoc with the given count.
void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc,
Counter Count) {
@@ -1015,15 +941,13 @@
CoverageMappingModuleGen &CVM,
llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM,
const LangOptions &LangOpts)
- : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
- DeferredRegion(None) {}
+ : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap) {}
/// Write the mapping data to the output stream
void write(llvm::raw_ostream &OS) {
llvm::SmallVector<unsigned, 8> VirtualFileMapping;
gatherFileIDs(VirtualFileMapping);
SourceRegionFilter Filter = emitExpansionRegions();
- assert(!DeferredRegion && "Deferred region never completed");
emitSourceRegions(Filter);
gatherSkippedRegions();
@@ -1038,15 +962,32 @@
void VisitStmt(const Stmt *S) {
if (S->getBeginLoc().isValid())
extendRegion(S);
+ const Stmt *LastStmt = nullptr;
+ bool SaveTerminateStmt = HasTerminateStmt;
+ HasTerminateStmt = false;
+ GapRegionCounter = Counter::getZero();
for (const Stmt *Child : S->children())
- if (Child)
+ if (Child) {
+ // If last statement contains terminate statements, add a gap area
+ // between the two statements. Skipping attributed statements, because
+ // they don't have valid start location.
+ if (LastStmt && HasTerminateStmt && !dyn_cast<AttributedStmt>(Child)) {
+ auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
+ if (Gap)
+ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
+ GapRegionCounter);
+ SaveTerminateStmt = true;
+ HasTerminateStmt = false;
+ }
this->Visit(Child);
+ LastStmt = Child;
+ }
+ if (SaveTerminateStmt)
+ HasTerminateStmt = true;
handleFileExit(getEnd(S));
}
void VisitDecl(const Decl *D) {
- assert(!DeferredRegion && "Deferred region never completed");
-
Stmt *Body = D->getBody();
// Do not propagate region counts into system headers.
@@ -1064,11 +1005,6 @@
propagateCounts(getRegionCounter(Body), Body,
/*VisitChildren=*/!Defaulted);
assert(RegionStack.empty() && "Regions entered but never exited");
-
- // Discard the last uncompleted deferred region in a decl, if one exists.
- // This prevents lines at the end of a function containing only whitespace
- // or closing braces from being marked as uncovered.
- DeferredRegion = None;
}
void VisitReturnStmt(const ReturnStmt *S) {
@@ -1102,8 +1038,6 @@
void VisitLabelStmt(const LabelStmt *S) {
Counter LabelCount = getRegionCounter(S);
SourceLocation Start = getStart(S);
- completeTopLevelDeferredRegion(LabelCount, Start);
- completeDeferred(LabelCount, Start);
// We can't extendRegion here or we risk overlapping with our new region.
handleFileExit(Start);
pushRegion(LabelCount, Start);
@@ -1148,6 +1082,9 @@
Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
+ bool BodyHasTerminateStmt = HasTerminateStmt;
+ HasTerminateStmt = false;
+
// Go back to handle the condition.
Counter CondCount =
addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
@@ -1155,14 +1092,18 @@
adjustForOutOfOrderTraversal(getEnd(S));
// The body count applies to the area immediately after the increment.
- auto Gap = findGapAreaBetween(S->getCond(), S->getBody());
+ auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
Counter OutCount =
addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
- if (OutCount != ParentCount)
+ if (OutCount != ParentCount) {
pushRegion(OutCount);
+ GapRegionCounter = OutCount;
+ if (BodyHasTerminateStmt)
+ HasTerminateStmt = true;
+ }
// Create Branch Region around condition.
createBranchRegion(S->getCond(), BodyCount,
@@ -1181,17 +1122,25 @@
propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
+ bool BodyHasTerminateStmt = HasTerminateStmt;
+ HasTerminateStmt = false;
+
Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
propagateCounts(CondCount, S->getCond());
Counter OutCount =
addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
- if (OutCount != ParentCount)
+ if (OutCount != ParentCount) {
pushRegion(OutCount);
+ GapRegionCounter = OutCount;
+ }
// Create Branch Region around condition.
createBranchRegion(S->getCond(), BodyCount,
subtractCounters(CondCount, BodyCount));
+
+ if (BodyHasTerminateStmt)
+ HasTerminateStmt = true;
}
void VisitForStmt(const ForStmt *S) {
@@ -1212,6 +1161,9 @@
Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
BreakContinue BodyBC = BreakContinueStack.pop_back_val();
+ bool BodyHasTerminateStmt = HasTerminateStmt;
+ HasTerminateStmt = false;
+
// The increment is essentially part of the body but it needs to include
// the count for all the continue statements.
BreakContinue IncrementBC;
@@ -1230,15 +1182,18 @@
}
// The body count applies to the area immediately after the increment.
- auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
- getStart(S->getBody()));
+ auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
subtractCounters(CondCount, BodyCount));
- if (OutCount != ParentCount)
+ if (OutCount != ParentCount) {
pushRegion(OutCount);
+ GapRegionCounter = OutCount;
+ if (BodyHasTerminateStmt)
+ HasTerminateStmt = true;
+ }
// Create Branch Region around condition.
createBranchRegion(S->getCond(), BodyCount,
@@ -1260,9 +1215,11 @@
Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
BreakContinue BC = BreakContinueStack.pop_back_val();
+ bool BodyHasTerminateStmt = HasTerminateStmt;
+ HasTerminateStmt = false;
+
// The body count applies to the area immediately after the range.
- auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
- getStart(S->getBody()));
+ auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
@@ -1270,8 +1227,12 @@
addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
Counter OutCount =
addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
- if (OutCount != ParentCount)
+ if (OutCount != ParentCount) {
pushRegion(OutCount);
+ GapRegionCounter = OutCount;
+ if (BodyHasTerminateStmt)
+ HasTerminateStmt = true;
+ }
// Create Branch Region around condition.
createBranchRegion(S->getCond(), BodyCount,
@@ -1291,8 +1252,7 @@
BreakContinue BC = BreakContinueStack.pop_back_val();
// The body count applies to the area immediately after the collection.
- auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
- getStart(S->getBody()));
+ auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
@@ -1300,8 +1260,10 @@
addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
Counter OutCount =
addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
- if (OutCount != ParentCount)
+ if (OutCount != ParentCount) {
pushRegion(OutCount);
+ GapRegionCounter = OutCount;
+ }
}
void VisitSwitchStmt(const SwitchStmt *S) {
@@ -1321,8 +1283,7 @@
// the unreachable code at the beginning of the switch body.
size_t Index = pushRegion(Counter::getZero(), getStart(CS));
getRegion().setGap(true);
- for (const auto *Child : CS->children())
- Visit(Child);
+ Visit(Body);
// Set the end for the body of the switch, if it isn't already set.
for (size_t i = RegionStack.size(); i != Index; --i) {
@@ -1344,6 +1305,7 @@
Counter ExitCount = getRegionCounter(S);
SourceLocation ExitLoc = getEnd(S);
pushRegion(ExitCount);
+ GapRegionCounter = ExitCount;
// Ensure that handleFileExit recognizes when the end location is located
// in a different file.
@@ -1386,6 +1348,8 @@
else
pushRegion(Count, getStart(S));
+ GapRegionCounter = Count;
+
if (const auto *CS = dyn_cast<CaseStmt>(S)) {
Visit(CS->getLHS());
if (const Expr *RHS = CS->getRHS())
@@ -1411,7 +1375,7 @@
propagateCounts(ParentCount, S->getCond());
// The 'then' count applies to the area immediately after the condition.
- auto Gap = findGapAreaBetween(S->getCond(), S->getThen());
+ auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
@@ -1420,17 +1384,25 @@
Counter ElseCount = subtractCounters(ParentCount, ThenCount);
if (const Stmt *Else = S->getElse()) {
+ bool ThenHasTerminateStmt = HasTerminateStmt;
+ HasTerminateStmt = false;
+
// The 'else' count applies to the area immediately after the 'then'.
- Gap = findGapAreaBetween(S->getThen(), Else);
+ Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
extendRegion(Else);
OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
+
+ if (ThenHasTerminateStmt)
+ HasTerminateStmt = true;
} else
OutCount = addCounters(OutCount, ElseCount);
- if (OutCount != ParentCount)
+ if (OutCount != ParentCount) {
pushRegion(OutCount);
+ GapRegionCounter = OutCount;
+ }
// Create Branch Region around condition.
createBranchRegion(S->getCond(), ThenCount,
@@ -1462,7 +1434,7 @@
Counter ParentCount = getRegion().getCounter();
Counter TrueCount = getRegionCounter(E);
- Visit(E->getCond());
+ propagateCounts(ParentCount, E->getCond());
if (!isa<BinaryConditionalOperator>(E)) {
// The 'then' count applies to the area immediately after the condition.
@@ -1588,14 +1560,22 @@
CoverageMappingModuleGen::CoverageMappingModuleGen(
CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
: CGM(CGM), SourceInfo(SourceInfo) {
- ProfilePrefixMap = CGM.getCodeGenOpts().ProfilePrefixMap;
+ CoveragePrefixMap = CGM.getCodeGenOpts().CoveragePrefixMap;
+}
+
+std::string CoverageMappingModuleGen::getCurrentDirname() {
+ if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty())
+ return CGM.getCodeGenOpts().CoverageCompilationDir;
+
+ SmallString<256> CWD;
+ llvm::sys::fs::current_path(CWD);
+ return CWD.str().str();
}
std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
llvm::SmallString<256> Path(Filename);
- llvm::sys::fs::make_absolute(Path);
llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
- for (const auto &Entry : ProfilePrefixMap) {
+ for (const auto &Entry : CoveragePrefixMap) {
if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
break;
}
@@ -1674,18 +1654,17 @@
// also processed by the CoverageMappingWriter which performs
// additional minimization operations such as reducing the number of
// expressions.
+ llvm::SmallVector<std::string, 16> FilenameStrs;
std::vector<StringRef> Filenames;
std::vector<CounterExpression> Expressions;
std::vector<CounterMappingRegion> Regions;
- llvm::SmallVector<std::string, 16> FilenameStrs;
- llvm::SmallVector<StringRef, 16> FilenameRefs;
- FilenameStrs.resize(FileEntries.size());
- FilenameRefs.resize(FileEntries.size());
+ FilenameStrs.resize(FileEntries.size() + 1);
+ FilenameStrs[0] = normalizeFilename(getCurrentDirname());
for (const auto &Entry : FileEntries) {
auto I = Entry.second;
FilenameStrs[I] = normalizeFilename(Entry.first->getName());
- FilenameRefs[I] = FilenameStrs[I];
}
+ ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(FilenameStrs);
RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
Expressions, Regions);
if (Reader.read())
@@ -1702,19 +1681,18 @@
// Create the filenames and merge them with coverage mappings
llvm::SmallVector<std::string, 16> FilenameStrs;
- llvm::SmallVector<StringRef, 16> FilenameRefs;
- FilenameStrs.resize(FileEntries.size());
- FilenameRefs.resize(FileEntries.size());
+ FilenameStrs.resize(FileEntries.size() + 1);
+ // The first filename is the current working directory.
+ FilenameStrs[0] = normalizeFilename(getCurrentDirname());
for (const auto &Entry : FileEntries) {
auto I = Entry.second;
FilenameStrs[I] = normalizeFilename(Entry.first->getName());
- FilenameRefs[I] = FilenameStrs[I];
}
std::string Filenames;
{
llvm::raw_string_ostream OS(Filenames);
- CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
+ CoverageFilenamesSectionWriter(FilenameStrs).write(OS);
}
auto *FilenamesVal =
llvm::ConstantDataArray::getString(Ctx, Filenames, false);
@@ -1772,7 +1750,7 @@
auto It = FileEntries.find(File);
if (It != FileEntries.end())
return It->second;
- unsigned FileID = FileEntries.size();
+ unsigned FileID = FileEntries.size() + 1;
FileEntries.insert(std::make_pair(File, FileID));
return FileID;
}
diff --git a/src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.h b/src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.h
index b26f79be..ae4f435 100644
--- a/src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.h
+++ b/src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.h
@@ -93,8 +93,9 @@
llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
std::vector<llvm::Constant *> FunctionNames;
std::vector<FunctionInfo> FunctionRecords;
- std::map<std::string, std::string> ProfilePrefixMap;
+ std::map<std::string, std::string> CoveragePrefixMap;
+ std::string getCurrentDirname();
std::string normalizeFilename(StringRef Filename);
/// Emit a function record.
diff --git a/src/llvm-project/clang/lib/CodeGen/EHScopeStack.h b/src/llvm-project/clang/lib/CodeGen/EHScopeStack.h
index 3a640d6..cd649cb 100644
--- a/src/llvm-project/clang/lib/CodeGen/EHScopeStack.h
+++ b/src/llvm-project/clang/lib/CodeGen/EHScopeStack.h
@@ -150,6 +150,8 @@
Cleanup(Cleanup &&) {}
Cleanup() = default;
+ virtual bool isRedundantBeforeReturn() { return false; }
+
/// Generation flags.
class Flags {
enum {
@@ -236,6 +238,9 @@
/// The innermost EH scope on the stack.
stable_iterator InnermostEHScope;
+ /// The CGF this Stack belong to
+ CodeGenFunction* CGF;
+
/// The current set of branch fixups. A branch fixup is a jump to
/// an as-yet unemitted label, i.e. a label for which we don't yet
/// know the EH stack depth. Whenever we pop a cleanup, we have
@@ -261,9 +266,10 @@
void *pushCleanup(CleanupKind K, size_t DataSize);
public:
- EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr),
- StartOfData(nullptr), InnermostNormalCleanup(stable_end()),
- InnermostEHScope(stable_end()) {}
+ EHScopeStack()
+ : StartOfBuffer(nullptr), EndOfBuffer(nullptr), StartOfData(nullptr),
+ InnermostNormalCleanup(stable_end()), InnermostEHScope(stable_end()),
+ CGF(nullptr) {}
~EHScopeStack() { delete[] StartOfBuffer; }
/// Push a lazily-created cleanup on the stack.
@@ -311,6 +317,8 @@
std::memcpy(Buffer, Cleanup, Size);
}
+ void setCGF(CodeGenFunction *inCGF) { CGF = inCGF; }
+
/// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp.
void popCleanup();
diff --git a/src/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp b/src/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 50fb30a..d3dc0e6 100644
--- a/src/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -337,14 +337,20 @@
/// Determine whether we will definitely emit this variable with a constant
/// initializer, either because the language semantics demand it or because
/// we know that the initializer is a constant.
- bool isEmittedWithConstantInitializer(const VarDecl *VD) const {
+ // For weak definitions, any initializer available in the current translation
+ // is not necessarily reflective of the initializer used; such initializers
+ // are ignored unless if InspectInitForWeakDef is true.
+ bool
+ isEmittedWithConstantInitializer(const VarDecl *VD,
+ bool InspectInitForWeakDef = false) const {
VD = VD->getMostRecentDecl();
if (VD->hasAttr<ConstInitAttr>())
return true;
// All later checks examine the initializer specified on the variable. If
// the variable is weak, such examination would not be correct.
- if (VD->isWeak() || VD->hasAttr<SelectAnyAttr>())
+ if (!InspectInitForWeakDef &&
+ (VD->isWeak() || VD->hasAttr<SelectAnyAttr>()))
return false;
const VarDecl *InitDecl = VD->getInitializingDeclaration();
@@ -515,6 +521,9 @@
: ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
/*UseARMGuardVarABI=*/true) {}
void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
+ llvm::CallInst *
+ emitTerminateForUnexpectedException(CodeGenFunction &CGF,
+ llvm::Value *Exn) override;
private:
bool HasThisReturn(GlobalDecl GD) const override {
@@ -543,7 +552,7 @@
}
CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
- switch (CGM.getTarget().getCXXABI().getKind()) {
+ switch (CGM.getContext().getCXXABIKind()) {
// For IR-generation purposes, there's no significant difference
// between the ARM and iOS ABIs.
case TargetCXXABI::GenericARM:
@@ -648,7 +657,7 @@
// for consistency.
llvm::Value *This = ThisAddr.getPointer();
llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
- Ptr = Builder.CreateInBoundsGEP(Ptr, Adj);
+ Ptr = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), Ptr, Adj);
This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
ThisPtrForCall = This;
@@ -717,7 +726,8 @@
}
if (ShouldEmitVFEInfo) {
- llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);
+ llvm::Value *VFPAddr =
+ Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
// If doing VFE, load from the vtable with a type.checked.load intrinsic
// call. Note that we use the GEP to calculate the address to load from
@@ -735,7 +745,8 @@
// When not doing VFE, emit a normal load, as it allows more
// optimisations than type.checked.load.
if (ShouldEmitCFICheck || ShouldEmitWPDInfo) {
- llvm::Value *VFPAddr = Builder.CreateGEP(VTable, VTableOffset);
+ llvm::Value *VFPAddr =
+ Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
CheckResult = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test),
{Builder.CreateBitCast(VFPAddr, CGF.Int8PtrTy), TypeId});
@@ -748,11 +759,13 @@
{VTable, VTableOffset});
VirtualFn = CGF.Builder.CreateBitCast(VirtualFn, FTy->getPointerTo());
} else {
- llvm::Value *VFPAddr = CGF.Builder.CreateGEP(VTable, VTableOffset);
+ llvm::Value *VFPAddr =
+ CGF.Builder.CreateGEP(CGF.Int8Ty, VTable, VTableOffset);
VFPAddr = CGF.Builder.CreateBitCast(
VFPAddr, FTy->getPointerTo()->getPointerTo());
VirtualFn = CGF.Builder.CreateAlignedLoad(
- VFPAddr, CGF.getPointerAlign(), "memptr.virtualfn");
+ FTy->getPointerTo(), VFPAddr, CGF.getPointerAlign(),
+ "memptr.virtualfn");
}
}
assert(VirtualFn && "Virtual fuction pointer not created!");
@@ -855,8 +868,8 @@
Base = Builder.CreateElementBitCast(Base, CGF.Int8Ty);
// Apply the offset, which we assume is non-null.
- llvm::Value *Addr =
- Builder.CreateInBoundsGEP(Base.getPointer(), MemPtr, "memptr.offset");
+ llvm::Value *Addr = Builder.CreateInBoundsGEP(
+ Base.getElementType(), Base.getPointer(), MemPtr, "memptr.offset");
// Cast the address to the appropriate pointer type, adopting the
// address space of the base pointer.
@@ -1250,14 +1263,14 @@
// Track back to entry -2 and pull out the offset there.
llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
- VTable, -2, "complete-offset.ptr");
- llvm::Value *Offset =
- CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign());
+ CGF.IntPtrTy, VTable, -2, "complete-offset.ptr");
+ llvm::Value *Offset = CGF.Builder.CreateAlignedLoad(CGF.IntPtrTy, OffsetPtr, CGF.getPointerAlign());
// Apply the offset.
llvm::Value *CompletePtr =
CGF.Builder.CreateBitCast(Ptr.getPointer(), CGF.Int8PtrTy);
- CompletePtr = CGF.Builder.CreateInBoundsGEP(CompletePtr, Offset);
+ CompletePtr =
+ CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, CompletePtr, Offset);
// If we're supposed to call the global delete, make sure we do so
// even if the destructor throws.
@@ -1462,9 +1475,11 @@
Value = CGF.Builder.CreateBitCast(Value, StdTypeInfoPtrTy->getPointerTo());
} else {
// Load the type info.
- Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
+ Value =
+ CGF.Builder.CreateConstInBoundsGEP1_64(StdTypeInfoPtrTy, Value, -1ULL);
}
- return CGF.Builder.CreateAlignedLoad(Value, CGF.getPointerAlign());
+ return CGF.Builder.CreateAlignedLoad(StdTypeInfoPtrTy, Value,
+ CGF.getPointerAlign());
}
bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
@@ -1530,9 +1545,9 @@
// Get the offset-to-top from the vtable.
OffsetToTop =
- CGF.Builder.CreateConstInBoundsGEP1_32(/*Type=*/nullptr, VTable, -2U);
+ CGF.Builder.CreateConstInBoundsGEP1_32(CGM.Int32Ty, VTable, -2U);
OffsetToTop = CGF.Builder.CreateAlignedLoad(
- OffsetToTop, CharUnits::fromQuantity(4), "offset.to.top");
+ CGM.Int32Ty, OffsetToTop, CharUnits::fromQuantity(4), "offset.to.top");
} else {
llvm::Type *PtrDiffLTy =
CGF.ConvertType(CGF.getContext().getPointerDiffType());
@@ -1542,14 +1557,15 @@
CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), ClassDecl);
// Get the offset-to-top from the vtable.
- OffsetToTop = CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
+ OffsetToTop =
+ CGF.Builder.CreateConstInBoundsGEP1_64(PtrDiffLTy, VTable, -2ULL);
OffsetToTop = CGF.Builder.CreateAlignedLoad(
- OffsetToTop, CGF.getPointerAlign(), "offset.to.top");
+ PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top");
}
// Finally, add the offset to the pointer.
llvm::Value *Value = ThisAddr.getPointer();
Value = CGF.EmitCastToVoidPtr(Value);
- Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
+ Value = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, Value, OffsetToTop);
return CGF.Builder.CreateBitCast(Value, DestLTy);
}
@@ -1571,20 +1587,22 @@
CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
BaseClassDecl);
llvm::Value *VBaseOffsetPtr =
- CGF.Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset.getQuantity(),
- "vbase.offset.ptr");
+ CGF.Builder.CreateConstGEP1_64(
+ CGF.Int8Ty, VTablePtr, VBaseOffsetOffset.getQuantity(),
+ "vbase.offset.ptr");
llvm::Value *VBaseOffset;
if (CGM.getItaniumVTableContext().isRelativeLayout()) {
VBaseOffsetPtr =
CGF.Builder.CreateBitCast(VBaseOffsetPtr, CGF.Int32Ty->getPointerTo());
VBaseOffset = CGF.Builder.CreateAlignedLoad(
- VBaseOffsetPtr, CharUnits::fromQuantity(4), "vbase.offset");
+ CGF.Int32Ty, VBaseOffsetPtr, CharUnits::fromQuantity(4),
+ "vbase.offset");
} else {
VBaseOffsetPtr = CGF.Builder.CreateBitCast(VBaseOffsetPtr,
CGM.PtrDiffTy->getPointerTo());
VBaseOffset = CGF.Builder.CreateAlignedLoad(
- VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
+ CGM.PtrDiffTy, VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
}
return VBaseOffset;
}
@@ -1767,8 +1785,22 @@
DC->getParent()->isTranslationUnit())
EmitFundamentalRTTIDescriptors(RD);
- if (!VTable->isDeclarationForLinker())
+ // Always emit type metadata on non-available_externally definitions, and on
+ // available_externally definitions if we are performing whole program
+ // devirtualization. For WPD we need the type metadata on all vtable
+ // definitions to ensure we associate derived classes with base classes
+ // defined in headers but with a strong definition only in a shared library.
+ if (!VTable->isDeclarationForLinker() ||
+ CGM.getCodeGenOpts().WholeProgramVTables) {
CGM.EmitVTableTypeMetadata(RD, VTable, VTLayout);
+ // For available_externally definitions, add the vtable to
+ // @llvm.compiler.used so that it isn't deleted before whole program
+ // analysis.
+ if (VTable->isDeclarationForLinker()) {
+ assert(CGM.getCodeGenOpts().WholeProgramVTables);
+ CGM.addCompilerUsedGlobal(VTable);
+ }
+ }
if (VTContext.isRelativeLayout() && !VTable->isDSOLocal())
CGVT.GenerateRelativeVTableAlias(VTable, VTable->getName());
@@ -1815,6 +1847,29 @@
/*InRangeIndex=*/1);
}
+// Check whether all the non-inline virtual methods for the class have the
+// specified attribute.
+template <typename T>
+static bool CXXRecordAllNonInlineVirtualsHaveAttr(const CXXRecordDecl *RD) {
+ bool FoundNonInlineVirtualMethodWithAttr = false;
+ for (const auto *D : RD->noload_decls()) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (!FD->isVirtualAsWritten() || FD->isInlineSpecified() ||
+ FD->doesThisDeclarationHaveABody())
+ continue;
+ if (!D->hasAttr<T>())
+ return false;
+ FoundNonInlineVirtualMethodWithAttr = true;
+ }
+ }
+
+ // We didn't find any non-inline virtual methods missing the attribute. We
+ // will return true when we found at least one non-inline virtual with the
+ // attribute. (This lets our caller know that the attribute needs to be
+ // propagated up to the vtable.)
+ return FoundNonInlineVirtualMethodWithAttr;
+}
+
llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base,
const CXXRecordDecl *NearestVBase) {
@@ -1828,10 +1883,12 @@
/// Load the VTT.
llvm::Value *VTT = CGF.LoadCXXVTT();
if (VirtualPointerIndex)
- VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex);
+ VTT = CGF.Builder.CreateConstInBoundsGEP1_64(
+ CGF.VoidPtrTy, VTT, VirtualPointerIndex);
// And load the address point from the VTT.
- return CGF.Builder.CreateAlignedLoad(VTT, CGF.getPointerAlign());
+ return CGF.Builder.CreateAlignedLoad(CGF.VoidPtrTy, VTT,
+ CGF.getPointerAlign());
}
llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr(
@@ -1870,6 +1927,24 @@
getContext().toCharUnitsFromBits(PAlign).getQuantity());
VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ // In MS C++ if you have a class with virtual functions in which you are using
+ // selective member import/export, then all virtual functions must be exported
+ // unless they are inline, otherwise a link error will result. To match this
+ // behavior, for such classes, we dllimport the vtable if it is defined
+ // externally and all the non-inline virtual methods are marked dllimport, and
+ // we dllexport the vtable if it is defined in this TU and all the non-inline
+ // virtual methods are marked dllexport.
+ if (CGM.getTarget().hasPS4DLLImportExport()) {
+ if ((!RD->hasAttr<DLLImportAttr>()) && (!RD->hasAttr<DLLExportAttr>())) {
+ if (CGM.getVTables().isVTableExternal(RD)) {
+ if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD))
+ VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ } else {
+ if (CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD))
+ VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ }
+ }
+ }
CGM.setGVProperties(VTable, RD);
return VTable;
@@ -1880,9 +1955,10 @@
Address This,
llvm::Type *Ty,
SourceLocation Loc) {
+ llvm::Type *TyPtr = Ty->getPointerTo();
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
llvm::Value *VTable = CGF.GetVTablePtr(
- This, Ty->getPointerTo()->getPointerTo(), MethodDecl->getParent());
+ This, TyPtr->getPointerTo(), MethodDecl->getParent());
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
llvm::Value *VFunc;
@@ -1899,14 +1975,15 @@
llvm::Value *Load = CGF.Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::load_relative, {CGM.Int32Ty}),
{VTable, llvm::ConstantInt::get(CGM.Int32Ty, 4 * VTableIndex)});
- VFuncLoad = CGF.Builder.CreateBitCast(Load, Ty->getPointerTo());
+ VFuncLoad = CGF.Builder.CreateBitCast(Load, TyPtr);
} else {
VTable =
- CGF.Builder.CreateBitCast(VTable, Ty->getPointerTo()->getPointerTo());
- llvm::Value *VTableSlotPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
+ CGF.Builder.CreateBitCast(VTable, TyPtr->getPointerTo());
+ llvm::Value *VTableSlotPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
+ TyPtr, VTable, VTableIndex, "vfn");
VFuncLoad =
- CGF.Builder.CreateAlignedLoad(VTableSlotPtr, CGF.getPointerAlign());
+ CGF.Builder.CreateAlignedLoad(TyPtr, VTableSlotPtr,
+ CGF.getPointerAlign());
}
// Add !invariant.load md to virtual function load to indicate that
@@ -2044,14 +2121,15 @@
llvm::Value *VTablePtr = CGF.Builder.CreateLoad(VTablePtrPtr);
llvm::Value *Offset;
- llvm::Value *OffsetPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTablePtr, VirtualAdjustment);
+ llvm::Value *OffsetPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
+ CGF.Int8Ty, VTablePtr, VirtualAdjustment);
if (CGF.CGM.getItaniumVTableContext().isRelativeLayout()) {
// Load the adjustment offset from the vtable as a 32-bit int.
OffsetPtr =
CGF.Builder.CreateBitCast(OffsetPtr, CGF.Int32Ty->getPointerTo());
Offset =
- CGF.Builder.CreateAlignedLoad(OffsetPtr, CharUnits::fromQuantity(4));
+ CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, OffsetPtr,
+ CharUnits::fromQuantity(4));
} else {
llvm::Type *PtrDiffTy =
CGF.ConvertType(CGF.getContext().getPointerDiffType());
@@ -2060,10 +2138,12 @@
CGF.Builder.CreateBitCast(OffsetPtr, PtrDiffTy->getPointerTo());
// Load the adjustment offset from the vtable.
- Offset = CGF.Builder.CreateAlignedLoad(OffsetPtr, CGF.getPointerAlign());
+ Offset = CGF.Builder.CreateAlignedLoad(PtrDiffTy, OffsetPtr,
+ CGF.getPointerAlign());
}
// Adjust our pointer.
- ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getPointer(), Offset);
+ ResultPtr = CGF.Builder.CreateInBoundsGEP(
+ V.getElementType(), V.getPointer(), Offset);
} else {
ResultPtr = V.getPointer();
}
@@ -2071,7 +2151,7 @@
// In a derived-to-base conversion, the non-virtual adjustment is
// applied second.
if (NonVirtualAdjustment && IsReturnAdjustment) {
- ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ResultPtr,
+ ResultPtr = CGF.Builder.CreateConstInBoundsGEP1_64(CGF.Int8Ty, ResultPtr,
NonVirtualAdjustment);
}
@@ -2472,7 +2552,10 @@
CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy),
guardAddr.getPointer());
} else {
- Builder.CreateStore(llvm::ConstantInt::get(guardTy, 1), guardAddr);
+ // Store 1 into the first byte of the guard variable after initialization is
+ // complete.
+ Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
+ Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
}
CGF.EmitBlock(EndBlock);
@@ -2482,6 +2565,8 @@
static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
llvm::FunctionCallee dtor,
llvm::Constant *addr, bool TLS) {
+ assert(!CGF.getTarget().getTriple().isOSAIX() &&
+ "unexpected call to emitGlobalDtorWithCXAAtExit");
assert((TLS || CGF.getTypes().getCodeGenOpts().CXAAtExit) &&
"__cxa_atexit is disabled");
const char *Name = "__cxa_atexit";
@@ -2542,15 +2627,6 @@
return GlobalInitOrCleanupFn;
}
-static FunctionDecl *
-createGlobalInitOrCleanupFnDecl(CodeGen::CodeGenModule &CGM, StringRef FnName) {
- ASTContext &Ctx = CGM.getContext();
- QualType FunctionTy = Ctx.getFunctionType(Ctx.VoidTy, llvm::None, {});
- return FunctionDecl::Create(
- Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(),
- &Ctx.Idents.get(FnName), FunctionTy, nullptr, SC_Static, false, false);
-}
-
void CodeGenModule::unregisterGlobalDtorsWithUnAtExit() {
for (const auto &I : DtorsUsingAtExit) {
int Priority = I.first;
@@ -2560,13 +2636,11 @@
llvm::Function *GlobalCleanupFn =
createGlobalInitOrCleanupFn(*this, GlobalCleanupFnName);
- FunctionDecl *GlobalCleanupFD =
- createGlobalInitOrCleanupFnDecl(*this, GlobalCleanupFnName);
-
CodeGenFunction CGF(*this);
- CGF.StartFunction(GlobalDecl(GlobalCleanupFD), getContext().VoidTy,
- GlobalCleanupFn, getTypes().arrangeNullaryFunction(),
- FunctionArgList(), SourceLocation(), SourceLocation());
+ CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalCleanupFn,
+ getTypes().arrangeNullaryFunction(), FunctionArgList(),
+ SourceLocation(), SourceLocation());
+ auto AL = ApplyDebugLocation::CreateArtificial(CGF);
// Get the destructor function type, void(*)(void).
llvm::FunctionType *dtorFuncTy = llvm::FunctionType::get(CGF.VoidTy, false);
@@ -2619,13 +2693,12 @@
std::string("__GLOBAL_init_") + llvm::to_string(Priority);
llvm::Function *GlobalInitFn =
createGlobalInitOrCleanupFn(*this, GlobalInitFnName);
- FunctionDecl *GlobalInitFD =
- createGlobalInitOrCleanupFnDecl(*this, GlobalInitFnName);
CodeGenFunction CGF(*this);
- CGF.StartFunction(GlobalDecl(GlobalInitFD), getContext().VoidTy,
- GlobalInitFn, getTypes().arrangeNullaryFunction(),
- FunctionArgList(), SourceLocation(), SourceLocation());
+ CGF.StartFunction(GlobalDecl(), getContext().VoidTy, GlobalInitFn,
+ getTypes().arrangeNullaryFunction(), FunctionArgList(),
+ SourceLocation(), SourceLocation());
+ auto AL = ApplyDebugLocation::CreateArtificial(CGF);
// Since constructor functions are run in non-descending order of their
// priorities, destructors are registered in non-descending order of their
@@ -2742,7 +2815,7 @@
if (CGM.supportsCOMDAT() && Wrapper->isWeakForLinker())
Wrapper->setComdat(CGM.getModule().getOrInsertComdat(Wrapper->getName()));
- CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper);
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Wrapper, /*IsThunk=*/false);
// Always resolve references to the wrapper at link time.
if (!Wrapper->hasLocalLinkage())
@@ -2875,8 +2948,8 @@
llvm::GlobalVariable::ExternalWeakLinkage,
InitFnName.str(), &CGM.getModule());
const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
- CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI,
- cast<llvm::Function>(Init));
+ CGM.SetLLVMFunctionAttributes(
+ GlobalDecl(), FI, cast<llvm::Function>(Init), /*IsThunk=*/false);
}
if (Init) {
@@ -2887,6 +2960,33 @@
}
llvm::LLVMContext &Context = CGM.getModule().getContext();
+
+ // The linker on AIX is not happy with missing weak symbols. However,
+ // other TUs will not know whether the initialization routine exists
+ // so create an empty, init function to satisfy the linker.
+ // This is needed whenever a thread wrapper function is not used, and
+ // also when the symbol is weak.
+ if (CGM.getTriple().isOSAIX() && VD->hasDefinition() &&
+ isEmittedWithConstantInitializer(VD, true) &&
+ !VD->needsDestruction(getContext())) {
+ // Init should be null. If it were non-null, then the logic above would
+ // either be defining the function to be an alias or declaring the
+ // function with the expectation that the definition of the variable
+ // is elsewhere.
+ assert(Init == nullptr && "Expected Init to be null.");
+
+ llvm::Function *Func = llvm::Function::Create(
+ InitFnTy, Var->getLinkage(), InitFnName.str(), &CGM.getModule());
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
+ CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI,
+ cast<llvm::Function>(Func),
+ /*IsThunk=*/false);
+ // Create a function body that just returns
+ llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Func);
+ CGBuilderTy Builder(CGM, Entry);
+ Builder.CreateRetVoid();
+ }
+
llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper);
CGBuilderTy Builder(CGM, Entry);
if (HasConstantInitialization) {
@@ -2901,6 +3001,15 @@
Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
}
}
+ } else if (CGM.getTriple().isOSAIX()) {
+ // On AIX, except if constinit and also neither of class type or of
+ // (possibly multi-dimensional) array of class type, thread_local vars
+ // will have init routines regardless of whether they are
+ // const-initialized. Since the routine is guaranteed to exist, we can
+ // unconditionally call it without testing for its existance. This
+ // avoids potentially unresolved weak symbols which the AIX linker
+ // isn't happy with.
+ Builder.CreateCall(InitFnTy, Init);
} else {
// Don't know whether we have an init function. Call it if it exists.
llvm::Value *Have = Builder.CreateIsNotNull(Init);
@@ -2920,7 +3029,7 @@
llvm::Value *Val = Var;
if (VD->getType()->isReferenceType()) {
CharUnits Align = CGM.getContext().getDeclAlign(VD);
- Val = Builder.CreateAlignedLoad(Val, Align);
+ Val = Builder.CreateAlignedLoad(Var->getValueType(), Var, Align);
}
if (Val->getType() != Wrapper->getReturnType())
Val = Builder.CreatePointerBitCastOrAddrSpaceCast(
@@ -3111,6 +3220,14 @@
Name);
const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
CGM.setGVProperties(GV, RD);
+ // Import the typeinfo symbol when all non-inline virtual methods are
+ // imported.
+ if (CGM.getTarget().hasPS4DLLImportExport()) {
+ if (RD && CXXRecordAllNonInlineVirtualsHaveAttr<DLLImportAttr>(RD)) {
+ GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
+ CGM.setDSOLocal(GV);
+ }
+ }
}
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
@@ -3181,6 +3298,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
case BuiltinType::ShortAccum:
case BuiltinType::Accum:
case BuiltinType::LongAccum:
@@ -3285,11 +3404,14 @@
if (CGM.getTriple().isWindowsGNUEnvironment())
return false;
- if (CGM.getVTables().isVTableExternal(RD))
+ if (CGM.getVTables().isVTableExternal(RD)) {
+ if (CGM.getTarget().hasPS4DLLImportExport())
+ return true;
+
return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment()
? false
: true;
-
+ }
if (IsDLLImport)
return true;
}
@@ -3741,6 +3863,18 @@
new llvm::GlobalVariable(M, Init->getType(),
/*isConstant=*/true, Linkage, Init, Name);
+ // Export the typeinfo in the same circumstances as the vtable is exported.
+ auto GVDLLStorageClass = DLLStorageClass;
+ if (CGM.getTarget().hasPS4DLLImportExport()) {
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (RD->hasAttr<DLLExportAttr>() ||
+ CXXRecordAllNonInlineVirtualsHaveAttr<DLLExportAttr>(RD)) {
+ GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
+ }
+ }
+ }
+
// If there's already an old global variable, replace it with the new one.
if (OldGV) {
GV->takeName(OldGV);
@@ -3779,7 +3913,9 @@
CGM.setDSOLocal(GV);
TypeName->setDLLStorageClass(DLLStorageClass);
- GV->setDLLStorageClass(DLLStorageClass);
+ GV->setDLLStorageClass(CGM.getTarget().hasPS4DLLImportExport()
+ ? GVDLLStorageClass
+ : DLLStorageClass);
TypeName->setPartition(CGM.getCodeGenOpts().SymbolPartition);
GV->setPartition(CGM.getCodeGenOpts().SymbolPartition);
@@ -4360,7 +4496,8 @@
// we have to skip past in order to reach the exception data.
unsigned HeaderSize =
CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
- AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);
+ AdjustedExn =
+ CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize);
// However, if we're catching a pointer-to-record type that won't
// work, because the personality function might have adjusted
@@ -4621,22 +4758,57 @@
ItaniumCXXABI::emitBeginCatch(CGF, C);
}
+llvm::CallInst *
+WebAssemblyCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
+ llvm::Value *Exn) {
+ // Itanium ABI calls __clang_call_terminate(), which __cxa_begin_catch() on
+ // the violating exception to mark it handled, but it is currently hard to do
+ // with wasm EH instruction structure with catch/catch_all, we just call
+ // std::terminate and ignore the violating exception as in CGCXXABI.
+ // TODO Consider code transformation that makes calling __clang_call_terminate
+ // possible.
+ return CGCXXABI::emitTerminateForUnexpectedException(CGF, Exn);
+}
+
/// Register a global destructor as best as we know how.
void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
- llvm::FunctionCallee dtor,
- llvm::Constant *addr) {
- if (D.getTLSKind() != VarDecl::TLS_None)
- llvm::report_fatal_error("thread local storage not yet implemented on AIX");
+ llvm::FunctionCallee Dtor,
+ llvm::Constant *Addr) {
+ if (D.getTLSKind() != VarDecl::TLS_None) {
+ // atexit routine expects "int(*)(int,...)"
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.IntTy, CGM.IntTy, true);
+ llvm::PointerType *FpTy = FTy->getPointerTo();
+
+ // extern "C" int __pt_atexit_np(int flags, int(*)(int,...), ...);
+ llvm::FunctionType *AtExitTy =
+ llvm::FunctionType::get(CGM.IntTy, {CGM.IntTy, FpTy}, true);
+
+ // Fetch the actual function.
+ llvm::FunctionCallee AtExit =
+ CGM.CreateRuntimeFunction(AtExitTy, "__pt_atexit_np");
+
+ // Create __dtor function for the var decl.
+ llvm::Function *DtorStub = CGF.createTLSAtExitStub(D, Dtor, Addr, AtExit);
+
+ // Register above __dtor with atexit().
+ // First param is flags and must be 0, second param is function ptr
+ llvm::Value *NV = llvm::Constant::getNullValue(CGM.IntTy);
+ CGF.EmitNounwindRuntimeCall(AtExit, {NV, DtorStub});
+
+ // Cannot unregister TLS __dtor so done
+ return;
+ }
// Create __dtor function for the var decl.
- llvm::Function *dtorStub = CGF.createAtExitStub(D, dtor, addr);
+ llvm::Function *DtorStub = CGF.createAtExitStub(D, Dtor, Addr);
// Register above __dtor with atexit().
- CGF.registerGlobalDtorWithAtExit(dtorStub);
+ CGF.registerGlobalDtorWithAtExit(DtorStub);
// Emit __finalize function to unregister __dtor and (as appropriate) call
// __dtor.
- emitCXXStermFinalizer(D, dtorStub, addr);
+ emitCXXStermFinalizer(D, DtorStub, Addr);
}
void XLCXXABI::emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
@@ -4686,16 +4858,17 @@
CGF.FinishFunction();
- assert(!D.getAttr<InitPriorityAttr>() &&
- "Prioritized sinit and sterm functions are not yet supported.");
-
- if (isTemplateInstantiation(D.getTemplateSpecializationKind()) ||
- getContext().GetGVALinkageForVariable(&D) == GVA_DiscardableODR)
+ if (auto *IPA = D.getAttr<InitPriorityAttr>()) {
+ CGM.AddCXXPrioritizedStermFinalizerEntry(StermFinalizer,
+ IPA->getPriority());
+ } else if (isTemplateInstantiation(D.getTemplateSpecializationKind()) ||
+ getContext().GetGVALinkageForVariable(&D) == GVA_DiscardableODR) {
// According to C++ [basic.start.init]p2, class template static data
// members (i.e., implicitly or explicitly instantiated specializations)
// have unordered initialization. As a consequence, we can put them into
// their own llvm.global_dtors entry.
CGM.AddCXXStermFinalizerToGlobalDtor(StermFinalizer, 65535);
- else
+ } else {
CGM.AddCXXStermFinalizerEntry(StermFinalizer);
+ }
}
diff --git a/src/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/src/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index cb0dc1d..990648b 100644
--- a/src/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -131,7 +131,12 @@
/// MSVC needs an extra flag to indicate a catchall.
CatchTypeInfo getCatchAllTypeInfo() override {
- return CatchTypeInfo{nullptr, 0x40};
+ // For -EHa catch(...) must handle HW exception
+ // Adjective = HT_IsStdDotDot (0x40), only catch C++ exceptions
+ if (getContext().getLangOpts().EHAsynch)
+ return CatchTypeInfo{nullptr, 0};
+ else
+ return CatchTypeInfo{nullptr, 0x40};
}
bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override;
@@ -937,7 +942,8 @@
llvm::Value *Offset =
GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase);
- llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(Value.getPointer(), Offset);
+ llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(
+ Value.getElementType(), Value.getPointer(), Offset);
CharUnits VBaseAlign =
CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase);
return std::make_tuple(Address(Ptr, VBaseAlign), Offset, PolymorphicBase);
@@ -1219,9 +1225,10 @@
if (!Int8This)
Int8This = Builder.CreateBitCast(getThisValue(CGF),
CGF.Int8Ty->getPointerTo(AS));
- llvm::Value *VtorDispPtr = Builder.CreateInBoundsGEP(Int8This, VBaseOffset);
+ llvm::Value *VtorDispPtr =
+ Builder.CreateInBoundsGEP(CGF.Int8Ty, Int8This, VBaseOffset);
// vtorDisp is always the 32-bits before the vbase in the class layout.
- VtorDispPtr = Builder.CreateConstGEP1_32(VtorDispPtr, -4);
+ VtorDispPtr = Builder.CreateConstGEP1_32(CGF.Int8Ty, VtorDispPtr, -4);
VtorDispPtr = Builder.CreateBitCast(
VtorDispPtr, CGF.Int32Ty->getPointerTo(AS), "vtordisp.ptr");
@@ -1457,8 +1464,8 @@
const CXXRecordDecl *VBase = ML.VBase;
llvm::Value *VBaseOffset =
GetVirtualBaseClassOffset(CGF, Result, Derived, VBase);
- llvm::Value *VBasePtr =
- CGF.Builder.CreateInBoundsGEP(Result.getPointer(), VBaseOffset);
+ llvm::Value *VBasePtr = CGF.Builder.CreateInBoundsGEP(
+ Result.getElementType(), Result.getPointer(), VBaseOffset);
CharUnits VBaseAlign =
CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase);
Result = Address(VBasePtr, VBaseAlign);
@@ -1911,12 +1918,13 @@
SourceLocation Loc) {
CGBuilderTy &Builder = CGF.Builder;
- Ty = Ty->getPointerTo()->getPointerTo();
+ Ty = Ty->getPointerTo();
Address VPtr =
adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
- llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent());
+ llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty->getPointerTo(),
+ MethodDecl->getParent());
MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
MethodVFTableLocation ML = VFTContext.getMethodVFTableLocation(GD);
@@ -1943,8 +1951,8 @@
CGF.EmitTypeMetadataCodeForVCall(getObjectWithVPtr(), VTable, Loc);
llvm::Value *VFuncPtr =
- Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
- VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
+ Builder.CreateConstInBoundsGEP1_64(Ty, VTable, ML.Index, "vfn");
+ VFunc = Builder.CreateAlignedLoad(Ty, VFuncPtr, CGF.getPointerAlign());
}
CGCallee Callee(GD, VFunc);
@@ -2043,7 +2051,7 @@
if (MD->isExternallyVisible())
ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));
- CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
+ CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn, /*IsThunk=*/false);
CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn);
// Add the "thunk" attribute so that LLVM knows that the return type is
@@ -2072,13 +2080,14 @@
// Load the vfptr and then callee from the vftable. The callee should have
// adjusted 'this' so that the vfptr is at offset zero.
+ llvm::Type *ThunkPtrTy = ThunkTy->getPointerTo();
llvm::Value *VTable = CGF.GetVTablePtr(
- getThisAddress(CGF), ThunkTy->getPointerTo()->getPointerTo(), MD->getParent());
+ getThisAddress(CGF), ThunkPtrTy->getPointerTo(), MD->getParent());
- llvm::Value *VFuncPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
+ llvm::Value *VFuncPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
+ ThunkPtrTy, VTable, ML.Index, "vfn");
llvm::Value *Callee =
- CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
+ CGF.Builder.CreateAlignedLoad(ThunkPtrTy, VFuncPtr, CGF.getPointerAlign());
CGF.EmitMustTailThunk(MD, getThisValue(CGF), {ThunkTy, Callee});
@@ -2163,8 +2172,7 @@
}
assert(Offsets.size() ==
- cast<llvm::ArrayType>(cast<llvm::PointerType>(GV->getType())
- ->getElementType())->getNumElements());
+ cast<llvm::ArrayType>(GV->getValueType())->getNumElements());
llvm::ArrayType *VBTableType =
llvm::ArrayType::get(CGM.IntTy, Offsets.size());
llvm::Constant *Init = llvm::ConstantArray::get(VBTableType, Offsets);
@@ -2193,7 +2201,7 @@
CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset));
VtorDispPtr = CGF.Builder.CreateElementBitCast(VtorDispPtr, CGF.Int32Ty);
llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp");
- V = CGF.Builder.CreateGEP(This.getPointer(),
+ V = CGF.Builder.CreateGEP(This.getElementType(), This.getPointer(),
CGF.Builder.CreateNeg(VtorDisp));
// Unfortunately, having applied the vtordisp means that we no
@@ -2211,7 +2219,7 @@
GetVBaseOffsetFromVBPtr(CGF, Address(V, CGF.getPointerAlign()),
-TA.Virtual.Microsoft.VBPtrOffset,
TA.Virtual.Microsoft.VBOffsetOffset, &VBPtr);
- V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
+ V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, VBPtr, VBaseOffset);
}
}
@@ -2219,7 +2227,7 @@
// Non-virtual adjustment might result in a pointer outside the allocated
// object, e.g. if the final overrider class is laid out after the virtual
// base that declares a method in the most derived class.
- V = CGF.Builder.CreateConstGEP1_32(V, TA.NonVirtual);
+ V = CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, V, TA.NonVirtual);
}
// Don't need to bitcast back, the call CodeGen will handle this.
@@ -2243,7 +2251,7 @@
llvm::Value *VBaseOffset =
GetVBaseOffsetFromVBPtr(CGF, Ret, RA.Virtual.Microsoft.VBPtrOffset,
IntSize * RA.Virtual.Microsoft.VBIndex, &VBPtr);
- V = CGF.Builder.CreateInBoundsGEP(VBPtr, VBaseOffset);
+ V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, VBPtr, VBaseOffset);
}
if (RA.NonVirtual)
@@ -3008,8 +3016,8 @@
CGBuilderTy &Builder = CGF.Builder;
// Load the vbtable pointer from the vbptr in the instance.
This = Builder.CreateElementBitCast(This, CGM.Int8Ty);
- llvm::Value *VBPtr =
- Builder.CreateInBoundsGEP(This.getPointer(), VBPtrOffset, "vbptr");
+ llvm::Value *VBPtr = Builder.CreateInBoundsGEP(
+ This.getElementType(), This.getPointer(), VBPtrOffset, "vbptr");
if (VBPtrOut) *VBPtrOut = VBPtr;
VBPtr = Builder.CreateBitCast(VBPtr,
CGM.Int32Ty->getPointerTo(0)->getPointerTo(This.getAddressSpace()));
@@ -3022,7 +3030,8 @@
VBPtrAlign = CGF.getPointerAlign();
}
- llvm::Value *VBTable = Builder.CreateAlignedLoad(VBPtr, VBPtrAlign, "vbtable");
+ llvm::Value *VBTable = Builder.CreateAlignedLoad(
+ CGM.Int32Ty->getPointerTo(0), VBPtr, VBPtrAlign, "vbtable");
// Translate from byte offset to table index. It improves analyzability.
llvm::Value *VBTableIndex = Builder.CreateAShr(
@@ -3030,10 +3039,11 @@
"vbtindex", /*isExact=*/true);
// Load an i32 offset from the vb-table.
- llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableIndex);
+ llvm::Value *VBaseOffs =
+ Builder.CreateInBoundsGEP(CGM.Int32Ty, VBTable, VBTableIndex);
VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0));
- return Builder.CreateAlignedLoad(VBaseOffs, CharUnits::fromQuantity(4),
- "vbase_offs");
+ return Builder.CreateAlignedLoad(CGM.Int32Ty, VBaseOffs,
+ CharUnits::fromQuantity(4), "vbase_offs");
}
// Returns an adjusted base cast to i8*, since we do more address arithmetic on
@@ -3080,7 +3090,8 @@
llvm::Value *VBPtr = nullptr;
llvm::Value *VBaseOffs =
GetVBaseOffsetFromVBPtr(CGF, Base, VBPtrOffset, VBTableOffset, &VBPtr);
- llvm::Value *AdjustedBase = Builder.CreateInBoundsGEP(VBPtr, VBaseOffs);
+ llvm::Value *AdjustedBase =
+ Builder.CreateInBoundsGEP(CGM.Int8Ty, VBPtr, VBaseOffs);
// Merge control flow with the case where we didn't have to adjust.
if (VBaseAdjustBB) {
@@ -3132,7 +3143,8 @@
Addr = Builder.CreateBitCast(Addr, CGF.Int8Ty->getPointerTo(AS));
// Apply the offset, which we assume is non-null.
- Addr = Builder.CreateInBoundsGEP(Addr, FieldOffset, "memptr.offset");
+ Addr = Builder.CreateInBoundsGEP(CGF.Int8Ty, Addr, FieldOffset,
+ "memptr.offset");
// Cast the address to the appropriate pointer type, adopting the address
// space of the base pointer.
@@ -3294,9 +3306,10 @@
Mapping->getAggregateElement(cast<llvm::Constant>(VBIndex));
} else {
llvm::Value *Idxs[] = {getZeroInt(), VBIndex};
- VirtualBaseAdjustmentOffset =
- Builder.CreateAlignedLoad(Builder.CreateInBoundsGEP(VDispMap, Idxs),
- CharUnits::fromQuantity(4));
+ VirtualBaseAdjustmentOffset = Builder.CreateAlignedLoad(
+ CGM.IntTy, Builder.CreateInBoundsGEP(VDispMap->getValueType(),
+ VDispMap, Idxs),
+ CharUnits::fromQuantity(4));
}
DstVBIndexEqZero =
@@ -3426,7 +3439,7 @@
if (NonVirtualBaseAdjustment) {
// Apply the adjustment and cast back to the original struct type.
llvm::Value *Ptr = Builder.CreateBitCast(ThisPtrForCall, CGF.Int8PtrTy);
- Ptr = Builder.CreateInBoundsGEP(Ptr, NonVirtualBaseAdjustment);
+ Ptr = Builder.CreateInBoundsGEP(CGF.Int8Ty, Ptr, NonVirtualBaseAdjustment);
ThisPtrForCall = Builder.CreateBitCast(Ptr, ThisPtrForCall->getType(),
"this.adjusted");
}
@@ -4325,7 +4338,7 @@
};
auto *GV = new llvm::GlobalVariable(
CGM.getModule(), TIType, /*isConstant=*/true, getLinkageForRTTI(T),
- llvm::ConstantStruct::get(TIType, Fields), StringRef(MangledName));
+ llvm::ConstantStruct::get(TIType, Fields), MangledName.str());
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
GV->setSection(".xdata");
if (GV->isWeakForLinker())
diff --git a/src/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp b/src/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp
index 01093cf..b63f756 100644
--- a/src/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -138,7 +138,7 @@
Ctx = &Context;
M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple());
- M->setDataLayout(Ctx->getTargetInfo().getDataLayout());
+ M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion();
if (!SDKVersion.empty())
M->setSDKVersion(SDKVersion);
diff --git a/src/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/src/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
index de5c1a4..1adf0ad 100644
--- a/src/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
@@ -166,7 +166,7 @@
Ctx = &Context;
VMContext.reset(new llvm::LLVMContext());
M.reset(new llvm::Module(MainFileName, *VMContext));
- M->setDataLayout(Ctx->getTargetInfo().getDataLayout());
+ M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
Builder.reset(new CodeGen::CodeGenModule(
*Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
@@ -245,7 +245,7 @@
return;
M->setTargetTriple(Ctx.getTargetInfo().getTriple().getTriple());
- M->setDataLayout(Ctx.getTargetInfo().getDataLayout());
+ M->setDataLayout(Ctx.getTargetInfo().getDataLayoutString());
// PCH files don't have a signature field in the control block,
// but LLVM detects DWO CUs by looking for a non-zero DWO id.
@@ -295,7 +295,7 @@
llvm::SmallString<0> Buffer;
clang::EmitBackendOutput(
Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
- Ctx.getTargetInfo().getDataLayout(), M.get(),
+ Ctx.getTargetInfo().getDataLayoutString(), M.get(),
BackendAction::Backend_EmitLL,
std::make_unique<llvm::raw_svector_ostream>(Buffer));
llvm::dbgs() << Buffer;
@@ -303,9 +303,9 @@
// Use the LLVM backend to emit the pch container.
clang::EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts,
- LangOpts, Ctx.getTargetInfo().getDataLayout(),
- M.get(), BackendAction::Backend_EmitObj,
- std::move(OS));
+ LangOpts,
+ Ctx.getTargetInfo().getDataLayoutString(), M.get(),
+ BackendAction::Backend_EmitObj, std::move(OS));
// Free the memory for the temporary buffer.
llvm::SmallVector<char, 0> Empty;
diff --git a/src/llvm-project/clang/lib/CodeGen/SanitizerMetadata.cpp b/src/llvm-project/clang/lib/CodeGen/SanitizerMetadata.cpp
index cdf8337..009965a 100644
--- a/src/llvm-project/clang/lib/CodeGen/SanitizerMetadata.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/SanitizerMetadata.cpp
@@ -1,4 +1,4 @@
-//===--- SanitizerMetadata.cpp - Blacklist for sanitizers -----------------===//
+//===--- SanitizerMetadata.cpp - Ignored entities for sanitizers ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -34,15 +34,15 @@
bool IsExcluded) {
if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize))
return;
- IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init");
- IsExcluded |= CGM.isInSanitizerBlacklist(GV, Loc, Ty);
+ IsDynInit &= !CGM.isInNoSanitizeList(GV, Loc, Ty, "init");
+ IsExcluded |= CGM.isInNoSanitizeList(GV, Loc, Ty);
llvm::Metadata *LocDescr = nullptr;
llvm::Metadata *GlobalName = nullptr;
llvm::LLVMContext &VMContext = CGM.getLLVMContext();
if (!IsExcluded) {
- // Don't generate source location and global name if it is blacklisted -
- // it won't be instrumented anyway.
+ // Don't generate source location and global name if it is on
+ // the NoSanitizeList - it won't be instrumented anyway.
LocDescr = getLocationMetadata(Loc);
if (!Name.empty())
GlobalName = llvm::MDString::get(VMContext, Name);
diff --git a/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp b/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp
index bcd2429..d2cc0a6 100644
--- a/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/TargetInfo.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/Builtins.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/CodeGen/SwiftCallingConv.h"
#include "llvm/ADT/SmallBitVector.h"
@@ -30,6 +31,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IntrinsicsNVPTX.h"
+#include "llvm/IR/IntrinsicsS390.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm> // std::sort
@@ -1103,6 +1105,7 @@
bool IsWin32StructABI;
bool IsSoftFloatABI;
bool IsMCUABI;
+ bool IsLinuxABI;
unsigned DefaultNumRegisterParameters;
static bool isRegisterSize(unsigned Size) {
@@ -1165,9 +1168,9 @@
unsigned NumRegisterParameters, bool SoftFloatABI)
: SwiftABIInfo(CGT), IsDarwinVectorABI(DarwinVectorABI),
IsRetSmallStructInRegABI(RetSmallStructInRegABI),
- IsWin32StructABI(Win32StructABI),
- IsSoftFloatABI(SoftFloatABI),
+ IsWin32StructABI(Win32StructABI), IsSoftFloatABI(SoftFloatABI),
IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()),
+ IsLinuxABI(CGT.getTarget().getTriple().isOSLinux()),
DefaultNumRegisterParameters(NumRegisterParameters) {}
bool shouldPassIndirectlyForSwift(ArrayRef<llvm::Type*> scalars,
@@ -1592,6 +1595,14 @@
if (Align <= MinABIStackAlignInBytes)
return 0; // Use default alignment.
+ if (IsLinuxABI) {
+ // Exclude other System V OS (e.g Darwin, PS4 and FreeBSD) since we don't
+ // want to spend any effort dealing with the ramifications of ABI breaks.
+ //
+ // If the vector type is __m128/__m256/__m512, return the default alignment.
+ if (Ty->isVectorType() && (Align == 16 || Align == 32 || Align == 64))
+ return Align;
+ }
// On non-Darwin, the stack type alignment is always 4.
if (!IsDarwinVectorABI) {
// Set explicit alignment, since we may need to realign the top.
@@ -2599,7 +2610,7 @@
bool Quote = (Lib.find(' ') != StringRef::npos);
std::string ArgStr = Quote ? "\"" : "";
ArgStr += Lib;
- if (!Lib.endswith_lower(".lib") && !Lib.endswith_lower(".a"))
+ if (!Lib.endswith_insensitive(".lib") && !Lib.endswith_insensitive(".a"))
ArgStr += ".lib";
ArgStr += Quote ? "\"" : "";
return ArgStr;
@@ -3955,8 +3966,8 @@
uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8;
llvm::Value *Offset =
llvm::ConstantInt::get(CGF.Int32Ty, (SizeInBytes + 7) & ~7);
- overflow_arg_area = CGF.Builder.CreateGEP(overflow_arg_area, Offset,
- "overflow_arg_area.next");
+ overflow_arg_area = CGF.Builder.CreateGEP(CGF.Int8Ty, overflow_arg_area,
+ Offset, "overflow_arg_area.next");
CGF.Builder.CreateStore(overflow_arg_area, overflow_arg_area_p);
// AMD64-ABI 3.5.7p5: Step 11. Return the fetched type.
@@ -4050,8 +4061,10 @@
"Unexpected ABI info for mixed regs");
llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo);
llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi);
- llvm::Value *GPAddr = CGF.Builder.CreateGEP(RegSaveArea, gp_offset);
- llvm::Value *FPAddr = CGF.Builder.CreateGEP(RegSaveArea, fp_offset);
+ llvm::Value *GPAddr =
+ CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset);
+ llvm::Value *FPAddr =
+ CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset);
llvm::Value *RegLoAddr = TyLo->isFPOrFPVectorTy() ? FPAddr : GPAddr;
llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
@@ -4070,7 +4083,7 @@
RegAddr = CGF.Builder.CreateElementBitCast(Tmp, LTy);
} else if (neededInt) {
- RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, gp_offset),
+ RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset),
CharUnits::fromQuantity(8));
RegAddr = CGF.Builder.CreateElementBitCast(RegAddr, LTy);
@@ -4088,7 +4101,7 @@
}
} else if (neededSSE == 1) {
- RegAddr = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset),
+ RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset),
CharUnits::fromQuantity(16));
RegAddr = CGF.Builder.CreateElementBitCast(RegAddr, LTy);
} else {
@@ -4099,7 +4112,8 @@
// to assume that the slots are 16-byte aligned, since the stack is
// naturally 16-byte aligned and the prologue is expected to store
// all the SSE registers to the RSA.
- Address RegAddrLo = Address(CGF.Builder.CreateGEP(RegSaveArea, fp_offset),
+ Address RegAddrLo = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea,
+ fp_offset),
CharUnits::fromQuantity(16));
Address RegAddrHi =
CGF.Builder.CreateConstInBoundsByteGEP(RegAddrLo,
@@ -4150,7 +4164,12 @@
Address X86_64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const {
- return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+ // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
+ // not 1, 2, 4, or 8 bytes, must be passed by reference."
+ uint64_t Width = getContext().getTypeSize(Ty);
+ bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
+
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
CGF.getContext().getTypeInfoInChars(Ty),
CharUnits::fromQuantity(8),
/*allowHigherAlign*/ false);
@@ -4347,15 +4366,10 @@
Address WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const {
-
- bool IsIndirect = false;
-
// MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
// not 1, 2, 4, or 8 bytes, must be passed by reference."
- if (isAggregateTypeForABI(Ty) || Ty->isMemberPointerType()) {
- uint64_t Width = getContext().getTypeSize(Ty);
- IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
- }
+ uint64_t Width = getContext().getTypeSize(Ty);
+ bool IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
CGF.getContext().getTypeInfoInChars(Ty),
@@ -4561,10 +4575,6 @@
if (Ty->isAnyComplexType())
llvm::report_fatal_error("complex type is not supported on AIX yet");
- if (Ty->isVectorType())
- llvm::report_fatal_error(
- "vector types are not yet supported for variadic functions on AIX");
-
auto TypeInfo = getContext().getTypeInfoInChars(Ty);
TypeInfo.Align = getParamTypeAlignment(Ty);
@@ -5411,7 +5421,8 @@
bool isDarwinPCS() const { return Kind == DarwinPCS; }
ABIArgInfo classifyReturnType(QualType RetTy, bool IsVariadic) const;
- ABIArgInfo classifyArgumentType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy, bool IsVariadic,
+ unsigned CallingConvention) const;
ABIArgInfo coerceIllegalVector(QualType Ty) const;
bool isHomogeneousAggregateBaseType(QualType Ty) const override;
bool isHomogeneousAggregateSmallEnough(const Type *Ty,
@@ -5425,7 +5436,8 @@
classifyReturnType(FI.getReturnType(), FI.isVariadic());
for (auto &it : FI.arguments())
- it.info = classifyArgumentType(it.type);
+ it.info = classifyArgumentType(it.type, FI.isVariadic(),
+ FI.getCallingConvention());
}
Address EmitDarwinVAArg(Address VAListAddr, QualType Ty,
@@ -5514,6 +5526,20 @@
Fn->addFnAttr("branch-target-enforcement",
BPI.BranchTargetEnforcement ? "true" : "false");
}
+
+ bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
+ llvm::Type *Ty) const override {
+ if (CGF.getTarget().hasFeature("ls64")) {
+ auto *ST = dyn_cast<llvm::StructType>(Ty);
+ if (ST && ST->getNumElements() == 1) {
+ auto *AT = dyn_cast<llvm::ArrayType>(ST->getElementType(0));
+ if (AT && AT->getNumElements() == 8 &&
+ AT->getElementType()->isIntegerTy(64))
+ return true;
+ }
+ }
+ return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty);
+ }
};
class WindowsAArch64TargetCodeGenInfo : public AArch64TargetCodeGenInfo {
@@ -5628,7 +5654,9 @@
return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
}
-ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
+ABIArgInfo
+AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadic,
+ unsigned CallingConvention) const {
Ty = useFirstFieldIfTransparentUnion(Ty);
// Handle illegal vector types here.
@@ -5674,9 +5702,24 @@
// Homogeneous Floating-point Aggregates (HFAs) need to be expanded.
const Type *Base = nullptr;
uint64_t Members = 0;
- if (isHomogeneousAggregate(Ty, Base, Members)) {
+ bool IsWin64 = Kind == Win64 || CallingConvention == llvm::CallingConv::Win64;
+ bool IsWinVariadic = IsWin64 && IsVariadic;
+ // In variadic functions on Windows, all composite types are treated alike,
+ // no special handling of HFAs/HVAs.
+ if (!IsWinVariadic && isHomogeneousAggregate(Ty, Base, Members)) {
+ if (Kind != AArch64ABIInfo::AAPCS)
+ return ABIArgInfo::getDirect(
+ llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members));
+
+ // For alignment adjusted HFAs, cap the argument alignment to 16, leave it
+ // default otherwise.
+ unsigned Align =
+ getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
+ unsigned BaseAlign = getContext().getTypeAlignInChars(Base).getQuantity();
+ Align = (Align > BaseAlign && Align >= 16) ? 16 : 0;
return ABIArgInfo::getDirect(
- llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members));
+ llvm::ArrayType::get(CGT.ConvertType(QualType(Base, 0)), Members), 0,
+ nullptr, true, Align);
}
// Aggregates <= 16 bytes are passed directly in registers or on the stack.
@@ -5755,6 +5798,18 @@
if (getTarget().isRenderScriptTarget()) {
return coerceToIntArray(RetTy, getContext(), getVMContext());
}
+
+ if (Size <= 64 && getDataLayout().isLittleEndian()) {
+ // Composite types are returned in lower bits of a 64-bit register for LE,
+ // and in higher bits for BE. However, integer types are always returned
+ // in lower bits for both LE and BE, and they are not rounded up to
+ // 64-bits. We can skip rounding up of composite types for LE, but not for
+ // BE, otherwise composite types will be indistinguishable from integer
+ // types.
+ return ABIArgInfo::getDirect(
+ llvm::IntegerType::get(getVMContext(), Size));
+ }
+
unsigned Alignment = getContext().getTypeAlign(RetTy);
Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes
@@ -5831,10 +5886,10 @@
return Members <= 4;
}
-Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr,
- QualType Ty,
- CodeGenFunction &CGF) const {
- ABIArgInfo AI = classifyArgumentType(Ty);
+Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ ABIArgInfo AI = classifyArgumentType(Ty, /*IsVariadic=*/true,
+ CGF.CurFnInfo->getCallingConvention());
bool IsIndirect = AI.isIndirect();
llvm::Type *BaseTy = CGF.ConvertType(Ty);
@@ -5948,7 +6003,7 @@
Address reg_top_p =
CGF.Builder.CreateStructGEP(VAListAddr, reg_top_index, "reg_top_p");
reg_top = CGF.Builder.CreateLoad(reg_top_p, "reg_top");
- Address BaseAddr(CGF.Builder.CreateInBoundsGEP(reg_top, reg_offs),
+ Address BaseAddr(CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, reg_top, reg_offs),
CharUnits::fromQuantity(IsFPR ? 16 : 8));
Address RegAddr = Address::invalid();
llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty);
@@ -6046,8 +6101,8 @@
StackSize = TySize.alignTo(StackSlotSize);
llvm::Value *StackSizeC = CGF.Builder.getSize(StackSize);
- llvm::Value *NewStack =
- CGF.Builder.CreateInBoundsGEP(OnStackPtr, StackSizeC, "new_stack");
+ llvm::Value *NewStack = CGF.Builder.CreateInBoundsGEP(
+ CGF.Int8Ty, OnStackPtr, StackSizeC, "new_stack");
// Write the new value of __stack for the next call to va_arg
CGF.Builder.CreateStore(NewStack, stack_p);
@@ -6114,7 +6169,13 @@
Address AArch64ABIInfo::EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const {
- return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+ bool IsIndirect = false;
+
+ // Composites larger than 16 bytes are passed by reference.
+ if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) > 128)
+ IsIndirect = true;
+
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
CGF.getContext().getTypeInfoInChars(Ty),
CharUnits::fromQuantity(8),
/*allowHigherAlign*/ false);
@@ -6396,7 +6457,16 @@
return ABIArgInfo::getDirect(Ty, 0, nullptr, false);
}
}
- return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
+ unsigned Align = 0;
+ if (getABIKind() == ARMABIInfo::AAPCS ||
+ getABIKind() == ARMABIInfo::AAPCS_VFP) {
+ // For alignment adjusted HFAs, cap the argument alignment to 8, leave it
+ // default otherwise.
+ Align = getContext().getTypeUnadjustedAlignInChars(Ty).getQuantity();
+ unsigned BaseAlign = getContext().getTypeAlignInChars(Base).getQuantity();
+ Align = (Align > BaseAlign && Align >= 8) ? 8 : 0;
+ }
+ return ABIArgInfo::getDirect(nullptr, 0, nullptr, false, Align);
}
ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic,
@@ -7200,8 +7270,49 @@
SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
: TargetCodeGenInfo(
std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)) {}
-};
+ llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID,
+ CGBuilderTy &Builder,
+ CodeGenModule &CGM) const override {
+ assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
+ // Only use TDC in constrained FP mode.
+ if (!Builder.getIsFPConstrained())
+ return nullptr;
+
+ llvm::Type *Ty = V->getType();
+ if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) {
+ llvm::Module &M = CGM.getModule();
+ auto &Ctx = M.getContext();
+ llvm::Function *TDCFunc =
+ llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::s390_tdc, Ty);
+ unsigned TDCBits = 0;
+ switch (BuiltinID) {
+ case Builtin::BI__builtin_isnan:
+ TDCBits = 0xf;
+ break;
+ case Builtin::BIfinite:
+ case Builtin::BI__finite:
+ case Builtin::BIfinitef:
+ case Builtin::BI__finitef:
+ case Builtin::BIfinitel:
+ case Builtin::BI__finitel:
+ case Builtin::BI__builtin_isfinite:
+ TDCBits = 0xfc0;
+ break;
+ case Builtin::BI__builtin_isinf:
+ TDCBits = 0x30;
+ break;
+ default:
+ break;
+ }
+ if (TDCBits)
+ return Builder.CreateCall(
+ TDCFunc,
+ {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)});
+ }
+ return nullptr;
+ }
+};
}
bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {
@@ -7366,7 +7477,8 @@
// Update overflow_arg_area_ptr pointer
llvm::Value *NewOverflowArgArea =
- CGF.Builder.CreateGEP(OverflowArgArea.getPointer(), PaddedSizeV,
+ CGF.Builder.CreateGEP(OverflowArgArea.getElementType(),
+ OverflowArgArea.getPointer(), PaddedSizeV,
"overflow_arg_area");
CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
@@ -7416,7 +7528,7 @@
CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr");
llvm::Value *RegSaveArea =
CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area");
- Address RawRegAddr(CGF.Builder.CreateGEP(RegSaveArea, RegOffset,
+ Address RawRegAddr(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, RegOffset,
"raw_reg_addr"),
PaddedSize);
Address RegAddr =
@@ -7445,7 +7557,8 @@
// Update overflow_arg_area_ptr pointer
llvm::Value *NewOverflowArgArea =
- CGF.Builder.CreateGEP(OverflowArgArea.getPointer(), PaddedSizeV,
+ CGF.Builder.CreateGEP(OverflowArgArea.getElementType(),
+ OverflowArgArea.getPointer(), PaddedSizeV,
"overflow_arg_area");
CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);
CGF.EmitBranch(ContBlock);
@@ -8023,14 +8136,89 @@
}
//===----------------------------------------------------------------------===//
-// AVR ABI Implementation.
+// M68k ABI Implementation
//===----------------------------------------------------------------------===//
namespace {
+
+class M68kTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ M68kTargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const override;
+};
+
+} // namespace
+
+void M68kTargetCodeGenInfo::setTargetAttributes(
+ const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const {
+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+ if (const auto *attr = FD->getAttr<M68kInterruptAttr>()) {
+ // Handle 'interrupt' attribute:
+ llvm::Function *F = cast<llvm::Function>(GV);
+
+ // Step 1: Set ISR calling convention.
+ F->setCallingConv(llvm::CallingConv::M68k_INTR);
+
+ // Step 2: Add attributes goodness.
+ F->addFnAttr(llvm::Attribute::NoInline);
+
+ // Step 3: Emit ISR vector alias.
+ unsigned Num = attr->getNumber() / 2;
+ llvm::GlobalAlias::create(llvm::Function::ExternalLinkage,
+ "__isr_" + Twine(Num), F);
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// AVR ABI Implementation. Documented at
+// https://gcc.gnu.org/wiki/avr-gcc#Calling_Convention
+// https://gcc.gnu.org/wiki/avr-gcc#Reduced_Tiny
+//===----------------------------------------------------------------------===//
+
+namespace {
+class AVRABIInfo : public DefaultABIInfo {
+public:
+ AVRABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+
+ ABIArgInfo classifyReturnType(QualType Ty) const {
+ // A return struct with size less than or equal to 8 bytes is returned
+ // directly via registers R18-R25.
+ if (isAggregateTypeForABI(Ty) && getContext().getTypeSize(Ty) <= 64)
+ return ABIArgInfo::getDirect();
+ else
+ return DefaultABIInfo::classifyReturnType(Ty);
+ }
+
+ // Just copy the original implementation of DefaultABIInfo::computeInfo(),
+ // since DefaultABIInfo::classify{Return,Argument}Type() are not virtual.
+ void computeInfo(CGFunctionInfo &FI) const override {
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ for (auto &I : FI.arguments())
+ I.info = classifyArgumentType(I.type);
+ }
+};
+
class AVRTargetCodeGenInfo : public TargetCodeGenInfo {
public:
AVRTargetCodeGenInfo(CodeGenTypes &CGT)
- : TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
+ : TargetCodeGenInfo(std::make_unique<AVRABIInfo>(CGT)) {}
+
+ LangAS getGlobalVarAddressSpace(CodeGenModule &CGM,
+ const VarDecl *D) const override {
+ // Check if a global/static variable is defined within address space 1
+ // but not constant.
+ LangAS AS = D->getType().getAddressSpace();
+ if (isTargetAddressSpace(AS) && toTargetAddressSpace(AS) == 1 &&
+ !D->getType().isConstQualified())
+ CGM.getDiags().Report(D->getLocation(),
+ diag::err_verify_nonconst_addrspace)
+ << "__flash";
+ return TargetCodeGenInfo::getGlobalVarAddressSpace(CGM, D);
+ }
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const override {
@@ -8301,7 +8489,7 @@
// Add offset to the current pointer to access the argument.
__overflow_area_pointer =
- CGF.Builder.CreateGEP(__overflow_area_pointer, Offset);
+ CGF.Builder.CreateGEP(CGF.Int8Ty, __overflow_area_pointer, Offset);
llvm::Value *AsInt =
CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty);
@@ -8324,7 +8512,8 @@
uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4);
__overflow_area_pointer = CGF.Builder.CreateGEP(
- __overflow_area_pointer, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
+ CGF.Int8Ty, __overflow_area_pointer,
+ llvm::ConstantInt::get(CGF.Int32Ty, Offset),
"__overflow_area_pointer.next");
CGF.Builder.CreateStore(__overflow_area_pointer, __overflow_area_pointer_p);
@@ -8355,7 +8544,7 @@
uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4);
llvm::Value *NextAddr = Builder.CreateGEP(
- Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next");
+ CGF.Int8Ty, Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next");
Builder.CreateStore(NextAddr, VAListAddrAsBPP);
return AddrTyped;
@@ -8427,7 +8616,7 @@
}
llvm::Value *__new_saved_reg_area_pointer =
- CGF.Builder.CreateGEP(__current_saved_reg_area_pointer,
+ CGF.Builder.CreateGEP(CGF.Int8Ty, __current_saved_reg_area_pointer,
llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
"__new_saved_reg_area_pointer");
@@ -8483,7 +8672,8 @@
// Get the pointer for next argument in overflow area and store it
// to overflow area pointer.
llvm::Value *__new_overflow_area_pointer = CGF.Builder.CreateGEP(
- __overflow_area_pointer, llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
+ CGF.Int8Ty, __overflow_area_pointer,
+ llvm::ConstantInt::get(CGF.Int32Ty, ArgSize),
"__overflow_area_pointer.next");
CGF.Builder.CreateStore(__new_overflow_area_pointer,
@@ -8998,9 +9188,13 @@
assert(Max == 0 && "Max must be zero");
} else if (IsOpenCLKernel || IsHIPKernel) {
// By default, restrict the maximum size to a value specified by
- // --gpu-max-threads-per-block=n or its default value.
+ // --gpu-max-threads-per-block=n or its default value for HIP.
+ const unsigned OpenCLDefaultMaxWorkGroupSize = 256;
+ const unsigned DefaultMaxWorkGroupSize =
+ IsOpenCLKernel ? OpenCLDefaultMaxWorkGroupSize
+ : M.getLangOpts().GPUMaxThreadsPerBlock;
std::string AttrVal =
- std::string("1,") + llvm::utostr(M.getLangOpts().GPUMaxThreadsPerBlock);
+ std::string("1,") + llvm::utostr(DefaultMaxWorkGroupSize);
F->addFnAttr("amdgpu-flat-work-group-size", AttrVal);
}
@@ -9039,6 +9233,9 @@
if (M.getContext().getTargetInfo().allowAMDGPUUnsafeFPAtomics())
F->addFnAttr("amdgpu-unsafe-fp-atomics", "true");
+
+ if (!getABIInfo().getCodeGenOpts().EmitIEEENaNCompliantInsts)
+ F->addFnAttr("amdgpu-ieee", "false");
}
unsigned AMDGPUTargetCodeGenInfo::getOpenCLKernelCallingConv() const {
@@ -9941,6 +10138,12 @@
public:
SPIRTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
: TargetCodeGenInfo(std::make_unique<SPIRABIInfo>(CGT)) {}
+
+ LangAS getASTAllocaAddressSpace() const override {
+ return getLangASFromTargetAS(
+ getABIInfo().getDataLayout().getAllocaAddrSpace());
+ }
+
unsigned getOpenCLKernelCallingConv() const override;
};
@@ -10620,8 +10823,8 @@
llvm::Type *Field2Ty = nullptr;
CharUnits Field1Off = CharUnits::Zero();
CharUnits Field2Off = CharUnits::Zero();
- int NeededArgGPRs;
- int NeededArgFPRs;
+ int NeededArgGPRs = 0;
+ int NeededArgFPRs = 0;
bool IsCandidate =
detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off,
NeededArgGPRs, NeededArgFPRs);
@@ -10845,6 +11048,8 @@
case llvm::Triple::le32:
return SetCGInfo(new PNaClTargetCodeGenInfo(Types));
+ case llvm::Triple::m68k:
+ return SetCGInfo(new M68kTargetCodeGenInfo(Types));
case llvm::Triple::mips:
case llvm::Triple::mipsel:
if (Triple.getOS() == llvm::Triple::NaCl)
diff --git a/src/llvm-project/clang/lib/CodeGen/TargetInfo.h b/src/llvm-project/clang/lib/CodeGen/TargetInfo.h
index 0df9667..aa8bbb6 100644
--- a/src/llvm-project/clang/lib/CodeGen/TargetInfo.h
+++ b/src/llvm-project/clang/lib/CodeGen/TargetInfo.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
#define LLVM_CLANG_LIB_CODEGEN_TARGETINFO_H
+#include "CGBuilder.h"
#include "CodeGenModule.h"
#include "CGValue.h"
#include "clang/AST/Type.h"
@@ -126,6 +127,16 @@
return Address;
}
+ /// Performs a target specific test of a floating point value for things
+ /// like IsNaN, Infinity, ... Nullptr is returned if no implementation
+ /// exists.
+ virtual llvm::Value *
+ testFPKind(llvm::Value *V, unsigned BuiltinID, CGBuilderTy &Builder,
+ CodeGenModule &CGM) const {
+ assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");
+ return nullptr;
+ }
+
/// Corrects the low-level LLVM type for a given constraint and "usual"
/// type.
///
@@ -137,6 +148,13 @@
return Ty;
}
+ /// Target hook to decide whether an inline asm operand can be passed
+ /// by value.
+ virtual bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF,
+ llvm::Type *Ty) const {
+ return false;
+ }
+
/// Adds constraints and types for result registers.
virtual void addReturnRegisterOutputs(
CodeGen::CodeGenFunction &CGF, CodeGen::LValue ReturnValue,
diff --git a/src/llvm-project/clang/lib/CodeGen/VarBypassDetector.cpp b/src/llvm-project/clang/lib/CodeGen/VarBypassDetector.cpp
index f3a172e..e8717a6 100644
--- a/src/llvm-project/clang/lib/CodeGen/VarBypassDetector.cpp
+++ b/src/llvm-project/clang/lib/CodeGen/VarBypassDetector.cpp
@@ -1,4 +1,4 @@
-//===--- VarBypassDetector.h - Bypass jumps detector --------------*- C++ -*-=//
+//===--- VarBypassDetector.cpp - Bypass jumps detector ------------*- C++ -*-=//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/clang/lib/CodeGen/VarBypassDetector.h b/src/llvm-project/clang/lib/CodeGen/VarBypassDetector.h
index 8a2e388..b654eef 100644
--- a/src/llvm-project/clang/lib/CodeGen/VarBypassDetector.h
+++ b/src/llvm-project/clang/lib/CodeGen/VarBypassDetector.h
@@ -1,4 +1,4 @@
-//===--- VarBypassDetector.cpp - Bypass jumps detector ------------*- C++ -*-=//
+//===--- VarBypassDetector.h - Bypass jumps detector --------------*- C++ -*-=//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/clang/lib/CrossTU/CrossTranslationUnit.cpp b/src/llvm-project/clang/lib/CrossTU/CrossTranslationUnit.cpp
index e27779f..0aecad4 100644
--- a/src/llvm-project/clang/lib/CrossTU/CrossTranslationUnit.cpp
+++ b/src/llvm-project/clang/lib/CrossTU/CrossTranslationUnit.cpp
@@ -92,6 +92,10 @@
std::string message(int Condition) const override {
switch (static_cast<index_error_code>(Condition)) {
+ case index_error_code::success:
+ // There should not be a success error. Jump to unreachable directly.
+ // Add this case to make the compiler stop complaining.
+ break;
case index_error_code::unspecified:
return "An unknown error has occurred.";
case index_error_code::missing_index_file:
@@ -630,7 +634,7 @@
SmallString<32> NativeSourcePath(SourcePath);
llvm::sys::path::native(NativeSourcePath, PathStyle);
- StringRef InvocationKey(NativeSourcePath);
+ StringRef InvocationKey = NativeSourcePath;
if (InvocationList.find(InvocationKey) != InvocationList.end())
return llvm::make_error<IndexError>(
@@ -667,12 +671,15 @@
/// Lazily initialize the invocation list member used for on-demand parsing.
if (InvocationList)
return llvm::Error::success();
+ if (index_error_code::success != PreviousParsingResult)
+ return llvm::make_error<IndexError>(PreviousParsingResult);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileContent =
llvm::MemoryBuffer::getFile(InvocationListFilePath);
- if (!FileContent)
- return llvm::make_error<IndexError>(
- index_error_code::invocation_list_file_not_found);
+ if (!FileContent) {
+ PreviousParsingResult = index_error_code::invocation_list_file_not_found;
+ return llvm::make_error<IndexError>(PreviousParsingResult);
+ }
std::unique_ptr<llvm::MemoryBuffer> ContentBuffer = std::move(*FileContent);
assert(ContentBuffer && "If no error was produced after loading, the pointer "
"should not be nullptr.");
@@ -680,8 +687,13 @@
llvm::Expected<InvocationListTy> ExpectedInvocationList =
parseInvocationList(ContentBuffer->getBuffer(), PathStyle);
- if (!ExpectedInvocationList)
- return ExpectedInvocationList.takeError();
+ // Handle the error to store the code for next call to this function.
+ if (!ExpectedInvocationList) {
+ llvm::handleAllErrors(
+ ExpectedInvocationList.takeError(),
+ [&](const IndexError &E) { PreviousParsingResult = E.getCode(); });
+ return llvm::make_error<IndexError>(PreviousParsingResult);
+ }
InvocationList = *ExpectedInvocationList;
@@ -754,31 +766,15 @@
ASTImporter *NewImporter = new ASTImporter(
Context, Context.getSourceManager().getFileManager(), From,
From.getSourceManager().getFileManager(), false, ImporterSharedSt);
- NewImporter->setFileIDImportHandler([this, Unit](FileID ToID, FileID FromID) {
- assert(ImportedFileIDs.find(ToID) == ImportedFileIDs.end() &&
- "FileID already imported, should not happen.");
- ImportedFileIDs[ToID] = std::make_pair(FromID, Unit);
- });
ASTUnitImporterMap[From.getTranslationUnitDecl()].reset(NewImporter);
return *NewImporter;
}
-llvm::Optional<std::pair<SourceLocation, ASTUnit *>>
-CrossTranslationUnitContext::getImportedFromSourceLocation(
+llvm::Optional<clang::MacroExpansionContext>
+CrossTranslationUnitContext::getMacroExpansionContextForSourceLocation(
const clang::SourceLocation &ToLoc) const {
- const SourceManager &SM = Context.getSourceManager();
- auto DecToLoc = SM.getDecomposedLoc(ToLoc);
-
- auto I = ImportedFileIDs.find(DecToLoc.first);
- if (I == ImportedFileIDs.end())
- return {};
-
- FileID FromID = I->second.first;
- clang::ASTUnit *Unit = I->second.second;
- SourceLocation FromLoc =
- Unit->getSourceManager().getComposedLoc(FromID, DecToLoc.second);
-
- return std::make_pair(FromLoc, Unit);
+ // FIXME: Implement: Record such a context for every imported ASTUnit; lookup.
+ return llvm::None;
}
} // namespace cross_tu
diff --git a/src/llvm-project/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp b/src/llvm-project/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
index 176d6d6..963256f 100644
--- a/src/llvm-project/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
+++ b/src/llvm-project/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
@@ -14,6 +14,7 @@
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
#include <atomic>
#include <condition_variable>
diff --git a/src/llvm-project/clang/lib/DirectoryWatcher/windows/DirectoryWatcher-windows.cpp b/src/llvm-project/clang/lib/DirectoryWatcher/windows/DirectoryWatcher-windows.cpp
index 25cbcf5..1f040f6 100644
--- a/src/llvm-project/clang/lib/DirectoryWatcher/windows/DirectoryWatcher-windows.cpp
+++ b/src/llvm-project/clang/lib/DirectoryWatcher/windows/DirectoryWatcher-windows.cpp
@@ -6,19 +6,12 @@
//
//===----------------------------------------------------------------------===//
-// TODO: This is not yet an implementation, but it will make it so Windows
-// builds don't fail.
-
#include "DirectoryScanner.h"
#include "clang/DirectoryWatcher/DirectoryWatcher.h"
-
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/ScopeExit.h"
-#include "llvm/Support/AlignOf.h"
-#include "llvm/Support/Errno.h"
-#include "llvm/Support/Mutex.h"
+#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Path.h"
-#include <atomic>
+#include "llvm/Support/Windows/WindowsSupport.h"
#include <condition_variable>
#include <mutex>
#include <queue>
@@ -28,23 +21,271 @@
namespace {
+using DirectoryWatcherCallback =
+ std::function<void(llvm::ArrayRef<clang::DirectoryWatcher::Event>, bool)>;
+
using namespace llvm;
using namespace clang;
class DirectoryWatcherWindows : public clang::DirectoryWatcher {
+ OVERLAPPED Overlapped;
+
+ std::vector<DWORD> Notifications;
+
+ std::thread WatcherThread;
+ std::thread HandlerThread;
+ std::function<void(ArrayRef<DirectoryWatcher::Event>, bool)> Callback;
+ SmallString<MAX_PATH> Path;
+ HANDLE Terminate;
+
+ std::mutex Mutex;
+ bool WatcherActive = false;
+ std::condition_variable Ready;
+
+ class EventQueue {
+ std::mutex M;
+ std::queue<DirectoryWatcher::Event> Q;
+ std::condition_variable CV;
+
+ public:
+ void emplace(DirectoryWatcher::Event::EventKind Kind, StringRef Path) {
+ {
+ std::unique_lock<std::mutex> L(M);
+ Q.emplace(Kind, Path);
+ }
+ CV.notify_one();
+ }
+
+ DirectoryWatcher::Event pop_front() {
+ std::unique_lock<std::mutex> L(M);
+ while (true) {
+ if (!Q.empty()) {
+ DirectoryWatcher::Event E = Q.front();
+ Q.pop();
+ return E;
+ }
+ CV.wait(L, [this]() { return !Q.empty(); });
+ }
+ }
+ } Q;
+
public:
- ~DirectoryWatcherWindows() override { }
- void InitialScan() { }
- void EventReceivingLoop() { }
- void StopWork() { }
+ DirectoryWatcherWindows(HANDLE DirectoryHandle, bool WaitForInitialSync,
+ DirectoryWatcherCallback Receiver);
+
+ ~DirectoryWatcherWindows() override;
+
+ void InitialScan();
+ void WatcherThreadProc(HANDLE DirectoryHandle);
+ void NotifierThreadProc(bool WaitForInitialSync);
};
+
+DirectoryWatcherWindows::DirectoryWatcherWindows(
+ HANDLE DirectoryHandle, bool WaitForInitialSync,
+ DirectoryWatcherCallback Receiver)
+ : Callback(Receiver), Terminate(INVALID_HANDLE_VALUE) {
+ // Pre-compute the real location as we will be handing over the directory
+ // handle to the watcher and performing synchronous operations.
+ {
+ DWORD Size = GetFinalPathNameByHandleW(DirectoryHandle, NULL, 0, 0);
+ std::unique_ptr<WCHAR[]> Buffer{new WCHAR[Size]};
+ Size = GetFinalPathNameByHandleW(DirectoryHandle, Buffer.get(), Size, 0);
+ Buffer[Size] = L'\0';
+ llvm::sys::windows::UTF16ToUTF8(Buffer.get(), Size, Path);
+ }
+
+ size_t EntrySize = sizeof(FILE_NOTIFY_INFORMATION) + MAX_PATH * sizeof(WCHAR);
+ Notifications.resize((4 * EntrySize) / sizeof(DWORD));
+
+ memset(&Overlapped, 0, sizeof(Overlapped));
+ Overlapped.hEvent =
+ CreateEventW(NULL, /*bManualReset=*/FALSE, /*bInitialState=*/FALSE, NULL);
+ assert(Overlapped.hEvent && "unable to create event");
+
+ Terminate =
+ CreateEventW(NULL, /*bManualReset=*/TRUE, /*bInitialState=*/FALSE, NULL);
+
+ WatcherThread = std::thread([this, DirectoryHandle]() {
+ this->WatcherThreadProc(DirectoryHandle);
+ });
+
+ if (WaitForInitialSync)
+ InitialScan();
+
+ HandlerThread = std::thread([this, WaitForInitialSync]() {
+ this->NotifierThreadProc(WaitForInitialSync);
+ });
+}
+
+DirectoryWatcherWindows::~DirectoryWatcherWindows() {
+ // Signal the Watcher to exit.
+ SetEvent(Terminate);
+ HandlerThread.join();
+ WatcherThread.join();
+ CloseHandle(Terminate);
+ CloseHandle(Overlapped.hEvent);
+}
+
+void DirectoryWatcherWindows::InitialScan() {
+ std::unique_lock<std::mutex> lock(Mutex);
+ Ready.wait(lock, [this] { return this->WatcherActive; });
+
+ Callback(getAsFileEvents(scanDirectory(Path.data())), /*IsInitial=*/true);
+}
+
+void DirectoryWatcherWindows::WatcherThreadProc(HANDLE DirectoryHandle) {
+ while (true) {
+ // We do not guarantee subdirectories, but macOS already provides
+ // subdirectories, might as well as ...
+ BOOL WatchSubtree = TRUE;
+ DWORD NotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME
+ | FILE_NOTIFY_CHANGE_DIR_NAME
+ | FILE_NOTIFY_CHANGE_SIZE
+ | FILE_NOTIFY_CHANGE_LAST_WRITE
+ | FILE_NOTIFY_CHANGE_CREATION;
+
+ DWORD BytesTransferred;
+ if (!ReadDirectoryChangesW(DirectoryHandle, Notifications.data(),
+ Notifications.size() * sizeof(DWORD),
+ WatchSubtree, NotifyFilter, &BytesTransferred,
+ &Overlapped, NULL)) {
+ Q.emplace(DirectoryWatcher::Event::EventKind::WatcherGotInvalidated,
+ "");
+ break;
+ }
+
+ if (!WatcherActive) {
+ std::unique_lock<std::mutex> lock(Mutex);
+ WatcherActive = true;
+ }
+ Ready.notify_one();
+
+ HANDLE Handles[2] = { Terminate, Overlapped.hEvent };
+ switch (WaitForMultipleObjects(2, Handles, FALSE, INFINITE)) {
+ case WAIT_OBJECT_0: // Terminate Request
+ case WAIT_FAILED: // Failure
+ Q.emplace(DirectoryWatcher::Event::EventKind::WatcherGotInvalidated,
+ "");
+ (void)CloseHandle(DirectoryHandle);
+ return;
+ case WAIT_TIMEOUT: // Spurious wakeup?
+ continue;
+ case WAIT_OBJECT_0 + 1: // Directory change
+ break;
+ }
+
+ if (!GetOverlappedResult(DirectoryHandle, &Overlapped, &BytesTransferred,
+ FALSE)) {
+ Q.emplace(DirectoryWatcher::Event::EventKind::WatchedDirRemoved,
+ "");
+ Q.emplace(DirectoryWatcher::Event::EventKind::WatcherGotInvalidated,
+ "");
+ break;
+ }
+
+ // There was a buffer underrun on the kernel side. We may have lost
+ // events, please re-synchronize.
+ if (BytesTransferred == 0) {
+ Q.emplace(DirectoryWatcher::Event::EventKind::WatcherGotInvalidated,
+ "");
+ break;
+ }
+
+ for (FILE_NOTIFY_INFORMATION *I =
+ (FILE_NOTIFY_INFORMATION *)Notifications.data();
+ I;
+ I = I->NextEntryOffset
+ ? (FILE_NOTIFY_INFORMATION *)((CHAR *)I + I->NextEntryOffset)
+ : NULL) {
+ DirectoryWatcher::Event::EventKind Kind =
+ DirectoryWatcher::Event::EventKind::WatcherGotInvalidated;
+ switch (I->Action) {
+ case FILE_ACTION_ADDED:
+ case FILE_ACTION_MODIFIED:
+ case FILE_ACTION_RENAMED_NEW_NAME:
+ Kind = DirectoryWatcher::Event::EventKind::Modified;
+ break;
+ case FILE_ACTION_REMOVED:
+ case FILE_ACTION_RENAMED_OLD_NAME:
+ Kind = DirectoryWatcher::Event::EventKind::Removed;
+ break;
+ }
+
+ SmallString<MAX_PATH> filename;
+ sys::windows::UTF16ToUTF8(I->FileName, I->FileNameLength / sizeof(WCHAR),
+ filename);
+ Q.emplace(Kind, filename);
+ }
+ }
+
+ (void)CloseHandle(DirectoryHandle);
+}
+
+void DirectoryWatcherWindows::NotifierThreadProc(bool WaitForInitialSync) {
+ // If we did not wait for the initial sync, then we should perform the
+ // scan when we enter the thread.
+ if (!WaitForInitialSync)
+ this->InitialScan();
+
+ while (true) {
+ DirectoryWatcher::Event E = Q.pop_front();
+ Callback(E, /*IsInitial=*/false);
+ if (E.Kind == DirectoryWatcher::Event::EventKind::WatcherGotInvalidated)
+ break;
+ }
+}
+
+auto error(DWORD ErrorCode) {
+ DWORD Flags = FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS;
+
+ LPSTR Buffer;
+ if (!FormatMessageA(Flags, NULL, ErrorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&Buffer,
+ 0, NULL)) {
+ return make_error<llvm::StringError>("error " + utostr(ErrorCode),
+ inconvertibleErrorCode());
+ }
+ std::string Message{Buffer};
+ LocalFree(Buffer);
+ return make_error<llvm::StringError>(Message, inconvertibleErrorCode());
+}
+
} // namespace
llvm::Expected<std::unique_ptr<DirectoryWatcher>>
-clang::DirectoryWatcher::create(
- StringRef Path,
- std::function<void(llvm::ArrayRef<DirectoryWatcher::Event>, bool)> Receiver,
- bool WaitForInitialSync) {
- return llvm::Expected<std::unique_ptr<DirectoryWatcher>>(
- llvm::errorCodeToError(std::make_error_code(std::errc::not_supported)));
+clang::DirectoryWatcher::create(StringRef Path,
+ DirectoryWatcherCallback Receiver,
+ bool WaitForInitialSync) {
+ if (Path.empty())
+ llvm::report_fatal_error(
+ "DirectoryWatcher::create can not accept an empty Path.");
+
+ if (!sys::fs::is_directory(Path))
+ llvm::report_fatal_error(
+ "DirectoryWatcher::create can not accept a filepath.");
+
+ SmallVector<wchar_t, MAX_PATH> WidePath;
+ if (sys::windows::UTF8ToUTF16(Path, WidePath))
+ return llvm::make_error<llvm::StringError>(
+ "unable to convert path to UTF-16", llvm::inconvertibleErrorCode());
+
+ DWORD DesiredAccess = FILE_LIST_DIRECTORY;
+ DWORD ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ DWORD CreationDisposition = OPEN_EXISTING;
+ DWORD FlagsAndAttributes = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
+
+ HANDLE DirectoryHandle =
+ CreateFileW(WidePath.data(), DesiredAccess, ShareMode,
+ /*lpSecurityAttributes=*/NULL, CreationDisposition,
+ FlagsAndAttributes, NULL);
+ if (DirectoryHandle == INVALID_HANDLE_VALUE)
+ return error(GetLastError());
+
+ // NOTE: We use the watcher instance as a RAII object to discard the handles
+ // for the directory in case of an error. Hence, this is early allocated,
+ // with the state being written directly to the watcher.
+ return std::make_unique<DirectoryWatcherWindows>(
+ DirectoryHandle, WaitForInitialSync, Receiver);
}
diff --git a/src/llvm-project/clang/lib/Driver/Action.cpp b/src/llvm-project/clang/lib/Driver/Action.cpp
index 2ec063d..e2d2f6c 100644
--- a/src/llvm-project/clang/lib/Driver/Action.cpp
+++ b/src/llvm-project/clang/lib/Driver/Action.cpp
@@ -165,8 +165,8 @@
void InputAction::anchor() {}
-InputAction::InputAction(const Arg &_Input, types::ID _Type)
- : Action(InputClass, _Type), Input(_Input) {}
+InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)
+ : Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {}
void BindArchAction::anchor() {}
diff --git a/src/llvm-project/clang/lib/Driver/CMakeLists.txt b/src/llvm-project/clang/lib/Driver/CMakeLists.txt
index aeffcf0..08be9f0 100644
--- a/src/llvm-project/clang/lib/Driver/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/Driver/CMakeLists.txt
@@ -13,7 +13,6 @@
add_clang_library(clangDriver
Action.cpp
Compilation.cpp
- DarwinSDKInfo.cpp
Distro.cpp
Driver.cpp
DriverOptions.cpp
@@ -26,6 +25,7 @@
ToolChain.cpp
ToolChains/Arch/AArch64.cpp
ToolChains/Arch/ARM.cpp
+ ToolChains/Arch/M68k.cpp
ToolChains/Arch/Mips.cpp
ToolChains/Arch/PPC.cpp
ToolChains/Arch/RISCV.cpp
@@ -36,6 +36,7 @@
ToolChains/AIX.cpp
ToolChains/Ananas.cpp
ToolChains/AMDGPU.cpp
+ ToolChains/AMDGPUOpenMP.cpp
ToolChains/AVR.cpp
ToolChains/BareMetal.cpp
ToolChains/Clang.cpp
diff --git a/src/llvm-project/clang/lib/Driver/Compilation.cpp b/src/llvm-project/clang/lib/Driver/Compilation.cpp
index d330557..0144d80 100644
--- a/src/llvm-project/clang/lib/Driver/Compilation.cpp
+++ b/src/llvm-project/clang/lib/Driver/Compilation.cpp
@@ -170,11 +170,12 @@
// Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
// output stream.
- if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
+ if (getDriver().CCPrintOptions &&
+ !getDriver().CCPrintOptionsFilename.empty()) {
std::error_code EC;
OwnedStream.reset(new llvm::raw_fd_ostream(
- getDriver().CCPrintOptionsFilename, EC,
- llvm::sys::fs::OF_Append | llvm::sys::fs::OF_Text));
+ getDriver().CCPrintOptionsFilename.c_str(), EC,
+ llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF));
if (EC) {
getDriver().Diag(diag::err_drv_cc_print_options_failure)
<< EC.message();
diff --git a/src/llvm-project/clang/lib/Driver/DarwinSDKInfo.cpp b/src/llvm-project/clang/lib/Driver/DarwinSDKInfo.cpp
deleted file mode 100644
index 761c671..0000000
--- a/src/llvm-project/clang/lib/Driver/DarwinSDKInfo.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Driver/DarwinSDKInfo.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-
-using namespace clang::driver;
-using namespace clang;
-
-Expected<Optional<DarwinSDKInfo>>
-driver::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) {
- llvm::SmallString<256> Filepath = SDKRootPath;
- llvm::sys::path::append(Filepath, "SDKSettings.json");
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
- VFS.getBufferForFile(Filepath);
- if (!File) {
- // If the file couldn't be read, assume it just doesn't exist.
- return None;
- }
- Expected<llvm::json::Value> Result =
- llvm::json::parse(File.get()->getBuffer());
- if (!Result)
- return Result.takeError();
-
- if (const auto *Obj = Result->getAsObject()) {
- auto VersionString = Obj->getString("Version");
- if (VersionString) {
- VersionTuple Version;
- if (!Version.tryParse(*VersionString))
- return DarwinSDKInfo(Version);
- }
- }
- return llvm::make_error<llvm::StringError>("invalid SDKSettings.json",
- llvm::inconvertibleErrorCode());
-}
diff --git a/src/llvm-project/clang/lib/Driver/Distro.cpp b/src/llvm-project/clang/lib/Driver/Distro.cpp
index ee4fe84..c4cf4e4 100644
--- a/src/llvm-project/clang/lib/Driver/Distro.cpp
+++ b/src/llvm-project/clang/lib/Driver/Distro.cpp
@@ -36,6 +36,7 @@
for (StringRef Line : Lines)
if (Version == Distro::UnknownDistro && Line.startswith("ID="))
Version = llvm::StringSwitch<Distro::DistroType>(Line.substr(3))
+ .Case("alpine", Distro::AlpineLinux)
.Case("fedora", Distro::Fedora)
.Case("gentoo", Distro::Gentoo)
.Case("arch", Distro::ArchLinux)
@@ -88,6 +89,7 @@
.Case("focal", Distro::UbuntuFocal)
.Case("groovy", Distro::UbuntuGroovy)
.Case("hirsute", Distro::UbuntuHirsute)
+ .Case("impish", Distro::UbuntuImpish)
.Default(Distro::UnknownDistro);
return Version;
}
@@ -188,15 +190,6 @@
}
// ...and others.
- if (VFS.exists("/etc/exherbo-release"))
- return Distro::Exherbo;
-
- if (VFS.exists("/etc/alpine-release"))
- return Distro::AlpineLinux;
-
- if (VFS.exists("/etc/arch-release"))
- return Distro::ArchLinux;
-
if (VFS.exists("/etc/gentoo-release"))
return Distro::Gentoo;
diff --git a/src/llvm-project/clang/lib/Driver/Driver.cpp b/src/llvm-project/clang/lib/Driver/Driver.cpp
index 418e1d3..5c323cb 100644
--- a/src/llvm-project/clang/lib/Driver/Driver.cpp
+++ b/src/llvm-project/clang/lib/Driver/Driver.cpp
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Driver.h"
-#include "InputInfo.h"
#include "ToolChains/AIX.h"
#include "ToolChains/AMDGPU.h"
+#include "ToolChains/AMDGPUOpenMP.h"
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
#include "ToolChains/BareMetal.h"
@@ -53,6 +53,7 @@
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
@@ -62,6 +63,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/llvm-config.h"
@@ -76,6 +78,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
@@ -133,13 +136,13 @@
: Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
- DriverTitle(Title), CCPrintOptionsFilename(nullptr),
- CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
+ DriverTitle(Title), CCPrintStatReportFilename(), CCPrintOptionsFilename(),
+ CCPrintHeadersFilename(), CCLogDiagnosticsFilename(),
CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false),
CCLogDiagnostics(false), CCGenDiagnostics(false),
- TargetTriple(TargetTriple), CCCGenericGCCName(""), Saver(Alloc),
- CheckInputsExist(true), GenReproducer(false),
- SuppressMissingInputWarning(false) {
+ CCPrintProcessStats(false), TargetTriple(TargetTriple),
+ CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true),
+ GenReproducer(false), SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
this->VFS = llvm::vfs::getRealFileSystem();
@@ -166,28 +169,9 @@
ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
}
-void Driver::ParseDriverMode(StringRef ProgramName,
- ArrayRef<const char *> Args) {
- if (ClangNameParts.isEmpty())
- ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName);
- setDriverModeFromOption(ClangNameParts.DriverMode);
-
- for (const char *ArgPtr : Args) {
- // Ignore nullptrs, they are the response file's EOL markers.
- if (ArgPtr == nullptr)
- continue;
- const StringRef Arg = ArgPtr;
- setDriverModeFromOption(Arg);
- }
-}
-
-void Driver::setDriverModeFromOption(StringRef Opt) {
- const std::string OptName =
+void Driver::setDriverMode(StringRef Value) {
+ static const std::string OptName =
getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
- if (!Opt.startswith(OptName))
- return;
- StringRef Value = Opt.drop_front(OptName.size());
-
if (auto M = llvm::StringSwitch<llvm::Optional<DriverMode>>(Value)
.Case("gcc", GCCMode)
.Case("g++", GXXMode)
@@ -517,14 +501,21 @@
AT = Target.get64BitArchVariant().getArch();
if (Target.getEnvironment() == llvm::Triple::GNUX32)
Target.setEnvironment(llvm::Triple::GNU);
+ else if (Target.getEnvironment() == llvm::Triple::MuslX32)
+ Target.setEnvironment(llvm::Triple::Musl);
} else if (A->getOption().matches(options::OPT_mx32) &&
Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
AT = llvm::Triple::x86_64;
- Target.setEnvironment(llvm::Triple::GNUX32);
+ if (Target.getEnvironment() == llvm::Triple::Musl)
+ Target.setEnvironment(llvm::Triple::MuslX32);
+ else
+ Target.setEnvironment(llvm::Triple::GNUX32);
} else if (A->getOption().matches(options::OPT_m32)) {
AT = Target.get32BitArchVariant().getArch();
if (Target.getEnvironment() == llvm::Triple::GNUX32)
Target.setEnvironment(llvm::Triple::GNU);
+ else if (Target.getEnvironment() == llvm::Triple::MuslX32)
+ Target.setEnvironment(llvm::Triple::Musl);
} else if (A->getOption().matches(options::OPT_m16) &&
Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
AT = llvm::Triple::x86;
@@ -582,9 +573,9 @@
A = Args.getLastArg(options::OPT_march_EQ);
if (A && Target.isRISCV()) {
StringRef ArchName = A->getValue();
- if (ArchName.startswith_lower("rv32"))
+ if (ArchName.startswith_insensitive("rv32"))
Target.setArch(llvm::Triple::riscv32);
- else if (ArchName.startswith_lower("rv64"))
+ else if (ArchName.startswith_insensitive("rv64"))
Target.setArch(llvm::Triple::riscv64);
}
@@ -592,16 +583,24 @@
}
// Parse the LTO options and record the type of LTO compilation
-// based on which -f(no-)?lto(=.*)? option occurs last.
-void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
- LTOMode = LTOK_None;
- if (!Args.hasFlag(options::OPT_flto, options::OPT_flto_EQ,
- options::OPT_fno_lto, false))
- return;
+// based on which -f(no-)?lto(=.*)? or -f(no-)?offload-lto(=.*)?
+// option occurs last.
+static llvm::Optional<driver::LTOKind>
+parseLTOMode(Driver &D, const llvm::opt::ArgList &Args, OptSpecifier OptPos,
+ OptSpecifier OptNeg, OptSpecifier OptEq, bool IsOffload) {
+ driver::LTOKind LTOMode = LTOK_None;
+ // Non-offload LTO allows -flto=auto and -flto=jobserver. Offload LTO does
+ // not support those options.
+ if (!Args.hasFlag(OptPos, OptEq, OptNeg, false) &&
+ (IsOffload ||
+ (!Args.hasFlag(options::OPT_flto_EQ_auto, options::OPT_fno_lto, false) &&
+ !Args.hasFlag(options::OPT_flto_EQ_jobserver, options::OPT_fno_lto,
+ false))))
+ return None;
StringRef LTOName("full");
- const Arg *A = Args.getLastArg(options::OPT_flto_EQ);
+ const Arg *A = Args.getLastArg(OptEq);
if (A)
LTOName = A->getValue();
@@ -612,9 +611,27 @@
if (LTOMode == LTOK_Unknown) {
assert(A);
- Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName()
- << A->getValue();
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
+ return None;
}
+ return LTOMode;
+}
+
+// Parse the LTO options.
+void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
+ LTOMode = LTOK_None;
+ if (auto M = parseLTOMode(*this, Args, options::OPT_flto,
+ options::OPT_fno_lto, options::OPT_flto_EQ,
+ /*IsOffload=*/false))
+ LTOMode = M.getValue();
+
+ OffloadLTOMode = LTOK_None;
+ if (auto M = parseLTOMode(*this, Args, options::OPT_foffload_lto,
+ options::OPT_fno_offload_lto,
+ options::OPT_foffload_lto_EQ,
+ /*IsOffload=*/true))
+ OffloadLTOMode = M.getValue();
}
/// Compute the desired OpenMP runtime from the flags provided.
@@ -739,18 +756,27 @@
Diag(clang::diag::err_drv_invalid_omp_target) << Val;
else {
const ToolChain *TC;
- // CUDA toolchains have to be selected differently. They pair host
+ // Device toolchains have to be selected differently. They pair host
// and device in their implementation.
- if (TT.isNVPTX()) {
+ if (TT.isNVPTX() || TT.isAMDGCN()) {
const ToolChain *HostTC =
C.getSingleOffloadToolChain<Action::OFK_Host>();
assert(HostTC && "Host toolchain should be always defined.");
- auto &CudaTC =
+ auto &DeviceTC =
ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
- if (!CudaTC)
- CudaTC = std::make_unique<toolchains::CudaToolChain>(
- *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP);
- TC = CudaTC.get();
+ if (!DeviceTC) {
+ if (TT.isNVPTX())
+ DeviceTC = std::make_unique<toolchains::CudaToolChain>(
+ *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP);
+ else if (TT.isAMDGCN())
+ DeviceTC =
+ std::make_unique<toolchains::AMDGPUOpenMPToolChain>(
+ *this, TT, *HostTC, C.getInputArgs());
+ else
+ assert(DeviceTC && "Device toolchain not defined.");
+ }
+
+ TC = DeviceTC.get();
} else
TC = &getToolChain(C.getInputArgs(), TT);
C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
@@ -987,7 +1013,10 @@
// We look for the driver mode option early, because the mode can affect
// how other options are parsed.
- ParseDriverMode(ClangExecutable, ArgList.slice(1));
+
+ auto DriverMode = getDriverMode(ClangExecutable, ArgList.slice(1));
+ if (!DriverMode.empty())
+ setDriverMode(DriverMode);
// FIXME: What are we going to do with -V and -b?
@@ -1085,6 +1114,15 @@
GenReproducer = Args.hasFlag(options::OPT_gen_reproducer,
options::OPT_fno_crash_diagnostics,
!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"));
+
+ // Process -fproc-stat-report options.
+ if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {
+ CCPrintProcessStats = true;
+ CCPrintStatReportFilename = A->getValue();
+ }
+ if (Args.hasArg(options::OPT_fproc_stat_report))
+ CCPrintProcessStats = true;
+
// FIXME: TargetTriple is used by the target-prefixed calls to as/ld
// and getToolChain is const.
if (IsCLMode()) {
@@ -1434,7 +1472,9 @@
llvm::SmallString<128> Script(CrashInfo.Filename);
llvm::sys::path::replace_extension(Script, "sh");
std::error_code EC;
- llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew);
+ llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew,
+ llvm::sys::fs::FA_Write,
+ llvm::sys::fs::OF_Text);
if (EC) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating run script: " << Script << " " << EC.message();
@@ -1471,8 +1511,7 @@
}
}
- for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file,
- options::OPT_frewrite_map_file_EQ))
+ for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file_EQ))
Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue();
Diag(clang::diag::note_drv_command_failed_diag_msg)
@@ -1581,7 +1620,7 @@
ExcludedFlagsBitmask |= options::FlangOnlyOption;
std::string Usage = llvm::formatv("{0} [options] file...", Name).str();
- getOpts().PrintHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),
+ getOpts().printHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),
IncludedFlagsBitmask, ExcludedFlagsBitmask,
/*ShowAllAliases=*/false);
}
@@ -1701,7 +1740,7 @@
// case-insensitive sorting for consistency with the -help option
// which prints out options in the case-insensitive alphabetical order.
llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) {
- if (int X = A.compare_lower(B))
+ if (int X = A.compare_insensitive(B))
return X < 0;
return A.compare(B) > 0;
});
@@ -1802,6 +1841,15 @@
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) {
+ std::string CandidateRuntimePath = TC.getRuntimePath();
+ if (getVFS().exists(CandidateRuntimePath))
+ llvm::outs() << CandidateRuntimePath << '\n';
+ else
+ llvm::outs() << TC.getCompilerRTPath() << '\n';
+ return false;
+ }
+
// FIXME: The following handlers should use a callback mechanism, we don't
// know what the client would like to do.
if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {
@@ -1870,6 +1918,12 @@
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_multiarch)) {
+ llvm::outs() << TC.getMultiarchTriple(*this, TC.getTriple(), SysRoot)
+ << "\n";
+ return false;
+ }
+
if (C.getArgs().hasArg(options::OPT_print_targets)) {
llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs());
return false;
@@ -2179,15 +2233,20 @@
// stdin must be handled specially.
if (memcmp(Value, "-", 2) == 0) {
- // If running with -E, treat as a C input (this changes the builtin
- // macros, for example). This may be overridden by -ObjC below.
- //
- // Otherwise emit an error but still use a valid type to avoid
- // spurious errors (e.g., no inputs).
- if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())
- Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl
- : clang::diag::err_drv_unknown_stdin_type);
- Ty = types::TY_C;
+ if (IsFlangMode()) {
+ Ty = types::TY_Fortran;
+ } else {
+ // If running with -E, treat as a C input (this changes the
+ // builtin macros, for example). This may be overridden by -ObjC
+ // below.
+ //
+ // Otherwise emit an error but still use a valid type to avoid
+ // spurious errors (e.g., no inputs).
+ if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())
+ Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl
+ : clang::diag::err_drv_unknown_stdin_type);
+ Ty = types::TY_C;
+ }
} else {
// Otherwise lookup by extension.
// Fallback is C if invoked as C preprocessor, C++ if invoked with
@@ -2443,6 +2502,14 @@
/// Default GPU architecture if there's no one specified.
CudaArch DefaultCudaArch = CudaArch::UNKNOWN;
+ /// Method to generate compilation unit ID specified by option
+ /// '-fuse-cuid='.
+ enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid };
+ UseCUIDKind UseCUID = CUID_Hash;
+
+ /// Compilation unit ID specified by option '-cuid='.
+ StringRef FixedCUID;
+
public:
CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,
const Driver::InputList &Inputs,
@@ -2479,9 +2546,32 @@
// Replicate inputs for each GPU architecture.
auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE
: types::TY_CUDA_DEVICE;
+ std::string CUID = FixedCUID.str();
+ if (CUID.empty()) {
+ if (UseCUID == CUID_Random)
+ CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(),
+ /*LowerCase=*/true);
+ else if (UseCUID == CUID_Hash) {
+ llvm::MD5 Hasher;
+ llvm::MD5::MD5Result Hash;
+ SmallString<256> RealPath;
+ llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath,
+ /*expand_tilde=*/true);
+ Hasher.update(RealPath);
+ for (auto *A : Args) {
+ if (A->getOption().matches(options::OPT_INPUT))
+ continue;
+ Hasher.update(A->getAsString(Args));
+ }
+ Hasher.final(Hash);
+ CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
+ }
+ }
+ IA->setId(CUID);
+
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
CudaDeviceActions.push_back(
- C.MakeAction<InputAction>(IA->getInputArg(), Ty));
+ C.MakeAction<InputAction>(IA->getInputArg(), Ty, IA->getId()));
}
return ABRT_Success;
@@ -2603,6 +2693,21 @@
options::OPT_cuda_device_only);
EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
EmitAsm = Args.getLastArg(options::OPT_S);
+ FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);
+ if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {
+ StringRef UseCUIDStr = A->getValue();
+ UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr)
+ .Case("hash", CUID_Hash)
+ .Case("random", CUID_Random)
+ .Case("none", CUID_None)
+ .Default(CUID_Invalid);
+ if (UseCUID == CUID_Invalid) {
+ C.getDriver().Diag(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << UseCUIDStr;
+ C.setContainsError();
+ return true;
+ }
+ }
// Collect all cuda_gpu_arch parameters, removing duplicates.
std::set<StringRef> GpuArchs;
@@ -2665,7 +2770,7 @@
StringRef getCanonicalOffloadArch(StringRef ArchStr) override {
CudaArch Arch = StringToCudaArch(ArchStr);
- if (Arch == CudaArch::UNKNOWN) {
+ if (Arch == CudaArch::UNKNOWN || !IsNVIDIAGpuArch(Arch)) {
C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;
return StringRef();
}
@@ -2786,12 +2891,25 @@
class HIPActionBuilder final : public CudaActionBuilderBase {
/// The linker inputs obtained for each device arch.
SmallVector<ActionList, 8> DeviceLinkerInputs;
+ bool GPUSanitize;
+ // The default bundling behavior depends on the type of output, therefore
+ // BundleOutput needs to be tri-value: None, true, or false.
+ // Bundle code objects except --no-gpu-output is specified for device
+ // only compilation. Bundle other type of output files only if
+ // --gpu-bundle-output is specified for device only compilation.
+ Optional<bool> BundleOutput;
public:
HIPActionBuilder(Compilation &C, DerivedArgList &Args,
const Driver::InputList &Inputs)
: CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {
DefaultCudaArch = CudaArch::GFX803;
+ GPUSanitize = Args.hasFlag(options::OPT_fgpu_sanitize,
+ options::OPT_fno_gpu_sanitize, false);
+ if (Args.hasArg(options::OPT_gpu_bundle_output,
+ options::OPT_no_gpu_bundle_output))
+ BundleOutput = Args.hasFlag(options::OPT_gpu_bundle_output,
+ options::OPT_no_gpu_bundle_output);
}
bool canUseBundlerUnbundler() const override { return true; }
@@ -2840,17 +2958,31 @@
// a fat binary containing all the code objects for different GPU's.
// The fat binary is then an input to the host action.
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
- auto BackendAction = C.getDriver().ConstructPhaseAction(
- C, Args, phases::Backend, CudaDeviceActions[I],
- AssociatedOffloadKind);
- auto AssembleAction = C.getDriver().ConstructPhaseAction(
- C, Args, phases::Assemble, BackendAction, AssociatedOffloadKind);
- // Create a link action to link device IR with device library
- // and generate ISA.
- ActionList AL;
- AL.push_back(AssembleAction);
- CudaDeviceActions[I] =
- C.MakeAction<LinkJobAction>(AL, types::TY_Image);
+ if (C.getDriver().isUsingLTO(/*IsOffload=*/true)) {
+ // When LTO is enabled, skip the backend and assemble phases and
+ // use lld to link the bitcode.
+ ActionList AL;
+ AL.push_back(CudaDeviceActions[I]);
+ // Create a link action to link device IR with device library
+ // and generate ISA.
+ CudaDeviceActions[I] =
+ C.MakeAction<LinkJobAction>(AL, types::TY_Image);
+ } else {
+ // When LTO is not enabled, we follow the conventional
+ // compiler phases, including backend and assemble phases.
+ ActionList AL;
+ auto BackendAction = C.getDriver().ConstructPhaseAction(
+ C, Args, phases::Backend, CudaDeviceActions[I],
+ AssociatedOffloadKind);
+ auto AssembleAction = C.getDriver().ConstructPhaseAction(
+ C, Args, phases::Assemble, BackendAction,
+ AssociatedOffloadKind);
+ AL.push_back(AssembleAction);
+ // Create a link action to link device IR with device library
+ // and generate ISA.
+ CudaDeviceActions[I] =
+ C.MakeAction<LinkJobAction>(AL, types::TY_Image);
+ }
// OffloadingActionBuilder propagates device arch until an offload
// action. Since the next action for creating fatbin does
@@ -2864,23 +2996,26 @@
CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
DDep, CudaDeviceActions[I]->getType());
}
- // Create HIP fat binary with a special "link" action.
- CudaFatBinary =
- C.MakeAction<LinkJobAction>(CudaDeviceActions,
- types::TY_HIP_FATBIN);
- if (!CompileDeviceOnly) {
- DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
- AssociatedOffloadKind);
- // Clear the fat binary, it is already a dependence to an host
- // action.
- CudaFatBinary = nullptr;
+ if (!CompileDeviceOnly || !BundleOutput.hasValue() ||
+ BundleOutput.getValue()) {
+ // Create HIP fat binary with a special "link" action.
+ CudaFatBinary = C.MakeAction<LinkJobAction>(CudaDeviceActions,
+ types::TY_HIP_FATBIN);
+
+ if (!CompileDeviceOnly) {
+ DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
+ AssociatedOffloadKind);
+ // Clear the fat binary, it is already a dependence to an host
+ // action.
+ CudaFatBinary = nullptr;
+ }
+
+ // Remove the CUDA actions as they are already connected to an host
+ // action or fat binary.
+ CudaDeviceActions.clear();
}
- // Remove the CUDA actions as they are already connected to an host
- // action or fat binary.
- CudaDeviceActions.clear();
-
return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
} else if (CurPhase == phases::Link) {
// Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.
@@ -2906,6 +3041,20 @@
A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A,
AssociatedOffloadKind);
+ if (CompileDeviceOnly && CurPhase == FinalPhase &&
+ BundleOutput.hasValue() && BundleOutput.getValue()) {
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],
+ AssociatedOffloadKind);
+ CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
+ DDep, CudaDeviceActions[I]->getType());
+ }
+ CudaFatBinary =
+ C.MakeAction<OffloadBundlingJobAction>(CudaDeviceActions);
+ CudaDeviceActions.clear();
+ }
+
return (CompileDeviceOnly && CurPhase == FinalPhase) ? ABRT_Ignore_Host
: ABRT_Success;
}
@@ -3343,7 +3492,7 @@
return nullptr;
// Let builders add host linking actions.
- Action* HA;
+ Action* HA = nullptr;
for (DeviceActionBuilder *SB : SpecializedBuilders) {
if (!SB->isValid())
continue;
@@ -3418,7 +3567,8 @@
if (Args.hasArg(options::OPT_emit_llvm))
Diag(clang::diag::err_drv_emit_llvm_link);
if (IsCLMode() && LTOMode != LTOK_None &&
- !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld"))
+ !Args.getLastArgValue(options::OPT_fuse_ld_EQ)
+ .equals_insensitive("lld"))
Diag(clang::diag::err_drv_lto_without_lld);
}
@@ -3890,10 +4040,13 @@
}
const llvm::Triple &RawTriple = C.getDefaultToolChain().getTriple();
- if (RawTriple.isOSAIX())
+ if (RawTriple.isOSAIX()) {
if (Arg *A = C.getArgs().getLastArg(options::OPT_G))
Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getSpelling() << RawTriple.str();
+ if (LTOMode == LTOK_Thin)
+ Diag(diag::err_drv_clang_unsupported) << "thinLTO on AIX";
+ }
// Collect the list of architectures.
llvm::StringSet<> ArchNames;
@@ -3927,66 +4080,64 @@
/*TargetDeviceOffloadKind*/ Action::OFK_None);
}
- StringRef StatReportFile;
- bool PrintProcessStat = false;
- if (const Arg *A = C.getArgs().getLastArg(options::OPT_fproc_stat_report_EQ))
- StatReportFile = A->getValue();
- if (C.getArgs().hasArg(options::OPT_fproc_stat_report))
- PrintProcessStat = true;
-
// If we have more than one job, then disable integrated-cc1 for now. Do this
// also when we need to report process execution statistics.
- if (C.getJobs().size() > 1 || !StatReportFile.empty() || PrintProcessStat)
+ if (C.getJobs().size() > 1 || CCPrintProcessStats)
for (auto &J : C.getJobs())
J.InProcess = false;
- if (!StatReportFile.empty() || PrintProcessStat) {
+ if (CCPrintProcessStats) {
C.setPostCallback([=](const Command &Cmd, int Res) {
Optional<llvm::sys::ProcessStatistics> ProcStat =
Cmd.getProcessStatistics();
if (!ProcStat)
return;
- if (PrintProcessStat) {
+
+ const char *LinkingOutput = nullptr;
+ if (FinalOutput)
+ LinkingOutput = FinalOutput->getValue();
+ else if (!Cmd.getOutputFilenames().empty())
+ LinkingOutput = Cmd.getOutputFilenames().front().c_str();
+ else
+ LinkingOutput = getDefaultImageName();
+
+ if (CCPrintStatReportFilename.empty()) {
using namespace llvm;
// Human readable output.
outs() << sys::path::filename(Cmd.getExecutable()) << ": "
- << "output=";
- if (Cmd.getOutputFilenames().empty())
- outs() << "\"\"";
- else
- outs() << Cmd.getOutputFilenames().front();
+ << "output=" << LinkingOutput;
outs() << ", total="
<< format("%.3f", ProcStat->TotalTime.count() / 1000.) << " ms"
<< ", user="
<< format("%.3f", ProcStat->UserTime.count() / 1000.) << " ms"
<< ", mem=" << ProcStat->PeakMemory << " Kb\n";
- }
- if (!StatReportFile.empty()) {
+ } else {
// CSV format.
std::string Buffer;
llvm::raw_string_ostream Out(Buffer);
llvm::sys::printArg(Out, llvm::sys::path::filename(Cmd.getExecutable()),
/*Quote*/ true);
Out << ',';
- if (Cmd.getOutputFilenames().empty())
- Out << "\"\"";
- else
- llvm::sys::printArg(Out, Cmd.getOutputFilenames().front(), true);
+ llvm::sys::printArg(Out, LinkingOutput, true);
Out << ',' << ProcStat->TotalTime.count() << ','
<< ProcStat->UserTime.count() << ',' << ProcStat->PeakMemory
<< '\n';
Out.flush();
std::error_code EC;
- llvm::raw_fd_ostream OS(StatReportFile, EC, llvm::sys::fs::OF_Append);
+ llvm::raw_fd_ostream OS(CCPrintStatReportFilename.c_str(), EC,
+ llvm::sys::fs::OF_Append |
+ llvm::sys::fs::OF_Text);
if (EC)
return;
auto L = OS.lock();
if (!L) {
- llvm::errs() << "ERROR: Cannot lock file " << StatReportFile << ": "
+ llvm::errs() << "ERROR: Cannot lock file "
+ << CCPrintStatReportFilename << ": "
<< toString(L.takeError()) << "\n";
return;
}
OS << Buffer;
+ OS.flush();
}
});
}
@@ -4479,6 +4630,25 @@
if (!T)
return InputInfo();
+ if (BuildingForOffloadDevice &&
+ A->getOffloadingDeviceKind() == Action::OFK_OpenMP) {
+ if (TC->getTriple().isAMDGCN()) {
+ // AMDGCN treats backend and assemble actions as no-op because
+ // linker does not support object files.
+ if (const BackendJobAction *BA = dyn_cast<BackendJobAction>(A)) {
+ return BuildJobsForAction(C, *BA->input_begin(), TC, BoundArch,
+ AtTopLevel, MultipleArchs, LinkingOutput,
+ CachedResults, TargetDeviceOffloadKind);
+ }
+
+ if (const AssembleJobAction *AA = dyn_cast<AssembleJobAction>(A)) {
+ return BuildJobsForAction(C, *AA->input_begin(), TC, BoundArch,
+ AtTopLevel, MultipleArchs, LinkingOutput,
+ CachedResults, TargetDeviceOffloadKind);
+ }
+ }
+ }
+
// If we've collapsed action list that contained OffloadAction we
// need to build jobs for host/device-side inputs it may have held.
for (const auto *OA : CollapsedOffloadActions)
@@ -4598,11 +4768,12 @@
/*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() &&
!AtTopLevel);
if (isa<OffloadWrapperJobAction>(JA)) {
- OffloadingPrefix += "-wrapper";
if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
BaseInput = FinalOutput->getValue();
else
BaseInput = getDefaultImageName();
+ BaseInput =
+ C.getArgs().MakeArgString(std::string(BaseInput) + "-wrapper");
}
Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
AtTopLevel, MultipleArchs,
@@ -4729,6 +4900,11 @@
return "-";
}
+ if (JA.getType() == types::TY_ModuleFile &&
+ C.getArgs().getLastArg(options::OPT_module_file_info)) {
+ return "-";
+ }
+
// Is this the assembly listing for /FA?
if (JA.getType() == types::TY_PP_Asm &&
(C.getArgs().hasArg(options::OPT__SLASH_FA) ||
@@ -4963,11 +5139,6 @@
// FIXME: Needs a better variable than TargetTriple
Names.emplace_back((TargetTriple + "-" + Tool).str());
Names.emplace_back(Tool);
-
- // Allow the discovery of tools prefixed with LLVM's default target triple.
- std::string DefaultTargetTriple = llvm::sys::getDefaultTargetTriple();
- if (DefaultTargetTriple != TargetTriple)
- Names.emplace_back((DefaultTargetTriple + "-" + Tool).str());
}
static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) {
@@ -5158,7 +5329,7 @@
case llvm::Triple::MSVC:
case llvm::Triple::UnknownEnvironment:
if (Args.getLastArgValue(options::OPT_fuse_ld_EQ)
- .startswith_lower("bfd"))
+ .startswith_insensitive("bfd"))
TC = std::make_unique<toolchains::CrossWindowsToolChain>(
*this, Target, Args);
else
@@ -5387,3 +5558,21 @@
return true;
return false;
}
+
+llvm::StringRef clang::driver::getDriverMode(StringRef ProgName,
+ ArrayRef<const char *> Args) {
+ static const std::string OptName =
+ getDriverOptTable().getOption(options::OPT_driver_mode).getPrefixedName();
+ llvm::StringRef Opt;
+ for (StringRef Arg : Args) {
+ if (!Arg.startswith(OptName))
+ continue;
+ Opt = Arg;
+ break;
+ }
+ if (Opt.empty())
+ Opt = ToolChain::getTargetAndModeFromProgramName(ProgName).DriverMode;
+ return Opt.consume_front(OptName) ? Opt : "";
+}
+
+bool driver::IsClangCL(StringRef DriverMode) { return DriverMode.equals("cl"); }
diff --git a/src/llvm-project/clang/lib/Driver/InputInfo.h b/src/llvm-project/clang/lib/Driver/InputInfo.h
deleted file mode 100644
index a6b6f7f..0000000
--- a/src/llvm-project/clang/lib/Driver/InputInfo.h
+++ /dev/null
@@ -1,107 +0,0 @@
-//===--- InputInfo.h - Input Source & Type Information ----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_DRIVER_INPUTINFO_H
-#define LLVM_CLANG_LIB_DRIVER_INPUTINFO_H
-
-#include "clang/Driver/Action.h"
-#include "clang/Driver/Types.h"
-#include "llvm/Option/Arg.h"
-#include <cassert>
-#include <string>
-
-namespace clang {
-namespace driver {
-
-/// InputInfo - Wrapper for information about an input source.
-class InputInfo {
- // FIXME: The distinction between filenames and inputarg here is
- // gross; we should probably drop the idea of a "linker
- // input". Doing so means tweaking pipelining to still create link
- // steps when it sees linker inputs (but not treat them as
- // arguments), and making sure that arguments get rendered
- // correctly.
- enum Class {
- Nothing,
- Filename,
- InputArg,
- Pipe
- };
-
- union {
- const char *Filename;
- const llvm::opt::Arg *InputArg;
- } Data;
- Class Kind;
- const Action* Act;
- types::ID Type;
- const char *BaseInput;
-
- static types::ID GetActionType(const Action *A) {
- return A != nullptr ? A->getType() : types::TY_Nothing;
- }
-
-public:
- InputInfo() : InputInfo(nullptr, nullptr) {}
- InputInfo(const Action *A, const char *_BaseInput)
- : Kind(Nothing), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {}
-
- InputInfo(types::ID _Type, const char *_Filename, const char *_BaseInput)
- : Kind(Filename), Act(nullptr), Type(_Type), BaseInput(_BaseInput) {
- Data.Filename = _Filename;
- }
- InputInfo(const Action *A, const char *_Filename, const char *_BaseInput)
- : Kind(Filename), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {
- Data.Filename = _Filename;
- }
-
- InputInfo(types::ID _Type, const llvm::opt::Arg *_InputArg,
- const char *_BaseInput)
- : Kind(InputArg), Act(nullptr), Type(_Type), BaseInput(_BaseInput) {
- Data.InputArg = _InputArg;
- }
- InputInfo(const Action *A, const llvm::opt::Arg *_InputArg,
- const char *_BaseInput)
- : Kind(InputArg), Act(A), Type(GetActionType(A)), BaseInput(_BaseInput) {
- Data.InputArg = _InputArg;
- }
-
- bool isNothing() const { return Kind == Nothing; }
- bool isFilename() const { return Kind == Filename; }
- bool isInputArg() const { return Kind == InputArg; }
- types::ID getType() const { return Type; }
- const char *getBaseInput() const { return BaseInput; }
- /// The action for which this InputInfo was created. May be null.
- const Action *getAction() const { return Act; }
- void setAction(const Action *A) { Act = A; }
-
- const char *getFilename() const {
- assert(isFilename() && "Invalid accessor.");
- return Data.Filename;
- }
- const llvm::opt::Arg &getInputArg() const {
- assert(isInputArg() && "Invalid accessor.");
- return *Data.InputArg;
- }
-
- /// getAsString - Return a string name for this input, for
- /// debugging.
- std::string getAsString() const {
- if (isFilename())
- return std::string("\"") + getFilename() + '"';
- else if (isInputArg())
- return "(input arg)";
- else
- return "(nothing)";
- }
-};
-
-} // end namespace driver
-} // end namespace clang
-
-#endif
diff --git a/src/llvm-project/clang/lib/Driver/Job.cpp b/src/llvm-project/clang/lib/Driver/Job.cpp
index 911fd5d..5b87106 100644
--- a/src/llvm-project/clang/lib/Driver/Job.cpp
+++ b/src/llvm-project/clang/lib/Driver/Job.cpp
@@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Job.h"
-#include "InputInfo.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/ArrayRef.h"
@@ -43,7 +43,7 @@
Executable(Executable), Arguments(Arguments) {
for (const auto &II : Inputs)
if (II.isFilename())
- InputFilenames.push_back(II.getFilename());
+ InputInfoList.push_back(II);
for (const auto &II : Outputs)
if (II.isFilename())
OutputFilenames.push_back(II.getFilename());
@@ -237,9 +237,10 @@
}
}
- auto Found = llvm::find_if(InputFilenames,
- [&Arg](StringRef IF) { return IF == Arg; });
- if (Found != InputFilenames.end() &&
+ auto Found = llvm::find_if(InputInfoList, [&Arg](const InputInfo &II) {
+ return II.getFilename() == Arg;
+ });
+ if (Found != InputInfoList.end() &&
(i == 0 || StringRef(Args[i - 1]) != "-main-file-name")) {
// Replace the input file name with the crashinfo's file name.
OS << ' ';
@@ -302,8 +303,8 @@
void Command::PrintFileNames() const {
if (PrintInputFilenames) {
- for (const char *Arg : InputFilenames)
- llvm::outs() << llvm::sys::path::filename(Arg) << "\n";
+ for (const auto &Arg : InputInfoList)
+ llvm::outs() << llvm::sys::path::filename(Arg.getFilename()) << "\n";
llvm::outs().flush();
}
}
@@ -414,50 +415,6 @@
"The CC1Command doesn't support changing the environment vars!");
}
-FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
- ResponseFileSupport ResponseSupport,
- const char *Executable_,
- const llvm::opt::ArgStringList &Arguments_,
- ArrayRef<InputInfo> Inputs,
- ArrayRef<InputInfo> Outputs,
- std::unique_ptr<Command> Fallback_)
- : Command(Source_, Creator_, ResponseSupport, Executable_, Arguments_,
- Inputs, Outputs),
- Fallback(std::move(Fallback_)) {}
-
-void FallbackCommand::Print(raw_ostream &OS, const char *Terminator,
- bool Quote, CrashReportInfo *CrashInfo) const {
- Command::Print(OS, "", Quote, CrashInfo);
- OS << " ||";
- Fallback->Print(OS, Terminator, Quote, CrashInfo);
-}
-
-static bool ShouldFallback(int ExitCode) {
- // FIXME: We really just want to fall back for internal errors, such
- // as when some symbol cannot be mangled, when we should be able to
- // parse something but can't, etc.
- return ExitCode != 0;
-}
-
-int FallbackCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
- std::string *ErrMsg, bool *ExecutionFailed) const {
- int PrimaryStatus = Command::Execute(Redirects, ErrMsg, ExecutionFailed);
- if (!ShouldFallback(PrimaryStatus))
- return PrimaryStatus;
-
- // Clear ExecutionFailed and ErrMsg before falling back.
- if (ErrMsg)
- ErrMsg->clear();
- if (ExecutionFailed)
- *ExecutionFailed = false;
-
- const Driver &D = getCreator().getToolChain().getDriver();
- D.Diag(diag::warn_drv_invoking_fallback) << Fallback->getExecutable();
-
- int SecondaryStatus = Fallback->Execute(Redirects, ErrMsg, ExecutionFailed);
- return SecondaryStatus;
-}
-
ForceSuccessCommand::ForceSuccessCommand(
const Action &Source_, const Tool &Creator_,
ResponseFileSupport ResponseSupport, const char *Executable_,
diff --git a/src/llvm-project/clang/lib/Driver/SanitizerArgs.cpp b/src/llvm-project/clang/lib/Driver/SanitizerArgs.cpp
index 5c27535..8770fb1c 100644
--- a/src/llvm-project/clang/lib/Driver/SanitizerArgs.cpp
+++ b/src/llvm-project/clang/lib/Driver/SanitizerArgs.cpp
@@ -18,6 +18,7 @@
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
#include <memory>
using namespace clang;
@@ -133,41 +134,41 @@
D.Diag(MalformedSCLErrorDiagID) << BLError;
}
-static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds,
- std::vector<std::string> &BlacklistFiles) {
- struct Blacklist {
+static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
+ std::vector<std::string> &IgnorelistFiles) {
+ struct Ignorelist {
const char *File;
SanitizerMask Mask;
- } Blacklists[] = {{"asan_blacklist.txt", SanitizerKind::Address},
- {"hwasan_blacklist.txt", SanitizerKind::HWAddress},
- {"memtag_blacklist.txt", SanitizerKind::MemTag},
- {"msan_blacklist.txt", SanitizerKind::Memory},
- {"tsan_blacklist.txt", SanitizerKind::Thread},
- {"dfsan_abilist.txt", SanitizerKind::DataFlow},
- {"cfi_blacklist.txt", SanitizerKind::CFI},
- {"ubsan_blacklist.txt",
- SanitizerKind::Undefined | SanitizerKind::Integer |
- SanitizerKind::Nullability |
- SanitizerKind::FloatDivideByZero}};
+ } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},
+ {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},
+ {"memtag_ignorelist.txt", SanitizerKind::MemTag},
+ {"msan_ignorelist.txt", SanitizerKind::Memory},
+ {"tsan_ignorelist.txt", SanitizerKind::Thread},
+ {"dfsan_abilist.txt", SanitizerKind::DataFlow},
+ {"cfi_ignorelist.txt", SanitizerKind::CFI},
+ {"ubsan_ignorelist.txt",
+ SanitizerKind::Undefined | SanitizerKind::Integer |
+ SanitizerKind::Nullability |
+ SanitizerKind::FloatDivideByZero}};
- for (auto BL : Blacklists) {
+ for (auto BL : Ignorelists) {
if (!(Kinds & BL.Mask))
continue;
clang::SmallString<64> Path(D.ResourceDir);
llvm::sys::path::append(Path, "share", BL.File);
if (D.getVFS().exists(Path))
- BlacklistFiles.push_back(std::string(Path.str()));
+ IgnorelistFiles.push_back(std::string(Path.str()));
else if (BL.Mask == SanitizerKind::CFI)
- // If cfi_blacklist.txt cannot be found in the resource dir, driver
+ // If cfi_ignorelist.txt cannot be found in the resource dir, driver
// should fail.
D.Diag(clang::diag::err_drv_no_such_file) << Path;
}
validateSpecialCaseListFormat(
- D, BlacklistFiles, clang::diag::err_drv_malformed_sanitizer_blacklist);
+ D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist);
}
-/// Parse -f(no-)?sanitize-(coverage-)?(white|black)list argument's values,
+/// Parse -f(no-)?sanitize-(coverage-)?(white|ignore)list argument's values,
/// diagnosing any invalid file paths and validating special case list format.
static void parseSpecialCaseListArg(const Driver &D,
const llvm::opt::ArgList &Args,
@@ -176,7 +177,7 @@
llvm::opt::OptSpecifier NoSCLOptionID,
unsigned MalformedSCLErrorDiagID) {
for (const auto *Arg : Args) {
- // Match -fsanitize-(coverage-)?(white|black)list.
+ // Match -fsanitize-(coverage-)?(white|ignore)list.
if (Arg->getOption().matches(SCLOptionID)) {
Arg->claim();
std::string SCLPath = Arg->getValue();
@@ -185,7 +186,7 @@
} else {
D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
}
- // Match -fno-sanitize-blacklist.
+ // Match -fno-sanitize-ignorelist.
} else if (Arg->getOption().matches(NoSCLOptionID)) {
Arg->claim();
SCLFiles.clear();
@@ -581,18 +582,18 @@
TrappingKinds &= Kinds;
RecoverableKinds &= ~TrappingKinds;
- // Setup blacklist files.
- // Add default blacklist from resource directory for activated sanitizers, and
- // validate special case lists format.
- if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_blacklist))
- addDefaultBlacklists(D, Kinds, SystemBlacklistFiles);
+ // Setup ignorelist files.
+ // Add default ignorelist from resource directory for activated sanitizers,
+ // and validate special case lists format.
+ if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))
+ addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles);
- // Parse -f(no-)?sanitize-blacklist options.
+ // Parse -f(no-)?sanitize-ignorelist options.
// This also validates special case lists format.
- parseSpecialCaseListArg(D, Args, UserBlacklistFiles,
- options::OPT_fsanitize_blacklist,
- options::OPT_fno_sanitize_blacklist,
- clang::diag::err_drv_malformed_sanitizer_blacklist);
+ parseSpecialCaseListArg(D, Args, UserIgnorelistFiles,
+ options::OPT_fsanitize_ignorelist_EQ,
+ options::OPT_fno_sanitize_ignorelist,
+ clang::diag::err_drv_malformed_sanitizer_ignorelist);
// Parse -f[no-]sanitize-memory-track-origins[=level] options.
if (AllAddedKinds & SanitizerKind::Memory) {
@@ -746,7 +747,7 @@
CoverageFeatures |= CoverageFunc;
}
- // Parse -fsanitize-coverage-(black|white)list options if coverage enabled.
+ // Parse -fsanitize-coverage-(ignore|white)list options if coverage enabled.
// This also validates special case lists format.
// Here, OptSpecifier() acts as a never-matching command-line argument.
// So, there is no way to clear coverage lists but you can append to them.
@@ -756,9 +757,9 @@
options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
clang::diag::err_drv_malformed_sanitizer_coverage_whitelist);
parseSpecialCaseListArg(
- D, Args, CoverageBlocklistFiles,
- options::OPT_fsanitize_coverage_blocklist, OptSpecifier(),
- clang::diag::err_drv_malformed_sanitizer_coverage_blacklist);
+ D, Args, CoverageIgnorelistFiles,
+ options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),
+ clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist);
}
SharedRuntime =
@@ -804,6 +805,11 @@
options::OPT_fno_sanitize_address_poison_custom_array_cookie,
AsanPoisonCustomArrayCookie);
+ AsanOutlineInstrumentation =
+ Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,
+ options::OPT_fno_sanitize_address_outline_instrumentation,
+ AsanOutlineInstrumentation);
+
// As a workaround for a bug in gold 2.26 and earlier, dead stripping of
// globals in ASan is disabled by default on ELF targets.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
@@ -825,6 +831,34 @@
AsanInvalidPointerSub = true;
}
+ if (TC.getTriple().isOSDarwin() &&
+ (Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext))) {
+ AsanDtorKind = llvm::AsanDtorKind::None;
+ }
+
+ if (const auto *Arg =
+ Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {
+ auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
+ if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid) {
+ TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
+ << Arg->getOption().getName() << Arg->getValue();
+ }
+ AsanDtorKind = parsedAsanDtorKind;
+ }
+
+ if (const auto *Arg = Args.getLastArg(
+ options::OPT_sanitize_address_use_after_return_EQ)) {
+ auto parsedAsanUseAfterReturn =
+ AsanDetectStackUseAfterReturnModeFromString(Arg->getValue());
+ if (parsedAsanUseAfterReturn ==
+ llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
+ TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
+ << Arg->getOption().getName() << Arg->getValue();
+ }
+ AsanUseAfterReturn = parsedAsanUseAfterReturn;
+ }
+
} else {
AsanUseAfterScope = false;
// -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
@@ -849,6 +883,11 @@
} else {
HwasanAbi = "interceptor";
}
+ if (TC.getTriple().getArch() == llvm::Triple::x86_64)
+ HwasanUseAliases = Args.hasFlag(
+ options::OPT_fsanitize_hwaddress_experimental_aliasing,
+ options::OPT_fno_sanitize_hwaddress_experimental_aliasing,
+ HwasanUseAliases);
}
if (AllAddedKinds & SanitizerKind::SafeStack) {
@@ -931,10 +970,15 @@
void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
types::ID InputType) const {
- // NVPTX/AMDGPU doesn't currently support sanitizers. Bailing out here means
+ // NVPTX doesn't currently support sanitizers. Bailing out here means
// that e.g. -fsanitize=address applies only to host code, which is what we
// want for now.
- if (TC.getTriple().isNVPTX() || TC.getTriple().isAMDGPU())
+ //
+ // AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
+ if (TC.getTriple().isNVPTX() ||
+ (TC.getTriple().isAMDGPU() &&
+ !Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
+ false)))
return;
// Translate available CoverageFeatures to corresponding clang-cc1 flags.
@@ -966,8 +1010,8 @@
}
addSpecialCaseListOpt(
Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
- addSpecialCaseListOpt(
- Args, CmdArgs, "-fsanitize-coverage-blocklist=", CoverageBlocklistFiles);
+ addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",
+ CoverageIgnorelistFiles);
if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
// Instruct the code generator to embed linker directives in the object file
@@ -1006,9 +1050,9 @@
Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
addSpecialCaseListOpt(Args, CmdArgs,
- "-fsanitize-blacklist=", UserBlacklistFiles);
+ "-fsanitize-ignorelist=", UserIgnorelistFiles);
addSpecialCaseListOpt(Args, CmdArgs,
- "-fsanitize-system-blacklist=", SystemBlacklistFiles);
+ "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);
if (MsanTrackOrigins)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
@@ -1033,6 +1077,11 @@
CmdArgs.push_back("-tsan-instrument-atomics=0");
}
+ if (HwasanUseAliases) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");
+ }
+
if (CfiCrossDso)
CmdArgs.push_back("-fsanitize-cfi-cross-dso");
@@ -1074,6 +1123,24 @@
CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
}
+ if (AsanOutlineInstrumentation) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");
+ }
+
+ // Only pass the option to the frontend if the user requested,
+ // otherwise the frontend will just use the codegen default.
+ if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
+ CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +
+ AsanDtorKindToString(AsanDtorKind)));
+ }
+
+ if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {
+ CmdArgs.push_back(Args.MakeArgString(
+ "-fsanitize-address-use-after-return=" +
+ AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));
+ }
+
if (!HwasanAbi.empty()) {
CmdArgs.push_back("-default-function-attr");
CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
diff --git a/src/llvm-project/clang/lib/Driver/Tool.cpp b/src/llvm-project/clang/lib/Driver/Tool.cpp
index 449f69c..a198f4f 100644
--- a/src/llvm-project/clang/lib/Driver/Tool.cpp
+++ b/src/llvm-project/clang/lib/Driver/Tool.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Tool.h"
-#include "InputInfo.h"
+#include "clang/Driver/InputInfo.h"
using namespace clang::driver;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChain.cpp b/src/llvm-project/clang/lib/Driver/ToolChain.cpp
index b2ddef1..6c1b881 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChain.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChain.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/ToolChain.h"
-#include "InputInfo.h"
#include "ToolChains/Arch/ARM.h"
#include "ToolChains/Clang.h"
#include "ToolChains/InterfaceStubs.h"
@@ -18,6 +17,7 @@
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
@@ -75,13 +75,13 @@
const ArgList &Args)
: D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
- if (D.CCCIsCXX()) {
- if (auto CXXStdlibPath = getCXXStdlibPath())
- getFilePaths().push_back(*CXXStdlibPath);
- }
+ std::string RuntimePath = getRuntimePath();
+ if (getVFS().exists(RuntimePath))
+ getLibraryPaths().push_back(RuntimePath);
- if (auto RuntimePath = getRuntimePath())
- getLibraryPaths().push_back(*RuntimePath);
+ std::string StdlibPath = getStdlibPath();
+ if (getVFS().exists(StdlibPath))
+ getFilePaths().push_back(StdlibPath);
std::string CandidateLibPath = getArchSpecificLibPath();
if (getVFS().exists(CandidateLibPath))
@@ -383,10 +383,16 @@
if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())
return "i686";
+ if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32())
+ return "x32";
+
return llvm::Triple::getArchTypeName(TC.getArch());
}
StringRef ToolChain::getOSLibName() const {
+ if (Triple.isOSDarwin())
+ return "darwin";
+
switch (Triple.getOS()) {
case llvm::Triple::FreeBSD:
return "freebsd";
@@ -414,8 +420,16 @@
}
std::string ToolChain::getCompilerRTBasename(const ArgList &Args,
- StringRef Component, FileType Type,
- bool AddArch) const {
+ StringRef Component,
+ FileType Type) const {
+ std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type);
+ return llvm::sys::path::filename(CRTAbsolutePath).str();
+}
+
+std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
+ StringRef Component,
+ FileType Type,
+ bool AddArch) const {
const llvm::Triple &TT = getTriple();
bool IsITANMSVCWindows =
TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
@@ -431,8 +445,8 @@
Suffix = IsITANMSVCWindows ? ".lib" : ".a";
break;
case ToolChain::FT_Shared:
- Suffix = Triple.isOSWindows()
- ? (Triple.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
+ Suffix = TT.isOSWindows()
+ ? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
: ".so";
break;
}
@@ -450,7 +464,7 @@
FileType Type) const {
// Check for runtime files in the new layout without the architecture first.
std::string CRTBasename =
- getCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
+ buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
for (const auto &LibPath : getLibraryPaths()) {
SmallString<128> P(LibPath);
llvm::sys::path::append(P, CRTBasename);
@@ -460,7 +474,8 @@
// Fall back to the old expected compiler-rt name if the new one does not
// exist.
- CRTBasename = getCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
+ CRTBasename =
+ buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
SmallString<128> Path(getCompilerRTPath());
llvm::sys::path::append(Path, CRTBasename);
return std::string(Path.str());
@@ -472,41 +487,16 @@
return Args.MakeArgString(getCompilerRT(Args, Component, Type));
}
-
-Optional<std::string> ToolChain::getRuntimePath() const {
- SmallString<128> P;
-
- // First try the triple passed to driver as --target=<triple>.
- P.assign(D.ResourceDir);
- llvm::sys::path::append(P, "lib", D.getTargetTriple());
- if (getVFS().exists(P))
- return llvm::Optional<std::string>(std::string(P.str()));
-
- // Second try the normalized triple.
- P.assign(D.ResourceDir);
- llvm::sys::path::append(P, "lib", Triple.str());
- if (getVFS().exists(P))
- return llvm::Optional<std::string>(std::string(P.str()));
-
- return None;
+std::string ToolChain::getRuntimePath() const {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "lib", getTripleString());
+ return std::string(P.str());
}
-Optional<std::string> ToolChain::getCXXStdlibPath() const {
- SmallString<128> P;
-
- // First try the triple passed to driver as --target=<triple>.
- P.assign(D.Dir);
- llvm::sys::path::append(P, "..", "lib", D.getTargetTriple(), "c++");
- if (getVFS().exists(P))
- return llvm::Optional<std::string>(std::string(P.str()));
-
- // Second try the normalized triple.
- P.assign(D.Dir);
- llvm::sys::path::append(P, "..", "lib", Triple.str(), "c++");
- if (getVFS().exists(P))
- return llvm::Optional<std::string>(std::string(P.str()));
-
- return None;
+std::string ToolChain::getStdlibPath() const {
+ SmallString<128> P(D.Dir);
+ llvm::sys::path::append(P, "..", "lib", getTripleString());
+ return std::string(P.str());
}
std::string ToolChain::getArchSpecificLibPath() const {
@@ -611,11 +601,11 @@
std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
if (llvm::sys::fs::can_execute(LinkerPath)) {
- // FIXME: Remove lld.darwinnew here once it's the only MachO lld.
+ // FIXME: Remove LinkerIsLLDDarwinNew once there's only one MachO lld.
if (LinkerIsLLD)
- *LinkerIsLLD = UseLinker == "lld" || UseLinker == "lld.darwinnew";
+ *LinkerIsLLD = UseLinker == "lld" || UseLinker == "lld.darwinold";
if (LinkerIsLLDDarwinNew)
- *LinkerIsLLDDarwinNew = UseLinker == "lld.darwinnew";
+ *LinkerIsLLDDarwinNew = UseLinker == "lld";
return LinkerPath;
}
}
@@ -726,118 +716,9 @@
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
- // FIXME: Factor into subclasses.
llvm::Triple Triple = getTriple();
- bool IsBigEndian = getTriple().getArch() == llvm::Triple::armeb ||
- getTriple().getArch() == llvm::Triple::thumbeb;
-
- // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
- // '-mbig-endian'/'-EB'.
- if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
- options::OPT_mbig_endian)) {
- IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
- }
-
- // Thumb2 is the default for V7 on Darwin.
- //
- // FIXME: Thumb should just be another -target-feaure, not in the triple.
- StringRef MCPU, MArch;
- if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
- MCPU = A->getValue();
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
- MArch = A->getValue();
- std::string CPU =
- Triple.isOSBinFormatMachO()
- ? tools::arm::getARMCPUForMArch(MArch, Triple).str()
- : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
- StringRef Suffix =
- tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
- bool IsMProfile = ARM::parseArchProfile(Suffix) == ARM::ProfileKind::M;
- bool ThumbDefault = IsMProfile || (ARM::parseArchVersion(Suffix) == 7 &&
- getTriple().isOSBinFormatMachO());
- // FIXME: this is invalid for WindowsCE
- if (getTriple().isOSWindows())
- ThumbDefault = true;
- std::string ArchName;
- if (IsBigEndian)
- ArchName = "armeb";
- else
- ArchName = "arm";
-
- // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for
- // M-Class CPUs/architecture variants, which is not supported.
- bool ARMModeRequested = !Args.hasFlag(options::OPT_mthumb,
- options::OPT_mno_thumb, ThumbDefault);
- if (IsMProfile && ARMModeRequested) {
- if (!MCPU.empty())
- getDriver().Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM";
- else
- getDriver().Diag(diag::err_arch_unsupported_isa)
- << tools::arm::getARMArch(MArch, getTriple()) << "ARM";
- }
-
- // Check to see if an explicit choice to use thumb has been made via
- // -mthumb. For assembler files we must check for -mthumb in the options
- // passed to the assembler via -Wa or -Xassembler.
- bool IsThumb = false;
- if (InputType != types::TY_PP_Asm)
- IsThumb = Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb,
- ThumbDefault);
- else {
- // Ideally we would check for these flags in
- // CollectArgsForIntegratedAssembler but we can't change the ArchName at
- // that point. There is no assembler equivalent of -mno-thumb, -marm, or
- // -mno-arm.
- for (const auto *A :
- Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
- for (StringRef Value : A->getValues()) {
- if (Value == "-mthumb")
- IsThumb = true;
- }
- }
- }
- // Assembly files should start in ARM mode, unless arch is M-profile, or
- // -mthumb has been passed explicitly to the assembler. Windows is always
- // thumb.
- if (IsThumb || IsMProfile || getTriple().isOSWindows()) {
- if (IsBigEndian)
- ArchName = "thumbeb";
- else
- ArchName = "thumb";
- }
- Triple.setArchName(ArchName + Suffix.str());
-
- bool isHardFloat =
- (arm::getARMFloatABI(getDriver(), Triple, Args) == arm::FloatABI::Hard);
- switch (Triple.getEnvironment()) {
- case Triple::GNUEABI:
- case Triple::GNUEABIHF:
- Triple.setEnvironment(isHardFloat ? Triple::GNUEABIHF : Triple::GNUEABI);
- break;
- case Triple::EABI:
- case Triple::EABIHF:
- Triple.setEnvironment(isHardFloat ? Triple::EABIHF : Triple::EABI);
- break;
- case Triple::MuslEABI:
- case Triple::MuslEABIHF:
- Triple.setEnvironment(isHardFloat ? Triple::MuslEABIHF
- : Triple::MuslEABI);
- break;
- default: {
- arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple);
- if (DefaultABI != arm::FloatABI::Invalid &&
- isHardFloat != (DefaultABI == arm::FloatABI::Hard)) {
- Arg *ABIArg =
- Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
- options::OPT_mfloat_abi_EQ);
- assert(ABIArg && "Non-default float abi expected to be from arg");
- D.Diag(diag::err_drv_unsupported_opt_for_target)
- << ABIArg->getAsString(Args) << Triple.getTriple();
- }
- break;
- }
- }
-
+ tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple);
+ tools::arm::setFloatABIInTriple(getDriver(), Args, Triple);
return Triple.getTriple();
}
}
@@ -873,66 +754,89 @@
ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
const ArgList &Args) const {
+ if (runtimeLibType)
+ return *runtimeLibType;
+
const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
// Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
if (LibName == "compiler-rt")
- return ToolChain::RLT_CompilerRT;
+ runtimeLibType = ToolChain::RLT_CompilerRT;
else if (LibName == "libgcc")
- return ToolChain::RLT_Libgcc;
+ runtimeLibType = ToolChain::RLT_Libgcc;
else if (LibName == "platform")
- return GetDefaultRuntimeLibType();
+ runtimeLibType = GetDefaultRuntimeLibType();
+ else {
+ if (A)
+ getDriver().Diag(diag::err_drv_invalid_rtlib_name)
+ << A->getAsString(Args);
- if (A)
- getDriver().Diag(diag::err_drv_invalid_rtlib_name) << A->getAsString(Args);
+ runtimeLibType = GetDefaultRuntimeLibType();
+ }
- return GetDefaultRuntimeLibType();
+ return *runtimeLibType;
}
ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
const ArgList &Args) const {
+ if (unwindLibType)
+ return *unwindLibType;
+
const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);
StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB;
if (LibName == "none")
- return ToolChain::UNW_None;
+ unwindLibType = ToolChain::UNW_None;
else if (LibName == "platform" || LibName == "") {
ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);
- if (RtLibType == ToolChain::RLT_CompilerRT)
- return ToolChain::UNW_None;
- else if (RtLibType == ToolChain::RLT_Libgcc)
- return ToolChain::UNW_Libgcc;
+ if (RtLibType == ToolChain::RLT_CompilerRT) {
+ if (getTriple().isAndroid() || getTriple().isOSAIX())
+ unwindLibType = ToolChain::UNW_CompilerRT;
+ else
+ unwindLibType = ToolChain::UNW_None;
+ } else if (RtLibType == ToolChain::RLT_Libgcc)
+ unwindLibType = ToolChain::UNW_Libgcc;
} else if (LibName == "libunwind") {
if (GetRuntimeLibType(Args) == RLT_Libgcc)
getDriver().Diag(diag::err_drv_incompatible_unwindlib);
- return ToolChain::UNW_CompilerRT;
+ unwindLibType = ToolChain::UNW_CompilerRT;
} else if (LibName == "libgcc")
- return ToolChain::UNW_Libgcc;
+ unwindLibType = ToolChain::UNW_Libgcc;
+ else {
+ if (A)
+ getDriver().Diag(diag::err_drv_invalid_unwindlib_name)
+ << A->getAsString(Args);
- if (A)
- getDriver().Diag(diag::err_drv_invalid_unwindlib_name)
- << A->getAsString(Args);
+ unwindLibType = GetDefaultUnwindLibType();
+ }
- return GetDefaultUnwindLibType();
+ return *unwindLibType;
}
ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
+ if (cxxStdlibType)
+ return *cxxStdlibType;
+
const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;
// Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!
if (LibName == "libc++")
- return ToolChain::CST_Libcxx;
+ cxxStdlibType = ToolChain::CST_Libcxx;
else if (LibName == "libstdc++")
- return ToolChain::CST_Libstdcxx;
+ cxxStdlibType = ToolChain::CST_Libstdcxx;
else if (LibName == "platform")
- return GetDefaultCXXStdlibType();
+ cxxStdlibType = GetDefaultCXXStdlibType();
+ else {
+ if (A)
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
- if (A)
- getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
+ cxxStdlibType = GetDefaultCXXStdlibType();
+ }
- return GetDefaultCXXStdlibType();
+ return *cxxStdlibType;
}
/// Utility function to add a system include directory to CC1 arguments.
@@ -975,6 +879,29 @@
}
}
+std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {
+ std::error_code EC;
+ int MaxVersion = 0;
+ std::string MaxVersionString;
+ SmallString<128> Path(IncludePath);
+ llvm::sys::path::append(Path, "c++");
+ for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
+ int Version;
+ if (VersionText[0] == 'v' &&
+ !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
+ if (Version > MaxVersion) {
+ MaxVersion = Version;
+ MaxVersionString = std::string(VersionText);
+ }
+ }
+ }
+ if (!MaxVersion)
+ return "";
+ return MaxVersionString;
+}
+
void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Header search paths should be handled by each of the subclasses.
@@ -993,7 +920,8 @@
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);
- if (!DriverArgs.hasArg(options::OPT_nostdincxx))
+ if (!DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
+ options::OPT_nostdlibinc))
for (const auto &P :
DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))
addSystemInclude(DriverArgs, CC1Args, P);
@@ -1096,6 +1024,11 @@
void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
+llvm::SmallVector<std::string, 12>
+ToolChain::getHIPDeviceLibs(const ArgList &DriverArgs) const {
+ return {};
+}
+
void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
index 36fe578..3000b84 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
@@ -176,7 +176,9 @@
/// AIX - AIX tool chain which can call as(1) and ld(1) directly.
AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {
- getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+ ParseInlineAsmUsingAsmParser = Args.hasFlag(
+ options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true);
+ getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib");
}
// Returns the effective header sysroot path to use.
@@ -221,6 +223,7 @@
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
return;
case ToolChain::CST_Libstdcxx:
llvm::report_fatal_error("linking libstdc++ unimplemented on AIX");
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/AIX.h b/src/llvm-project/clang/lib/Driver/ToolChains/AIX.h
index d4e5932..d1ec6d1 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/AIX.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/AIX.h
@@ -59,6 +59,9 @@
AIX(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
+ bool parseInlineAsmUsingAsmParser() const override {
+ return ParseInlineAsmUsingAsmParser;
+ }
bool isPICDefault() const override { return true; }
bool isPIEDefault() const override { return false; }
bool isPICDefaultForced() const override { return true; }
@@ -74,12 +77,20 @@
RuntimeLibType GetDefaultRuntimeLibType() const override;
+ // Set default DWARF version to 3 for now as latest AIX OS supports version 3.
+ unsigned GetDefaultDwarfVersion() const override { return 3; }
+
+ llvm::DebuggerKind getDefaultDebuggerTuning() const override {
+ return llvm::DebuggerKind::DBX;
+ }
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
private:
llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const;
+ bool ParseInlineAsmUsingAsmParser;
};
} // end namespace toolchains
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 0971a2d..d63c5e1 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -8,13 +8,20 @@
#include "AMDGPU.h"
#include "CommonArgs.h"
-#include "InputInfo.h"
#include "clang/Basic/TargetID.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
+#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/LineIterator.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include <system_error>
+
+#define AMDGPU_ARCH_PROGRAM_NAME "amdgpu-arch"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -22,6 +29,48 @@
using namespace clang;
using namespace llvm::opt;
+// Look for sub-directory starts with PackageName under ROCm candidate path.
+// If there is one and only one matching sub-directory found, append the
+// sub-directory to Path. If there is no matching sub-directory or there are
+// more than one matching sub-directories, diagnose them. Returns the full
+// path of the package if there is only one matching sub-directory, otherwise
+// returns an empty string.
+llvm::SmallString<0>
+RocmInstallationDetector::findSPACKPackage(const Candidate &Cand,
+ StringRef PackageName) {
+ if (!Cand.isSPACK())
+ return {};
+ std::error_code EC;
+ std::string Prefix = Twine(PackageName + "-" + Cand.SPACKReleaseStr).str();
+ llvm::SmallVector<llvm::SmallString<0>> SubDirs;
+ for (llvm::vfs::directory_iterator File = D.getVFS().dir_begin(Cand.Path, EC),
+ FileEnd;
+ File != FileEnd && !EC; File.increment(EC)) {
+ llvm::StringRef FileName = llvm::sys::path::filename(File->path());
+ if (FileName.startswith(Prefix)) {
+ SubDirs.push_back(FileName);
+ if (SubDirs.size() > 1)
+ break;
+ }
+ }
+ if (SubDirs.size() == 1) {
+ auto PackagePath = Cand.Path;
+ llvm::sys::path::append(PackagePath, SubDirs[0]);
+ return PackagePath;
+ }
+ if (SubDirs.size() == 0 && Verbose) {
+ llvm::errs() << "SPACK package " << Prefix << " not found at " << Cand.Path
+ << '\n';
+ return {};
+ }
+
+ if (SubDirs.size() > 1 && Verbose) {
+ llvm::errs() << "Cannot use SPACK package " << Prefix << " at " << Cand.Path
+ << " due to multiple installations for the same version\n";
+ }
+ return {};
+}
+
void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
assert(!Path.empty());
@@ -50,6 +99,8 @@
OpenCL = FilePath;
} else if (BaseName == "hip") {
HIP = FilePath;
+ } else if (BaseName == "asanrtl") {
+ AsanRTL = FilePath;
} else if (BaseName == "oclc_finite_only_off") {
FiniteOnly.Off = FilePath;
} else if (BaseName == "oclc_finite_only_on") {
@@ -114,13 +165,37 @@
return false;
}
-// For candidate specified by --rocm-path we do not do strict check.
-SmallVector<RocmInstallationDetector::Candidate, 4>
+/// \returns a list of candidate directories for ROCm installation, which is
+/// cached and populated only once.
+const SmallVectorImpl<RocmInstallationDetector::Candidate> &
RocmInstallationDetector::getInstallationPathCandidates() {
- SmallVector<Candidate, 4> Candidates;
+
+ // Return the cached candidate list if it has already been populated.
+ if (!ROCmSearchDirs.empty())
+ return ROCmSearchDirs;
+
+ auto DoPrintROCmSearchDirs = [&]() {
+ if (PrintROCmSearchDirs)
+ for (auto Cand : ROCmSearchDirs) {
+ llvm::errs() << "ROCm installation search path";
+ if (Cand.isSPACK())
+ llvm::errs() << " (Spack " << Cand.SPACKReleaseStr << ")";
+ llvm::errs() << ": " << Cand.Path << '\n';
+ }
+ };
+
+ // For candidate specified by --rocm-path we do not do strict check, i.e.,
+ // checking existence of HIP version file and device library files.
if (!RocmPathArg.empty()) {
- Candidates.emplace_back(RocmPathArg.str());
- return Candidates;
+ ROCmSearchDirs.emplace_back(RocmPathArg.str());
+ DoPrintROCmSearchDirs();
+ return ROCmSearchDirs;
+ } else if (const char *RocmPathEnv = ::getenv("ROCM_PATH")) {
+ if (!StringRef(RocmPathEnv).empty()) {
+ ROCmSearchDirs.emplace_back(RocmPathEnv);
+ DoPrintROCmSearchDirs();
+ return ROCmSearchDirs;
+ }
}
// Try to find relative to the compiler binary.
@@ -129,41 +204,120 @@
// Check both a normal Unix prefix position of the clang binary, as well as
// the Windows-esque layout the ROCm packages use with the host architecture
// subdirectory of bin.
+ auto DeduceROCmPath = [](StringRef ClangPath) {
+ // Strip off directory (usually bin)
+ StringRef ParentDir = llvm::sys::path::parent_path(ClangPath);
+ StringRef ParentName = llvm::sys::path::filename(ParentDir);
- // Strip off directory (usually bin)
- StringRef ParentDir = llvm::sys::path::parent_path(InstallDir);
- StringRef ParentName = llvm::sys::path::filename(ParentDir);
+ // Some builds use bin/{host arch}, so go up again.
+ if (ParentName == "bin") {
+ ParentDir = llvm::sys::path::parent_path(ParentDir);
+ ParentName = llvm::sys::path::filename(ParentDir);
+ }
- // Some builds use bin/{host arch}, so go up again.
- if (ParentName == "bin") {
- ParentDir = llvm::sys::path::parent_path(ParentDir);
- ParentName = llvm::sys::path::filename(ParentDir);
+ // Detect ROCm packages built with SPACK.
+ // clang is installed at
+ // <rocm_root>/llvm-amdgpu-<rocm_release_string>-<hash>/bin directory.
+ // We only consider the parent directory of llvm-amdgpu package as ROCm
+ // installation candidate for SPACK.
+ if (ParentName.startswith("llvm-amdgpu-")) {
+ auto SPACKPostfix =
+ ParentName.drop_front(strlen("llvm-amdgpu-")).split('-');
+ auto SPACKReleaseStr = SPACKPostfix.first;
+ if (!SPACKReleaseStr.empty()) {
+ ParentDir = llvm::sys::path::parent_path(ParentDir);
+ return Candidate(ParentDir.str(), /*StrictChecking=*/true,
+ SPACKReleaseStr);
+ }
+ }
+
+ // Some versions of the rocm llvm package install to /opt/rocm/llvm/bin
+ // Some versions of the aomp package install to /opt/rocm/aomp/bin
+ if (ParentName == "llvm" || ParentName.startswith("aomp"))
+ ParentDir = llvm::sys::path::parent_path(ParentDir);
+
+ return Candidate(ParentDir.str(), /*StrictChecking=*/true);
+ };
+
+ // Deduce ROCm path by the path used to invoke clang. Do not resolve symbolic
+ // link of clang itself.
+ ROCmSearchDirs.emplace_back(DeduceROCmPath(InstallDir));
+
+ // Deduce ROCm path by the real path of the invoked clang, resolving symbolic
+ // link of clang itself.
+ llvm::SmallString<256> RealClangPath;
+ llvm::sys::fs::real_path(D.getClangProgramPath(), RealClangPath);
+ auto ParentPath = llvm::sys::path::parent_path(RealClangPath);
+ if (ParentPath != InstallDir)
+ ROCmSearchDirs.emplace_back(DeduceROCmPath(ParentPath));
+
+ // Device library may be installed in clang or resource directory.
+ auto ClangRoot = llvm::sys::path::parent_path(InstallDir);
+ auto RealClangRoot = llvm::sys::path::parent_path(ParentPath);
+ ROCmSearchDirs.emplace_back(ClangRoot.str(), /*StrictChecking=*/true);
+ if (RealClangRoot != ClangRoot)
+ ROCmSearchDirs.emplace_back(RealClangRoot.str(), /*StrictChecking=*/true);
+ ROCmSearchDirs.emplace_back(D.ResourceDir,
+ /*StrictChecking=*/true);
+
+ ROCmSearchDirs.emplace_back(D.SysRoot + "/opt/rocm",
+ /*StrictChecking=*/true);
+
+ // Find the latest /opt/rocm-{release} directory.
+ std::error_code EC;
+ std::string LatestROCm;
+ llvm::VersionTuple LatestVer;
+ // Get ROCm version from ROCm directory name.
+ auto GetROCmVersion = [](StringRef DirName) {
+ llvm::VersionTuple V;
+ std::string VerStr = DirName.drop_front(strlen("rocm-")).str();
+ // The ROCm directory name follows the format of
+ // rocm-{major}.{minor}.{subMinor}[-{build}]
+ std::replace(VerStr.begin(), VerStr.end(), '-', '.');
+ V.tryParse(VerStr);
+ return V;
+ };
+ for (llvm::vfs::directory_iterator
+ File = D.getVFS().dir_begin(D.SysRoot + "/opt", EC),
+ FileEnd;
+ File != FileEnd && !EC; File.increment(EC)) {
+ llvm::StringRef FileName = llvm::sys::path::filename(File->path());
+ if (!FileName.startswith("rocm-"))
+ continue;
+ if (LatestROCm.empty()) {
+ LatestROCm = FileName.str();
+ LatestVer = GetROCmVersion(LatestROCm);
+ continue;
+ }
+ auto Ver = GetROCmVersion(FileName);
+ if (LatestVer < Ver) {
+ LatestROCm = FileName.str();
+ LatestVer = Ver;
+ }
}
+ if (!LatestROCm.empty())
+ ROCmSearchDirs.emplace_back(D.SysRoot + "/opt/" + LatestROCm,
+ /*StrictChecking=*/true);
- // Some versions of the rocm llvm package install to /opt/rocm/llvm/bin
- if (ParentName == "llvm")
- ParentDir = llvm::sys::path::parent_path(ParentDir);
-
- Candidates.emplace_back(ParentDir.str(), /*StrictChecking=*/true);
-
- // Device library may be installed in clang resource directory.
- Candidates.emplace_back(D.ResourceDir, /*StrictChecking=*/true);
-
- Candidates.emplace_back(D.SysRoot + "/opt/rocm", /*StrictChecking=*/true);
- return Candidates;
+ DoPrintROCmSearchDirs();
+ return ROCmSearchDirs;
}
RocmInstallationDetector::RocmInstallationDetector(
const Driver &D, const llvm::Triple &HostTriple,
const llvm::opt::ArgList &Args, bool DetectHIPRuntime, bool DetectDeviceLib)
: D(D) {
+ Verbose = Args.hasArg(options::OPT_v);
RocmPathArg = Args.getLastArgValue(clang::driver::options::OPT_rocm_path_EQ);
+ PrintROCmSearchDirs =
+ Args.hasArg(clang::driver::options::OPT_print_rocm_search_dirs);
RocmDeviceLibPathArg =
Args.getAllArgValues(clang::driver::options::OPT_rocm_device_lib_path_EQ);
+ HIPPathArg = Args.getLastArgValue(clang::driver::options::OPT_hip_path_EQ);
if (auto *A = Args.getLastArg(clang::driver::options::OPT_hip_version_EQ)) {
HIPVersionArg = A->getValue();
- unsigned Major = 0;
- unsigned Minor = 0;
+ unsigned Major = ~0U;
+ unsigned Minor = ~0U;
SmallVector<StringRef, 3> Parts;
HIPVersionArg.split(Parts, '.');
if (Parts.size())
@@ -174,7 +328,9 @@
VersionPatch = Parts[2].str();
if (VersionPatch.empty())
VersionPatch = "0";
- if (Major == 0 || Minor == 0)
+ if (Major != ~0U && Minor == ~0U)
+ Minor = 0;
+ if (Major == ~0U || Minor == ~0U)
D.Diag(diag::err_drv_invalid_value)
<< A->getAsString(Args) << HIPVersionArg;
@@ -222,8 +378,8 @@
// exist for each frontend project, and differ depending on which build
// system produced the packages. Standalone OpenCL builds also have a
// different directory structure from the ROCm OpenCL package.
- auto Candidates = getInstallationPathCandidates();
- for (const auto &Candidate : Candidates) {
+ auto &ROCmDirs = getInstallationPathCandidates();
+ for (const auto &Candidate : ROCmDirs) {
auto CandidatePath = Candidate.Path;
// Check device library exists at the given path.
@@ -276,13 +432,21 @@
}
void RocmInstallationDetector::detectHIPRuntime() {
- auto Candidates = getInstallationPathCandidates();
+ SmallVector<Candidate, 4> HIPSearchDirs;
+ if (!HIPPathArg.empty())
+ HIPSearchDirs.emplace_back(HIPPathArg.str(), /*StrictChecking=*/true);
+ else
+ HIPSearchDirs.append(getInstallationPathCandidates());
auto &FS = D.getVFS();
- for (const auto &Candidate : Candidates) {
+ for (const auto &Candidate : HIPSearchDirs) {
InstallPath = Candidate.Path;
if (InstallPath.empty() || !FS.exists(InstallPath))
continue;
+ // HIP runtime built by SPACK is installed to
+ // <rocm_root>/hip-<rocm_release_string>-<hash> directory.
+ auto SPACKPath = findSPACKPackage(Candidate, "hip");
+ InstallPath = SPACKPath.empty() ? InstallPath : SPACKPath;
BinPath = InstallPath;
llvm::sys::path::append(BinPath, "bin");
@@ -413,7 +577,7 @@
// and errors for the last invalid code object version options.
// It is done here to avoid repeated warning or error messages for
// each tool invocation.
- (void)getOrCheckAMDGPUCodeObjectVersion(D, Args, /*Diagnose=*/true);
+ checkAMDGPUCodeObjectVersion(D, Args);
}
Tool *AMDGPUToolChain::buildLinker() const {
@@ -488,8 +652,8 @@
auto Arch = getProcessorFromTargetID(getTriple(), JA.getOffloadingArch());
auto Kind = llvm::AMDGPU::parseArchAMDGCN(Arch);
if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
- DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
- options::OPT_fno_cuda_flush_denormals_to_zero,
+ DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
+ options::OPT_fno_gpu_flush_denormals_to_zero,
getDefaultDenormsAreZeroForTarget(Kind)))
return llvm::DenormalMode::getPreserveSign();
@@ -547,19 +711,101 @@
getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
}
-void AMDGPUToolChain::checkTargetID(
- const llvm::opt::ArgList &DriverArgs) const {
+AMDGPUToolChain::ParsedTargetIDType
+AMDGPUToolChain::getParsedTargetID(const llvm::opt::ArgList &DriverArgs) const {
StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
if (TargetID.empty())
- return;
+ return {None, None, None};
llvm::StringMap<bool> FeatureMap;
auto OptionalGpuArch = parseTargetID(getTriple(), TargetID, &FeatureMap);
- if (!OptionalGpuArch) {
- getDriver().Diag(clang::diag::err_drv_bad_target_id) << TargetID;
+ if (!OptionalGpuArch)
+ return {TargetID.str(), None, None};
+
+ return {TargetID.str(), OptionalGpuArch.getValue().str(), FeatureMap};
+}
+
+void AMDGPUToolChain::checkTargetID(
+ const llvm::opt::ArgList &DriverArgs) const {
+ auto PTID = getParsedTargetID(DriverArgs);
+ if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
+ getDriver().Diag(clang::diag::err_drv_bad_target_id)
+ << PTID.OptionalTargetID.getValue();
}
}
+llvm::Error
+AMDGPUToolChain::detectSystemGPUs(const ArgList &Args,
+ SmallVector<std::string, 1> &GPUArchs) const {
+ std::string Program;
+ if (Arg *A = Args.getLastArg(options::OPT_amdgpu_arch_tool_EQ))
+ Program = A->getValue();
+ else
+ Program = GetProgramPath(AMDGPU_ARCH_PROGRAM_NAME);
+ llvm::SmallString<64> OutputFile;
+ llvm::sys::fs::createTemporaryFile("print-system-gpus", "" /* No Suffix */,
+ OutputFile);
+ llvm::FileRemover OutputRemover(OutputFile.c_str());
+ llvm::Optional<llvm::StringRef> Redirects[] = {
+ {""},
+ OutputFile.str(),
+ {""},
+ };
+
+ std::string ErrorMessage;
+ if (int Result = llvm::sys::ExecuteAndWait(
+ Program.c_str(), {}, {}, Redirects, /* SecondsToWait */ 0,
+ /*MemoryLimit*/ 0, &ErrorMessage)) {
+ if (Result > 0) {
+ ErrorMessage = "Exited with error code " + std::to_string(Result);
+ } else if (Result == -1) {
+ ErrorMessage = "Execute failed: " + ErrorMessage;
+ } else {
+ ErrorMessage = "Crashed: " + ErrorMessage;
+ }
+
+ return llvm::createStringError(std::error_code(),
+ Program + ": " + ErrorMessage);
+ }
+
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
+ llvm::MemoryBuffer::getFile(OutputFile.c_str());
+ if (!OutputBuf) {
+ return llvm::createStringError(OutputBuf.getError(),
+ "Failed to read stdout of " + Program +
+ ": " + OutputBuf.getError().message());
+ }
+
+ for (llvm::line_iterator LineIt(**OutputBuf); !LineIt.is_at_end(); ++LineIt) {
+ GPUArchs.push_back(LineIt->str());
+ }
+ return llvm::Error::success();
+}
+
+llvm::Error AMDGPUToolChain::getSystemGPUArch(const ArgList &Args,
+ std::string &GPUArch) const {
+ // detect the AMDGPU installed in system
+ SmallVector<std::string, 1> GPUArchs;
+ auto Err = detectSystemGPUs(Args, GPUArchs);
+ if (Err) {
+ return Err;
+ }
+ if (GPUArchs.empty()) {
+ return llvm::createStringError(std::error_code(),
+ "No AMD GPU detected in the system");
+ }
+ GPUArch = GPUArchs[0];
+ if (GPUArchs.size() > 1) {
+ bool AllSame = std::all_of(
+ GPUArchs.begin(), GPUArchs.end(),
+ [&](const StringRef &GPUArch) { return GPUArch == GPUArchs.front(); });
+ if (!AllSame)
+ return llvm::createStringError(
+ std::error_code(), "Multiple AMD GPUs found with different archs");
+ }
+ return llvm::Error::success();
+}
+
void ROCMToolChain::addClangTargetOptions(
const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadingKind) const {
@@ -605,47 +851,40 @@
DriverArgs.hasArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt);
// Add the OpenCL specific bitcode library.
- CC1Args.push_back("-mlink-builtin-bitcode");
- CC1Args.push_back(DriverArgs.MakeArgString(RocmInstallation.getOpenCLPath()));
+ llvm::SmallVector<std::string, 12> BCLibs;
+ BCLibs.push_back(RocmInstallation.getOpenCLPath().str());
// Add the generic set of libraries.
- RocmInstallation.addCommonBitcodeLibCC1Args(
- DriverArgs, CC1Args, LibDeviceFile, Wave64, DAZ, FiniteOnly,
- UnsafeMathOpt, FastRelaxedMath, CorrectSqrt);
+ BCLibs.append(RocmInstallation.getCommonBitcodeLibs(
+ DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
+ FastRelaxedMath, CorrectSqrt));
+
+ llvm::for_each(BCLibs, [&](StringRef BCFile) {
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
+ });
}
-void RocmInstallationDetector::addCommonBitcodeLibCC1Args(
- const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
- StringRef LibDeviceFile, bool Wave64, bool DAZ, bool FiniteOnly,
- bool UnsafeMathOpt, bool FastRelaxedMath, bool CorrectSqrt) const {
- static const char LinkBitcodeFlag[] = "-mlink-builtin-bitcode";
+llvm::SmallVector<std::string, 12>
+RocmInstallationDetector::getCommonBitcodeLibs(
+ const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64,
+ bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, bool FastRelaxedMath,
+ bool CorrectSqrt) const {
- CC1Args.push_back(LinkBitcodeFlag);
- CC1Args.push_back(DriverArgs.MakeArgString(getOCMLPath()));
+ llvm::SmallVector<std::string, 12> BCLibs;
- CC1Args.push_back(LinkBitcodeFlag);
- CC1Args.push_back(DriverArgs.MakeArgString(getOCKLPath()));
+ auto AddBCLib = [&](StringRef BCFile) { BCLibs.push_back(BCFile.str()); };
- CC1Args.push_back(LinkBitcodeFlag);
- CC1Args.push_back(DriverArgs.MakeArgString(getDenormalsAreZeroPath(DAZ)));
+ AddBCLib(getOCMLPath());
+ AddBCLib(getOCKLPath());
+ AddBCLib(getDenormalsAreZeroPath(DAZ));
+ AddBCLib(getUnsafeMathPath(UnsafeMathOpt || FastRelaxedMath));
+ AddBCLib(getFiniteOnlyPath(FiniteOnly || FastRelaxedMath));
+ AddBCLib(getCorrectlyRoundedSqrtPath(CorrectSqrt));
+ AddBCLib(getWavefrontSize64Path(Wave64));
+ AddBCLib(LibDeviceFile);
- CC1Args.push_back(LinkBitcodeFlag);
- CC1Args.push_back(DriverArgs.MakeArgString(
- getUnsafeMathPath(UnsafeMathOpt || FastRelaxedMath)));
-
- CC1Args.push_back(LinkBitcodeFlag);
- CC1Args.push_back(DriverArgs.MakeArgString(
- getFiniteOnlyPath(FiniteOnly || FastRelaxedMath)));
-
- CC1Args.push_back(LinkBitcodeFlag);
- CC1Args.push_back(
- DriverArgs.MakeArgString(getCorrectlyRoundedSqrtPath(CorrectSqrt)));
-
- CC1Args.push_back(LinkBitcodeFlag);
- CC1Args.push_back(DriverArgs.MakeArgString(getWavefrontSize64Path(Wave64)));
-
- CC1Args.push_back(LinkBitcodeFlag);
- CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
+ return BCLibs;
}
bool AMDGPUToolChain::shouldSkipArgument(const llvm::opt::Arg *A) const {
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h b/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h
index 55ef6e0..50ed3b3 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -64,6 +64,13 @@
bool IsIntegratedAssemblerDefault() const override { return true; }
bool IsMathErrnoDefault() const override { return false; }
+ bool useIntegratedAs() const override { return true; }
+ bool isCrossCompiling() const override { return true; }
+ bool isPICDefault() const override { return false; }
+ bool isPIEDefault() const override { return false; }
+ bool isPICDefaultForced() const override { return false; }
+ bool SupportsProfiling() const override { return false; }
+
llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;
@@ -93,12 +100,32 @@
/// Should skip argument.
bool shouldSkipArgument(const llvm::opt::Arg *Arg) const;
+ /// Uses amdgpu_arch tool to get arch of the system GPU. Will return error
+ /// if unable to find one.
+ llvm::Error getSystemGPUArch(const llvm::opt::ArgList &Args,
+ std::string &GPUArch) const;
+
protected:
/// Check and diagnose invalid target ID specified by -mcpu.
- void checkTargetID(const llvm::opt::ArgList &DriverArgs) const;
+ virtual void checkTargetID(const llvm::opt::ArgList &DriverArgs) const;
+
+ /// The struct type returned by getParsedTargetID.
+ struct ParsedTargetIDType {
+ Optional<std::string> OptionalTargetID;
+ Optional<std::string> OptionalGPUArch;
+ Optional<llvm::StringMap<bool>> OptionalFeatures;
+ };
+
+ /// Get target ID, GPU arch, and target ID features if the target ID is
+ /// specified and valid.
+ ParsedTargetIDType
+ getParsedTargetID(const llvm::opt::ArgList &DriverArgs) const;
/// Get GPU arch from -mcpu without checking.
StringRef getGPUArch(const llvm::opt::ArgList &DriverArgs) const;
+
+ llvm::Error detectSystemGPUs(const llvm::opt::ArgList &Args,
+ SmallVector<std::string, 1> &GPUArchs) const;
};
class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
new file mode 100644
index 0000000..fe1d19c
--- /dev/null
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -0,0 +1,304 @@
+//===- AMDGPUOpenMP.cpp - AMDGPUOpenMP ToolChain Implementation -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AMDGPUOpenMP.h"
+#include "AMDGPU.h"
+#include "CommonArgs.h"
+#include "clang/Basic/DiagnosticDriver.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+namespace {
+
+static const char *getOutputFileName(Compilation &C, StringRef Base,
+ const char *Postfix,
+ const char *Extension) {
+ const char *OutputFileName;
+ if (C.getDriver().isSaveTempsEnabled()) {
+ OutputFileName =
+ C.getArgs().MakeArgString(Base.str() + Postfix + "." + Extension);
+ } else {
+ std::string TmpName =
+ C.getDriver().GetTemporaryPath(Base.str() + Postfix, Extension);
+ OutputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName));
+ }
+ return OutputFileName;
+}
+
+static void addLLCOptArg(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ StringRef OOpt = "0";
+ if (A->getOption().matches(options::OPT_O4) ||
+ A->getOption().matches(options::OPT_Ofast))
+ OOpt = "3";
+ else if (A->getOption().matches(options::OPT_O0))
+ OOpt = "0";
+ else if (A->getOption().matches(options::OPT_O)) {
+ // Clang and opt support -Os/-Oz; llc only supports -O0, -O1, -O2 and -O3
+ // so we map -Os/-Oz to -O2.
+ // Only clang supports -Og, and maps it to -O1.
+ // We map anything else to -O2.
+ OOpt = llvm::StringSwitch<const char *>(A->getValue())
+ .Case("1", "1")
+ .Case("2", "2")
+ .Case("3", "3")
+ .Case("s", "2")
+ .Case("z", "2")
+ .Case("g", "1")
+ .Default("0");
+ }
+ CmdArgs.push_back(Args.MakeArgString("-O" + OOpt));
+ }
+}
+
+static bool checkSystemForAMDGPU(const ArgList &Args, const AMDGPUToolChain &TC,
+ std::string &GPUArch) {
+ if (auto Err = TC.getSystemGPUArch(Args, GPUArch)) {
+ std::string ErrMsg =
+ llvm::formatv("{0}", llvm::fmt_consume(std::move(Err)));
+ TC.getDriver().Diag(diag::err_drv_undetermined_amdgpu_arch) << ErrMsg;
+ return false;
+ }
+
+ return true;
+}
+} // namespace
+
+const char *AMDGCN::OpenMPLinker::constructLLVMLinkCommand(
+ Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
+ const ArgList &Args, StringRef SubArchName,
+ StringRef OutputFilePrefix) const {
+ ArgStringList CmdArgs;
+
+ for (const auto &II : Inputs)
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ // Add an intermediate output file.
+ CmdArgs.push_back("-o");
+ const char *OutputFileName =
+ getOutputFileName(C, OutputFilePrefix, "-linked", "bc");
+ CmdArgs.push_back(OutputFileName);
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs,
+ InputInfo(&JA, Args.MakeArgString(OutputFileName))));
+ return OutputFileName;
+}
+
+const char *AMDGCN::OpenMPLinker::constructLlcCommand(
+ Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix, const char *InputFileName,
+ bool OutputIsAsm) const {
+ // Construct llc command.
+ ArgStringList LlcArgs;
+ // The input to llc is the output from opt.
+ LlcArgs.push_back(InputFileName);
+ // Pass optimization arg to llc.
+ addLLCOptArg(Args, LlcArgs);
+ LlcArgs.push_back("-mtriple=amdgcn-amd-amdhsa");
+ LlcArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName));
+ LlcArgs.push_back(
+ Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj")));
+
+ for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
+ LlcArgs.push_back(A->getValue(0));
+ }
+
+ // Add output filename
+ LlcArgs.push_back("-o");
+ const char *LlcOutputFile =
+ getOutputFileName(C, OutputFilePrefix, "", OutputIsAsm ? "s" : "o");
+ LlcArgs.push_back(LlcOutputFile);
+ const char *Llc = Args.MakeArgString(getToolChain().GetProgramPath("llc"));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Llc, LlcArgs, Inputs,
+ InputInfo(&JA, Args.MakeArgString(LlcOutputFile))));
+ return LlcOutputFile;
+}
+
+void AMDGCN::OpenMPLinker::constructLldCommand(
+ Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
+ const InputInfo &Output, const llvm::opt::ArgList &Args,
+ const char *InputFileName) const {
+ // Construct lld command.
+ // The output from ld.lld is an HSA code object file.
+ ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined",
+ "-shared", "-o", Output.getFilename(),
+ InputFileName};
+
+ const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Lld, LldArgs, Inputs,
+ InputInfo(&JA, Args.MakeArgString(Output.getFilename()))));
+}
+
+// For amdgcn the inputs of the linker job are device bitcode and output is
+// object file. It calls llvm-link, opt, llc, then lld steps.
+void AMDGCN::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ToolChain &TC = getToolChain();
+ assert(getToolChain().getTriple().isAMDGCN() && "Unsupported target");
+
+ const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC =
+ static_cast<const toolchains::AMDGPUOpenMPToolChain &>(TC);
+
+ std::string GPUArch = Args.getLastArgValue(options::OPT_march_EQ).str();
+ if (GPUArch.empty()) {
+ if (!checkSystemForAMDGPU(Args, AMDGPUOpenMPTC, GPUArch))
+ return;
+ }
+
+ // Prefix for temporary file name.
+ std::string Prefix;
+ for (const auto &II : Inputs)
+ if (II.isFilename())
+ Prefix = llvm::sys::path::stem(II.getFilename()).str() + "-" + GPUArch;
+ assert(Prefix.length() && "no linker inputs are files ");
+
+ // Each command outputs different files.
+ const char *LLVMLinkCommand =
+ constructLLVMLinkCommand(C, JA, Inputs, Args, GPUArch, Prefix);
+
+ // Produce readable assembly if save-temps is enabled.
+ if (C.getDriver().isSaveTempsEnabled())
+ constructLlcCommand(C, JA, Inputs, Args, GPUArch, Prefix, LLVMLinkCommand,
+ /*OutputIsAsm=*/true);
+ const char *LlcCommand = constructLlcCommand(C, JA, Inputs, Args, GPUArch,
+ Prefix, LLVMLinkCommand);
+ constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
+}
+
+AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D,
+ const llvm::Triple &Triple,
+ const ToolChain &HostTC,
+ const ArgList &Args)
+ : ROCMToolChain(D, Triple, Args), HostTC(HostTC) {
+ // Lookup binaries into the driver directory, this is used to
+ // discover the clang-offload-bundler executable.
+ getProgramPaths().push_back(getDriver().Dir);
+}
+
+void AMDGPUOpenMPToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
+
+ std::string GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ).str();
+ if (GPUArch.empty()) {
+ if (!checkSystemForAMDGPU(DriverArgs, *this, GPUArch))
+ return;
+ }
+
+ assert(DeviceOffloadingKind == Action::OFK_OpenMP &&
+ "Only OpenMP offloading kinds are supported.");
+
+ CC1Args.push_back("-target-cpu");
+ CC1Args.push_back(DriverArgs.MakeArgStringRef(GPUArch));
+ CC1Args.push_back("-fcuda-is-device");
+
+ if (DriverArgs.hasArg(options::OPT_nogpulib))
+ return;
+
+ std::string BitcodeSuffix;
+ if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
+ options::OPT_fno_openmp_target_new_runtime, false))
+ BitcodeSuffix = "new-amdgcn-" + GPUArch;
+ else
+ BitcodeSuffix = "amdgcn-" + GPUArch;
+
+ addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix,
+ getTriple());
+}
+
+llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
+ const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
+ DerivedArgList *DAL =
+ HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+ if (!DAL)
+ DAL = new DerivedArgList(Args.getBaseArgs());
+
+ const OptTable &Opts = getDriver().getOpts();
+
+ if (DeviceOffloadKind != Action::OFK_OpenMP) {
+ for (Arg *A : Args) {
+ DAL->append(A);
+ }
+ }
+
+ if (!BoundArch.empty()) {
+ DAL->eraseArg(options::OPT_march_EQ);
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
+ BoundArch);
+ }
+
+ return DAL;
+}
+
+Tool *AMDGPUOpenMPToolChain::buildLinker() const {
+ assert(getTriple().isAMDGCN());
+ return new tools::AMDGCN::OpenMPLinker(*this);
+}
+
+void AMDGPUOpenMPToolChain::addClangWarningOptions(
+ ArgStringList &CC1Args) const {
+ HostTC.addClangWarningOptions(CC1Args);
+}
+
+ToolChain::CXXStdlibType
+AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const {
+ return HostTC.GetCXXStdlibType(Args);
+}
+
+void AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+}
+
+void AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
+ ArgStringList &CC1Args) const {
+ HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
+}
+
+SanitizerMask AMDGPUOpenMPToolChain::getSupportedSanitizers() const {
+ // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it
+ // allows sanitizer arguments on the command line if they are supported by the
+ // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command
+ // line arguments for any of these "supported" sanitizers. That means that no
+ // sanitization of device code is actually supported at this time.
+ //
+ // This behavior is necessary because the host and device toolchains
+ // invocations often share the command line, so the device toolchain must
+ // tolerate flags meant only for the host toolchain.
+ return HostTC.getSupportedSanitizers();
+}
+
+VersionTuple
+AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D,
+ const ArgList &Args) const {
+ return HostTC.computeMSVCVersion(D, Args);
+}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h b/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
new file mode 100644
index 0000000..effca7e
--- /dev/null
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
@@ -0,0 +1,106 @@
+//===- AMDGPUOpenMP.h - AMDGPUOpenMP ToolChain Implementation -*- C++ -*---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPUOPENMP_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPUOPENMP_H
+
+#include "AMDGPU.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+
+namespace tools {
+
+namespace AMDGCN {
+// Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with
+// device library, then compiles it to ISA in a shared object.
+class LLVM_LIBRARY_VISIBILITY OpenMPLinker : public Tool {
+public:
+ OpenMPLinker(const ToolChain &TC)
+ : Tool("AMDGCN::OpenMPLinker", "amdgcn-link", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+
+private:
+ /// \return llvm-link output file name.
+ const char *constructLLVMLinkCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix) const;
+
+ /// \return llc output file name.
+ const char *constructLlcCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix,
+ const char *InputFileName,
+ bool OutputIsAsm = false) const;
+
+ void constructLldCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs, const InputInfo &Output,
+ const llvm::opt::ArgList &Args,
+ const char *InputFileName) const;
+};
+
+} // end namespace AMDGCN
+} // end namespace tools
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY AMDGPUOpenMPToolChain final
+ : public ROCMToolChain {
+public:
+ AMDGPUOpenMPToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC,
+ const llvm::opt::ArgList &Args);
+
+ const llvm::Triple *getAuxTriple() const override {
+ return &HostTC.getTriple();
+ }
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ SanitizerMask getSupportedSanitizers() const override;
+
+ VersionTuple
+ computeMSVCVersion(const Driver *D,
+ const llvm::opt::ArgList &Args) const override;
+
+ const ToolChain &HostTC;
+
+protected:
+ Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPUOPENMP_H
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp
index ae56b7b..f147292 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp
@@ -8,9 +8,9 @@
#include "AVR.h"
#include "CommonArgs.h"
-#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringExtras.h"
@@ -32,247 +32,248 @@
StringRef Name;
std::string SubPath;
StringRef Family;
+ unsigned DataAddr;
} MCUInfo[] = {
- {"at90s1200", "", "avr1"},
- {"attiny11", "", "avr1"},
- {"attiny12", "", "avr1"},
- {"attiny15", "", "avr1"},
- {"attiny28", "", "avr1"},
- {"at90s2313", "tiny-stack", "avr2"},
- {"at90s2323", "tiny-stack", "avr2"},
- {"at90s2333", "tiny-stack", "avr2"},
- {"at90s2343", "tiny-stack", "avr2"},
- {"at90s4433", "tiny-stack", "avr2"},
- {"attiny22", "tiny-stack", "avr2"},
- {"attiny26", "tiny-stack", "avr2"},
- {"at90s4414", "", "avr2"},
- {"at90s4434", "", "avr2"},
- {"at90s8515", "", "avr2"},
- {"at90c8534", "", "avr2"},
- {"at90s8535", "", "avr2"},
- {"attiny13", "avr25/tiny-stack", "avr25"},
- {"attiny13a", "avr25/tiny-stack", "avr25"},
- {"attiny2313", "avr25/tiny-stack", "avr25"},
- {"attiny2313a", "avr25/tiny-stack", "avr25"},
- {"attiny24", "avr25/tiny-stack", "avr25"},
- {"attiny24a", "avr25/tiny-stack", "avr25"},
- {"attiny25", "avr25/tiny-stack", "avr25"},
- {"attiny261", "avr25/tiny-stack", "avr25"},
- {"attiny261a", "avr25/tiny-stack", "avr25"},
- {"at86rf401", "avr25", "avr25"},
- {"ata5272", "avr25", "avr25"},
- {"attiny4313", "avr25", "avr25"},
- {"attiny44", "avr25", "avr25"},
- {"attiny44a", "avr25", "avr25"},
- {"attiny84", "avr25", "avr25"},
- {"attiny84a", "avr25", "avr25"},
- {"attiny45", "avr25", "avr25"},
- {"attiny85", "avr25", "avr25"},
- {"attiny441", "avr25", "avr25"},
- {"attiny461", "avr25", "avr25"},
- {"attiny461a", "avr25", "avr25"},
- {"attiny841", "avr25", "avr25"},
- {"attiny861", "avr25", "avr25"},
- {"attiny861a", "avr25", "avr25"},
- {"attiny87", "avr25", "avr25"},
- {"attiny43u", "avr25", "avr25"},
- {"attiny48", "avr25", "avr25"},
- {"attiny88", "avr25", "avr25"},
- {"attiny828", "avr25", "avr25"},
- {"at43usb355", "avr3", "avr3"},
- {"at76c711", "avr3", "avr3"},
- {"atmega103", "avr31", "avr31"},
- {"at43usb320", "avr31", "avr31"},
- {"attiny167", "avr35", "avr35"},
- {"at90usb82", "avr35", "avr35"},
- {"at90usb162", "avr35", "avr35"},
- {"ata5505", "avr35", "avr35"},
- {"atmega8u2", "avr35", "avr35"},
- {"atmega16u2", "avr35", "avr35"},
- {"atmega32u2", "avr35", "avr35"},
- {"attiny1634", "avr35", "avr35"},
- {"atmega8", "avr4", "avr4"},
- {"ata6289", "avr4", "avr4"},
- {"atmega8a", "avr4", "avr4"},
- {"ata6285", "avr4", "avr4"},
- {"ata6286", "avr4", "avr4"},
- {"atmega48", "avr4", "avr4"},
- {"atmega48a", "avr4", "avr4"},
- {"atmega48pa", "avr4", "avr4"},
- {"atmega48pb", "avr4", "avr4"},
- {"atmega48p", "avr4", "avr4"},
- {"atmega88", "avr4", "avr4"},
- {"atmega88a", "avr4", "avr4"},
- {"atmega88p", "avr4", "avr4"},
- {"atmega88pa", "avr4", "avr4"},
- {"atmega88pb", "avr4", "avr4"},
- {"atmega8515", "avr4", "avr4"},
- {"atmega8535", "avr4", "avr4"},
- {"atmega8hva", "avr4", "avr4"},
- {"at90pwm1", "avr4", "avr4"},
- {"at90pwm2", "avr4", "avr4"},
- {"at90pwm2b", "avr4", "avr4"},
- {"at90pwm3", "avr4", "avr4"},
- {"at90pwm3b", "avr4", "avr4"},
- {"at90pwm81", "avr4", "avr4"},
- {"ata5790", "avr5", "avr5"},
- {"ata5795", "avr5", "avr5"},
- {"atmega16", "avr5", "avr5"},
- {"atmega16a", "avr5", "avr5"},
- {"atmega161", "avr5", "avr5"},
- {"atmega162", "avr5", "avr5"},
- {"atmega163", "avr5", "avr5"},
- {"atmega164a", "avr5", "avr5"},
- {"atmega164p", "avr5", "avr5"},
- {"atmega164pa", "avr5", "avr5"},
- {"atmega165", "avr5", "avr5"},
- {"atmega165a", "avr5", "avr5"},
- {"atmega165p", "avr5", "avr5"},
- {"atmega165pa", "avr5", "avr5"},
- {"atmega168", "avr5", "avr5"},
- {"atmega168a", "avr5", "avr5"},
- {"atmega168p", "avr5", "avr5"},
- {"atmega168pa", "avr5", "avr5"},
- {"atmega168pb", "avr5", "avr5"},
- {"atmega169", "avr5", "avr5"},
- {"atmega169a", "avr5", "avr5"},
- {"atmega169p", "avr5", "avr5"},
- {"atmega169pa", "avr5", "avr5"},
- {"atmega32", "avr5", "avr5"},
- {"atmega32a", "avr5", "avr5"},
- {"atmega323", "avr5", "avr5"},
- {"atmega324a", "avr5", "avr5"},
- {"atmega324p", "avr5", "avr5"},
- {"atmega324pa", "avr5", "avr5"},
- {"atmega325", "avr5", "avr5"},
- {"atmega325a", "avr5", "avr5"},
- {"atmega325p", "avr5", "avr5"},
- {"atmega325pa", "avr5", "avr5"},
- {"atmega3250", "avr5", "avr5"},
- {"atmega3250a", "avr5", "avr5"},
- {"atmega3250p", "avr5", "avr5"},
- {"atmega3250pa", "avr5", "avr5"},
- {"atmega328", "avr5", "avr5"},
- {"atmega328p", "avr5", "avr5"},
- {"atmega329", "avr5", "avr5"},
- {"atmega329a", "avr5", "avr5"},
- {"atmega329p", "avr5", "avr5"},
- {"atmega329pa", "avr5", "avr5"},
- {"atmega3290", "avr5", "avr5"},
- {"atmega3290a", "avr5", "avr5"},
- {"atmega3290p", "avr5", "avr5"},
- {"atmega3290pa", "avr5", "avr5"},
- {"atmega406", "avr5", "avr5"},
- {"atmega64", "avr5", "avr5"},
- {"atmega64a", "avr5", "avr5"},
- {"atmega640", "avr5", "avr5"},
- {"atmega644", "avr5", "avr5"},
- {"atmega644a", "avr5", "avr5"},
- {"atmega644p", "avr5", "avr5"},
- {"atmega644pa", "avr5", "avr5"},
- {"atmega645", "avr5", "avr5"},
- {"atmega645a", "avr5", "avr5"},
- {"atmega645p", "avr5", "avr5"},
- {"atmega649", "avr5", "avr5"},
- {"atmega649a", "avr5", "avr5"},
- {"atmega649p", "avr5", "avr5"},
- {"atmega6450", "avr5", "avr5"},
- {"atmega6450a", "avr5", "avr5"},
- {"atmega6450p", "avr5", "avr5"},
- {"atmega6490", "avr5", "avr5"},
- {"atmega6490a", "avr5", "avr5"},
- {"atmega6490p", "avr5", "avr5"},
- {"atmega64rfr2", "avr5", "avr5"},
- {"atmega644rfr2", "avr5", "avr5"},
- {"atmega16hva", "avr5", "avr5"},
- {"atmega16hva2", "avr5", "avr5"},
- {"atmega16hvb", "avr5", "avr5"},
- {"atmega16hvbrevb", "avr5", "avr5"},
- {"atmega32hvb", "avr5", "avr5"},
- {"atmega32hvbrevb", "avr5", "avr5"},
- {"atmega64hve", "avr5", "avr5"},
- {"at90can32", "avr5", "avr5"},
- {"at90can64", "avr5", "avr5"},
- {"at90pwm161", "avr5", "avr5"},
- {"at90pwm216", "avr5", "avr5"},
- {"at90pwm316", "avr5", "avr5"},
- {"atmega32c1", "avr5", "avr5"},
- {"atmega64c1", "avr5", "avr5"},
- {"atmega16m1", "avr5", "avr5"},
- {"atmega32m1", "avr5", "avr5"},
- {"atmega64m1", "avr5", "avr5"},
- {"atmega16u4", "avr5", "avr5"},
- {"atmega32u4", "avr5", "avr5"},
- {"atmega32u6", "avr5", "avr5"},
- {"at90usb646", "avr5", "avr5"},
- {"at90usb647", "avr5", "avr5"},
- {"at90scr100", "avr5", "avr5"},
- {"at94k", "avr5", "avr5"},
- {"m3000", "avr5", "avr5"},
- {"atmega128", "avr51", "avr51"},
- {"atmega128a", "avr51", "avr51"},
- {"atmega1280", "avr51", "avr51"},
- {"atmega1281", "avr51", "avr51"},
- {"atmega1284", "avr51", "avr51"},
- {"atmega1284p", "avr51", "avr51"},
- {"atmega128rfa1", "avr51", "avr51"},
- {"atmega128rfr2", "avr51", "avr51"},
- {"atmega1284rfr2", "avr51", "avr51"},
- {"at90can128", "avr51", "avr51"},
- {"at90usb1286", "avr51", "avr51"},
- {"at90usb1287", "avr51", "avr51"},
- {"atmega2560", "avr6", "avr6"},
- {"atmega2561", "avr6", "avr6"},
- {"atmega256rfr2", "avr6", "avr6"},
- {"atmega2564rfr2", "avr6", "avr6"},
- {"attiny4", "avrtiny", "avrtiny"},
- {"attiny5", "avrtiny", "avrtiny"},
- {"attiny9", "avrtiny", "avrtiny"},
- {"attiny10", "avrtiny", "avrtiny"},
- {"attiny20", "avrtiny", "avrtiny"},
- {"attiny40", "avrtiny", "avrtiny"},
- {"atxmega16a4", "avrxmega2", "avrxmega2"},
- {"atxmega16a4u", "avrxmega2", "avrxmega2"},
- {"atxmega16c4", "avrxmega2", "avrxmega2"},
- {"atxmega16d4", "avrxmega2", "avrxmega2"},
- {"atxmega32a4", "avrxmega2", "avrxmega2"},
- {"atxmega32a4u", "avrxmega2", "avrxmega2"},
- {"atxmega32c4", "avrxmega2", "avrxmega2"},
- {"atxmega32d4", "avrxmega2", "avrxmega2"},
- {"atxmega32e5", "avrxmega2", "avrxmega2"},
- {"atxmega16e5", "avrxmega2", "avrxmega2"},
- {"atxmega8e5", "avrxmega2", "avrxmega2"},
- {"atxmega64a3u", "avrxmega4", "avrxmega4"},
- {"atxmega64a4u", "avrxmega4", "avrxmega4"},
- {"atxmega64b1", "avrxmega4", "avrxmega4"},
- {"atxmega64b3", "avrxmega4", "avrxmega4"},
- {"atxmega64c3", "avrxmega4", "avrxmega4"},
- {"atxmega64d3", "avrxmega4", "avrxmega4"},
- {"atxmega64d4", "avrxmega4", "avrxmega4"},
- {"atxmega64a1", "avrxmega5", "avrxmega5"},
- {"atxmega64a1u", "avrxmega5", "avrxmega5"},
- {"atxmega128a3", "avrxmega6", "avrxmega6"},
- {"atxmega128a3u", "avrxmega6", "avrxmega6"},
- {"atxmega128b1", "avrxmega6", "avrxmega6"},
- {"atxmega128b3", "avrxmega6", "avrxmega6"},
- {"atxmega128c3", "avrxmega6", "avrxmega6"},
- {"atxmega128d3", "avrxmega6", "avrxmega6"},
- {"atxmega128d4", "avrxmega6", "avrxmega6"},
- {"atxmega192a3", "avrxmega6", "avrxmega6"},
- {"atxmega192a3u", "avrxmega6", "avrxmega6"},
- {"atxmega192c3", "avrxmega6", "avrxmega6"},
- {"atxmega192d3", "avrxmega6", "avrxmega6"},
- {"atxmega256a3", "avrxmega6", "avrxmega6"},
- {"atxmega256a3u", "avrxmega6", "avrxmega6"},
- {"atxmega256a3b", "avrxmega6", "avrxmega6"},
- {"atxmega256a3bu", "avrxmega6", "avrxmega6"},
- {"atxmega256c3", "avrxmega6", "avrxmega6"},
- {"atxmega256d3", "avrxmega6", "avrxmega6"},
- {"atxmega384c3", "avrxmega6", "avrxmega6"},
- {"atxmega384d3", "avrxmega6", "avrxmega6"},
- {"atxmega128a1", "avrxmega7", "avrxmega7"},
- {"atxmega128a1u", "avrxmega7", "avrxmega7"},
- {"atxmega128a4u", "avrxmega7", "avrxmega7"},
+ {"at90s1200", "", "avr1", 0},
+ {"attiny11", "", "avr1", 0},
+ {"attiny12", "", "avr1", 0},
+ {"attiny15", "", "avr1", 0},
+ {"attiny28", "", "avr1", 0},
+ {"at90s2313", "tiny-stack", "avr2", 0x800060},
+ {"at90s2323", "tiny-stack", "avr2", 0x800060},
+ {"at90s2333", "tiny-stack", "avr2", 0x800060},
+ {"at90s2343", "tiny-stack", "avr2", 0x800060},
+ {"at90s4433", "tiny-stack", "avr2", 0x800060},
+ {"attiny22", "tiny-stack", "avr2", 0x800060},
+ {"attiny26", "tiny-stack", "avr2", 0x800060},
+ {"at90s4414", "", "avr2", 0x800060},
+ {"at90s4434", "", "avr2", 0x800060},
+ {"at90s8515", "", "avr2", 0x800060},
+ {"at90c8534", "", "avr2", 0x800060},
+ {"at90s8535", "", "avr2", 0x800060},
+ {"attiny13", "avr25/tiny-stack", "avr25", 0x800060},
+ {"attiny13a", "avr25/tiny-stack", "avr25", 0x800060},
+ {"attiny2313", "avr25/tiny-stack", "avr25", 0x800060},
+ {"attiny2313a", "avr25/tiny-stack", "avr25", 0x800060},
+ {"attiny24", "avr25/tiny-stack", "avr25", 0x800060},
+ {"attiny24a", "avr25/tiny-stack", "avr25", 0x800060},
+ {"attiny25", "avr25/tiny-stack", "avr25", 0x800060},
+ {"attiny261", "avr25/tiny-stack", "avr25", 0x800060},
+ {"attiny261a", "avr25/tiny-stack", "avr25", 0x800060},
+ {"at86rf401", "avr25", "avr25", 0x800060},
+ {"ata5272", "avr25", "avr25", 0x800100},
+ {"attiny4313", "avr25", "avr25", 0x800060},
+ {"attiny44", "avr25", "avr25", 0x800060},
+ {"attiny44a", "avr25", "avr25", 0x800060},
+ {"attiny84", "avr25", "avr25", 0x800060},
+ {"attiny84a", "avr25", "avr25", 0x800060},
+ {"attiny45", "avr25", "avr25", 0x800060},
+ {"attiny85", "avr25", "avr25", 0x800060},
+ {"attiny441", "avr25", "avr25", 0x800100},
+ {"attiny461", "avr25", "avr25", 0x800060},
+ {"attiny461a", "avr25", "avr25", 0x800060},
+ {"attiny841", "avr25", "avr25", 0x800100},
+ {"attiny861", "avr25", "avr25", 0x800060},
+ {"attiny861a", "avr25", "avr25", 0x800060},
+ {"attiny87", "avr25", "avr25", 0x800100},
+ {"attiny43u", "avr25", "avr25", 0x800060},
+ {"attiny48", "avr25", "avr25", 0x800100},
+ {"attiny88", "avr25", "avr25", 0x800100},
+ {"attiny828", "avr25", "avr25", 0x800100},
+ {"at43usb355", "avr3", "avr3", 0x800100},
+ {"at76c711", "avr3", "avr3", 0x800060},
+ {"atmega103", "avr31", "avr31", 0x800060},
+ {"at43usb320", "avr31", "avr31", 0x800060},
+ {"attiny167", "avr35", "avr35", 0x800100},
+ {"at90usb82", "avr35", "avr35", 0x800100},
+ {"at90usb162", "avr35", "avr35", 0x800100},
+ {"ata5505", "avr35", "avr35", 0x800100},
+ {"atmega8u2", "avr35", "avr35", 0x800100},
+ {"atmega16u2", "avr35", "avr35", 0x800100},
+ {"atmega32u2", "avr35", "avr35", 0x800100},
+ {"attiny1634", "avr35", "avr35", 0x800100},
+ {"atmega8", "avr4", "avr4", 0x800060},
+ {"ata6289", "avr4", "avr4", 0x800100},
+ {"atmega8a", "avr4", "avr4", 0x800060},
+ {"ata6285", "avr4", "avr4", 0x800100},
+ {"ata6286", "avr4", "avr4", 0x800100},
+ {"atmega48", "avr4", "avr4", 0x800100},
+ {"atmega48a", "avr4", "avr4", 0x800100},
+ {"atmega48pa", "avr4", "avr4", 0x800100},
+ {"atmega48pb", "avr4", "avr4", 0x800100},
+ {"atmega48p", "avr4", "avr4", 0x800100},
+ {"atmega88", "avr4", "avr4", 0x800100},
+ {"atmega88a", "avr4", "avr4", 0x800100},
+ {"atmega88p", "avr4", "avr4", 0x800100},
+ {"atmega88pa", "avr4", "avr4", 0x800100},
+ {"atmega88pb", "avr4", "avr4", 0x800100},
+ {"atmega8515", "avr4", "avr4", 0x800060},
+ {"atmega8535", "avr4", "avr4", 0x800060},
+ {"atmega8hva", "avr4", "avr4", 0x800100},
+ {"at90pwm1", "avr4", "avr4", 0x800100},
+ {"at90pwm2", "avr4", "avr4", 0x800100},
+ {"at90pwm2b", "avr4", "avr4", 0x800100},
+ {"at90pwm3", "avr4", "avr4", 0x800100},
+ {"at90pwm3b", "avr4", "avr4", 0x800100},
+ {"at90pwm81", "avr4", "avr4", 0x800100},
+ {"ata5790", "avr5", "avr5", 0x800100},
+ {"ata5795", "avr5", "avr5", 0x800100},
+ {"atmega16", "avr5", "avr5", 0x800060},
+ {"atmega16a", "avr5", "avr5", 0x800060},
+ {"atmega161", "avr5", "avr5", 0x800060},
+ {"atmega162", "avr5", "avr5", 0x800100},
+ {"atmega163", "avr5", "avr5", 0x800060},
+ {"atmega164a", "avr5", "avr5", 0x800100},
+ {"atmega164p", "avr5", "avr5", 0x800100},
+ {"atmega164pa", "avr5", "avr5", 0x800100},
+ {"atmega165", "avr5", "avr5", 0x800100},
+ {"atmega165a", "avr5", "avr5", 0x800100},
+ {"atmega165p", "avr5", "avr5", 0x800100},
+ {"atmega165pa", "avr5", "avr5", 0x800100},
+ {"atmega168", "avr5", "avr5", 0x800100},
+ {"atmega168a", "avr5", "avr5", 0x800100},
+ {"atmega168p", "avr5", "avr5", 0x800100},
+ {"atmega168pa", "avr5", "avr5", 0x800100},
+ {"atmega168pb", "avr5", "avr5", 0x800100},
+ {"atmega169", "avr5", "avr5", 0x800100},
+ {"atmega169a", "avr5", "avr5", 0x800100},
+ {"atmega169p", "avr5", "avr5", 0x800100},
+ {"atmega169pa", "avr5", "avr5", 0x800100},
+ {"atmega32", "avr5", "avr5", 0x800060},
+ {"atmega32a", "avr5", "avr5", 0x800060},
+ {"atmega323", "avr5", "avr5", 0x800060},
+ {"atmega324a", "avr5", "avr5", 0x800100},
+ {"atmega324p", "avr5", "avr5", 0x800100},
+ {"atmega324pa", "avr5", "avr5", 0x800100},
+ {"atmega325", "avr5", "avr5", 0x800100},
+ {"atmega325a", "avr5", "avr5", 0x800100},
+ {"atmega325p", "avr5", "avr5", 0x800100},
+ {"atmega325pa", "avr5", "avr5", 0x800100},
+ {"atmega3250", "avr5", "avr5", 0x800100},
+ {"atmega3250a", "avr5", "avr5", 0x800100},
+ {"atmega3250p", "avr5", "avr5", 0x800100},
+ {"atmega3250pa", "avr5", "avr5", 0x800100},
+ {"atmega328", "avr5", "avr5", 0x800100},
+ {"atmega328p", "avr5", "avr5", 0x800100},
+ {"atmega329", "avr5", "avr5", 0x800100},
+ {"atmega329a", "avr5", "avr5", 0x800100},
+ {"atmega329p", "avr5", "avr5", 0x800100},
+ {"atmega329pa", "avr5", "avr5", 0x800100},
+ {"atmega3290", "avr5", "avr5", 0x800100},
+ {"atmega3290a", "avr5", "avr5", 0x800100},
+ {"atmega3290p", "avr5", "avr5", 0x800100},
+ {"atmega3290pa", "avr5", "avr5", 0x800100},
+ {"atmega406", "avr5", "avr5", 0x800100},
+ {"atmega64", "avr5", "avr5", 0x800100},
+ {"atmega64a", "avr5", "avr5", 0x800100},
+ {"atmega640", "avr5", "avr5", 0x800200},
+ {"atmega644", "avr5", "avr5", 0x800100},
+ {"atmega644a", "avr5", "avr5", 0x800100},
+ {"atmega644p", "avr5", "avr5", 0x800100},
+ {"atmega644pa", "avr5", "avr5", 0x800100},
+ {"atmega645", "avr5", "avr5", 0x800100},
+ {"atmega645a", "avr5", "avr5", 0x800100},
+ {"atmega645p", "avr5", "avr5", 0x800100},
+ {"atmega649", "avr5", "avr5", 0x800100},
+ {"atmega649a", "avr5", "avr5", 0x800100},
+ {"atmega649p", "avr5", "avr5", 0x800100},
+ {"atmega6450", "avr5", "avr5", 0x800100},
+ {"atmega6450a", "avr5", "avr5", 0x800100},
+ {"atmega6450p", "avr5", "avr5", 0x800100},
+ {"atmega6490", "avr5", "avr5", 0x800100},
+ {"atmega6490a", "avr5", "avr5", 0x800100},
+ {"atmega6490p", "avr5", "avr5", 0x800100},
+ {"atmega64rfr2", "avr5", "avr5", 0x800200},
+ {"atmega644rfr2", "avr5", "avr5", 0x800200},
+ {"atmega16hva", "avr5", "avr5", 0x800100},
+ {"atmega16hva2", "avr5", "avr5", 0x800100},
+ {"atmega16hvb", "avr5", "avr5", 0x800100},
+ {"atmega16hvbrevb", "avr5", "avr5", 0x800100},
+ {"atmega32hvb", "avr5", "avr5", 0x800100},
+ {"atmega32hvbrevb", "avr5", "avr5", 0x800100},
+ {"atmega64hve", "avr5", "avr5", 0x800100},
+ {"at90can32", "avr5", "avr5", 0x800100},
+ {"at90can64", "avr5", "avr5", 0x800100},
+ {"at90pwm161", "avr5", "avr5", 0x800100},
+ {"at90pwm216", "avr5", "avr5", 0x800100},
+ {"at90pwm316", "avr5", "avr5", 0x800100},
+ {"atmega32c1", "avr5", "avr5", 0x800100},
+ {"atmega64c1", "avr5", "avr5", 0x800100},
+ {"atmega16m1", "avr5", "avr5", 0x800100},
+ {"atmega32m1", "avr5", "avr5", 0x800100},
+ {"atmega64m1", "avr5", "avr5", 0x800100},
+ {"atmega16u4", "avr5", "avr5", 0x800100},
+ {"atmega32u4", "avr5", "avr5", 0x800100},
+ {"atmega32u6", "avr5", "avr5", 0x800100},
+ {"at90usb646", "avr5", "avr5", 0x800100},
+ {"at90usb647", "avr5", "avr5", 0x800100},
+ {"at90scr100", "avr5", "avr5", 0x800100},
+ {"at94k", "avr5", "avr5", 0x800060},
+ {"m3000", "avr5", "avr5", 0x800060},
+ {"atmega128", "avr51", "avr51", 0x800100},
+ {"atmega128a", "avr51", "avr51", 0x800100},
+ {"atmega1280", "avr51", "avr51", 0x800200},
+ {"atmega1281", "avr51", "avr51", 0x800200},
+ {"atmega1284", "avr51", "avr51", 0x800100},
+ {"atmega1284p", "avr51", "avr51", 0x800100},
+ {"atmega128rfa1", "avr51", "avr51", 0x800200},
+ {"atmega128rfr2", "avr51", "avr51", 0x800200},
+ {"atmega1284rfr2", "avr51", "avr51", 0x800200},
+ {"at90can128", "avr51", "avr51", 0x800200},
+ {"at90usb1286", "avr51", "avr51", 0x800200},
+ {"at90usb1287", "avr51", "avr51", 0x800200},
+ {"atmega2560", "avr6", "avr6", 0x800200},
+ {"atmega2561", "avr6", "avr6", 0x800200},
+ {"atmega256rfr2", "avr6", "avr6", 0x800200},
+ {"atmega2564rfr2", "avr6", "avr6", 0x800200},
+ {"attiny4", "avrtiny", "avrtiny", 0x800040},
+ {"attiny5", "avrtiny", "avrtiny", 0x800040},
+ {"attiny9", "avrtiny", "avrtiny", 0x800040},
+ {"attiny10", "avrtiny", "avrtiny", 0x800040},
+ {"attiny20", "avrtiny", "avrtiny", 0x800040},
+ {"attiny40", "avrtiny", "avrtiny", 0x800040},
+ {"atxmega16a4", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega16a4u", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega16c4", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega16d4", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32a4", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32a4u", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32c4", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32d4", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32e5", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega16e5", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega8e5", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega64a3u", "avrxmega4", "avrxmega4", 0x802000},
+ {"atxmega64a4u", "avrxmega4", "avrxmega4", 0x802000},
+ {"atxmega64b1", "avrxmega4", "avrxmega4", 0x802000},
+ {"atxmega64b3", "avrxmega4", "avrxmega4", 0x802000},
+ {"atxmega64c3", "avrxmega4", "avrxmega4", 0x802000},
+ {"atxmega64d3", "avrxmega4", "avrxmega4", 0x802000},
+ {"atxmega64d4", "avrxmega4", "avrxmega4", 0x802000},
+ {"atxmega64a1", "avrxmega5", "avrxmega5", 0x802000},
+ {"atxmega64a1u", "avrxmega5", "avrxmega5", 0x802000},
+ {"atxmega128a3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega128a3u", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega128b1", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega128b3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega128c3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega128d3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega128d4", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega192a3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega192a3u", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega192c3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega192d3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega256a3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega256a3u", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega256a3b", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega256a3bu", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega256c3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega256d3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega384c3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega384d3", "avrxmega6", "avrxmega6", 0x802000},
+ {"atxmega128a1", "avrxmega7", "avrxmega7", 0x802000},
+ {"atxmega128a1u", "avrxmega7", "avrxmega7", 0x802000},
+ {"atxmega128a4u", "avrxmega7", "avrxmega7", 0x802000},
};
std::string GetMCUSubPath(StringRef MCUName) {
@@ -289,11 +290,11 @@
return Optional<StringRef>();
}
-llvm::Optional<unsigned> GetMCUSectionAddressData(StringRef MCU) {
- return llvm::StringSwitch<llvm::Optional<unsigned>>(MCU)
- .Case("atmega328", Optional<unsigned>(0x800100))
- .Case("atmega328p", Optional<unsigned>(0x800100))
- .Default(Optional<unsigned>());
+llvm::Optional<unsigned> GetMCUSectionAddressData(StringRef MCUName) {
+ for (const auto &MCU : MCUInfo)
+ if (MCU.Name == MCUName && MCU.DataAddr > 0)
+ return Optional<unsigned>(MCU.DataAddr);
+ return Optional<unsigned>();
}
const StringRef PossibleAVRLibcLocations[] = {
@@ -334,10 +335,12 @@
// No avr-libc found and so no runtime linked.
D.Diag(diag::warn_drv_avr_libc_not_found);
} else { // We have enough information to link stdlibs
- std::string GCCRoot = std::string(GCCInstallation.getInstallPath());
+ std::string GCCRoot(GCCInstallation.getInstallPath());
+ std::string GCCParentPath(GCCInstallation.getParentLibPath());
std::string LibcRoot = AVRLibcRoot.getValue();
std::string SubPath = GetMCUSubPath(CPU);
+ getProgramPaths().push_back(GCCParentPath + "/../bin");
getFilePaths().push_back(LibcRoot + std::string("/lib/") + SubPath);
getFilePaths().push_back(GCCRoot + std::string("/") + SubPath);
@@ -350,6 +353,23 @@
}
}
+void AVRToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+ DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Omit if there is no avr-libc installed.
+ Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
+ if (!AVRLibcRoot.hasValue())
+ return;
+
+ // Add 'avr-libc/include' to clang system include paths if applicable.
+ std::string AVRInc = AVRLibcRoot.getValue() + "/include";
+ if (llvm::sys::fs::is_directory(AVRInc))
+ addSystemInclude(DriverArgs, CC1Args, AVRInc);
+}
+
Tool *AVRToolChain::buildLinker() const {
return new tools::AVR::Linker(getTriple(), *this, LinkStdlib);
}
@@ -419,9 +439,10 @@
llvm::Optional<std::string> AVRToolChain::findAVRLibcInstallation() const {
for (StringRef PossiblePath : PossibleAVRLibcLocations) {
+ std::string Path = getDriver().SysRoot + PossiblePath.str();
// Return the first avr-libc installation that exists.
- if (llvm::sys::fs::is_directory(PossiblePath))
- return Optional<std::string>(std::string(PossiblePath));
+ if (llvm::sys::fs::is_directory(Path))
+ return Optional<std::string>(Path);
}
return llvm::None;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/AVR.h b/src/llvm-project/clang/lib/Driver/ToolChains/AVR.h
index a3198b2..f612aa6 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/AVR.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/AVR.h
@@ -10,7 +10,7 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AVR_H
#include "Gnu.h"
-#include "InputInfo.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Tool.h"
@@ -22,6 +22,9 @@
public:
AVRToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
protected:
Tool *buildLinker() const override;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp
index e5e33fe..be1476a 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp
@@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===//
#include "Ananas.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Option/ArgList.h"
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index a5e632f..ed8c7e9 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -41,19 +41,19 @@
if (CPU == "native")
return std::string(llvm::sys::getHostCPUName());
- // arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
- if (Triple.isArm64e())
- return "apple-a12";
-
if (CPU.size())
return CPU;
if (Triple.isTargetMachineMac() &&
Triple.getArch() == llvm::Triple::aarch64) {
- // Apple Silicon macs default to A12 CPUs.
- return "apple-a12";
+ // Apple Silicon macs default to M1 CPUs.
+ return "apple-m1";
}
+ // arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
+ if (Triple.isArm64e())
+ return "apple-a12";
+
// Make sure we pick the appropriate Apple CPU if -arch is used or when
// targetting a Darwin OS.
if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
@@ -185,12 +185,25 @@
void aarch64::getAArch64TargetFeatures(const Driver &D,
const llvm::Triple &Triple,
const ArgList &Args,
- std::vector<StringRef> &Features) {
+ std::vector<StringRef> &Features,
+ bool ForAS) {
Arg *A;
bool success = true;
// Enable NEON by default.
Features.push_back("+neon");
- if ((A = Args.getLastArg(options::OPT_march_EQ)))
+ llvm::StringRef WaMArch = "";
+ if (ForAS)
+ for (const auto *A :
+ Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))
+ for (StringRef Value : A->getValues())
+ if (Value.startswith("-march="))
+ WaMArch = Value.substr(7);
+ // Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or
+ // "-Xassembler -march" is detected. Otherwise it may return false
+ // and causes Clang to error out.
+ if (WaMArch.size())
+ success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Features);
+ else if ((A = Args.getLastArg(options::OPT_march_EQ)))
success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
@@ -235,11 +248,17 @@
StringRef Scope = A->getValue();
bool EnableRetBr = false;
bool EnableBlr = false;
- if (Scope != "none" && Scope != "all") {
+ bool DisableComdat = false;
+ if (Scope != "none") {
SmallVector<StringRef, 4> Opts;
Scope.split(Opts, ",");
for (auto Opt : Opts) {
Opt = Opt.trim();
+ if (Opt == "all") {
+ EnableBlr = true;
+ EnableRetBr = true;
+ continue;
+ }
if (Opt == "retbr") {
EnableRetBr = true;
continue;
@@ -248,19 +267,27 @@
EnableBlr = true;
continue;
}
+ if (Opt == "comdat") {
+ DisableComdat = false;
+ continue;
+ }
+ if (Opt == "nocomdat") {
+ DisableComdat = true;
+ continue;
+ }
D.Diag(diag::err_invalid_sls_hardening)
<< Scope << A->getAsString(Args);
break;
}
- } else if (Scope == "all") {
- EnableRetBr = true;
- EnableBlr = true;
}
if (EnableRetBr)
Features.push_back("+harden-sls-retbr");
if (EnableBlr)
Features.push_back("+harden-sls-blr");
+ if (DisableComdat) {
+ Features.push_back("+harden-sls-nocomdat");
+ }
}
// En/disable crc
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.h b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.h
index 713af87..d47c402 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.h
@@ -22,7 +22,8 @@
void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
- std::vector<llvm::StringRef> &Features);
+ std::vector<llvm::StringRef> &Features,
+ bool ForAS);
std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple, llvm::opt::Arg *&A);
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index ef590db..4ab547f 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -50,11 +50,14 @@
for (const Arg *A :
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
- StringRef Value = A->getValue();
- if (Value.startswith("-mcpu="))
- CPU = Value.substr(6);
- if (Value.startswith("-march="))
- Arch = Value.substr(7);
+ // Use getValues because -Wa can have multiple arguments
+ // e.g. -Wa,-mcpu=foo,-mcpu=bar
+ for (StringRef Value : A->getValues()) {
+ if (Value.startswith("-mcpu="))
+ CPU = Value.substr(6);
+ if (Value.startswith("-march="))
+ Arch = Value.substr(7);
+ }
}
}
@@ -163,6 +166,132 @@
return ReadTPMode::Soft;
}
+void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,
+ types::ID InputType, llvm::Triple &Triple) {
+ StringRef MCPU, MArch;
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ MCPU = A->getValue();
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ MArch = A->getValue();
+
+ std::string CPU = Triple.isOSBinFormatMachO()
+ ? tools::arm::getARMCPUForMArch(MArch, Triple).str()
+ : tools::arm::getARMTargetCPU(MCPU, MArch, Triple);
+ StringRef Suffix = tools::arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
+
+ bool IsBigEndian = Triple.getArch() == llvm::Triple::armeb ||
+ Triple.getArch() == llvm::Triple::thumbeb;
+ // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
+ // '-mbig-endian'/'-EB'.
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian)) {
+ IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
+ }
+ std::string ArchName = IsBigEndian ? "armeb" : "arm";
+
+ // FIXME: Thumb should just be another -target-feaure, not in the triple.
+ bool IsMProfile =
+ llvm::ARM::parseArchProfile(Suffix) == llvm::ARM::ProfileKind::M;
+ bool ThumbDefault = IsMProfile ||
+ // Thumb2 is the default for V7 on Darwin.
+ (llvm::ARM::parseArchVersion(Suffix) == 7 &&
+ Triple.isOSBinFormatMachO()) ||
+ // FIXME: this is invalid for WindowsCE
+ Triple.isOSWindows();
+
+ // Check if ARM ISA was explicitly selected (using -mno-thumb or -marm) for
+ // M-Class CPUs/architecture variants, which is not supported.
+ bool ARMModeRequested =
+ !Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);
+ if (IsMProfile && ARMModeRequested) {
+ if (MCPU.size())
+ D.Diag(diag::err_cpu_unsupported_isa) << CPU << "ARM";
+ else
+ D.Diag(diag::err_arch_unsupported_isa)
+ << tools::arm::getARMArch(MArch, Triple) << "ARM";
+ }
+
+ // Check to see if an explicit choice to use thumb has been made via
+ // -mthumb. For assembler files we must check for -mthumb in the options
+ // passed to the assembler via -Wa or -Xassembler.
+ bool IsThumb = false;
+ if (InputType != types::TY_PP_Asm)
+ IsThumb =
+ Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault);
+ else {
+ // Ideally we would check for these flags in
+ // CollectArgsForIntegratedAssembler but we can't change the ArchName at
+ // that point.
+ llvm::StringRef WaMArch, WaMCPU;
+ for (const auto *A :
+ Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
+ for (StringRef Value : A->getValues()) {
+ // There is no assembler equivalent of -mno-thumb, -marm, or -mno-arm.
+ if (Value == "-mthumb")
+ IsThumb = true;
+ else if (Value.startswith("-march="))
+ WaMArch = Value.substr(7);
+ else if (Value.startswith("-mcpu="))
+ WaMCPU = Value.substr(6);
+ }
+ }
+
+ if (WaMCPU.size() || WaMArch.size()) {
+ // The way this works means that we prefer -Wa,-mcpu's architecture
+ // over -Wa,-march. Which matches the compiler behaviour.
+ Suffix = tools::arm::getLLVMArchSuffixForARM(WaMCPU, WaMArch, Triple);
+ }
+ }
+
+ // Assembly files should start in ARM mode, unless arch is M-profile, or
+ // -mthumb has been passed explicitly to the assembler. Windows is always
+ // thumb.
+ if (IsThumb || IsMProfile || Triple.isOSWindows()) {
+ if (IsBigEndian)
+ ArchName = "thumbeb";
+ else
+ ArchName = "thumb";
+ }
+ Triple.setArchName(ArchName + Suffix.str());
+}
+
+void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,
+ llvm::Triple &Triple) {
+ bool isHardFloat =
+ (arm::getARMFloatABI(D, Triple, Args) == arm::FloatABI::Hard);
+
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::GNUEABI:
+ case llvm::Triple::GNUEABIHF:
+ Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHF
+ : llvm::Triple::GNUEABI);
+ break;
+ case llvm::Triple::EABI:
+ case llvm::Triple::EABIHF:
+ Triple.setEnvironment(isHardFloat ? llvm::Triple::EABIHF
+ : llvm::Triple::EABI);
+ break;
+ case llvm::Triple::MuslEABI:
+ case llvm::Triple::MuslEABIHF:
+ Triple.setEnvironment(isHardFloat ? llvm::Triple::MuslEABIHF
+ : llvm::Triple::MuslEABI);
+ break;
+ default: {
+ arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple);
+ if (DefaultABI != arm::FloatABI::Invalid &&
+ isHardFloat != (DefaultABI == arm::FloatABI::Hard)) {
+ Arg *ABIArg =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ);
+ assert(ABIArg && "Non-default float abi expected to be from arg");
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << ABIArg->getAsString(Args) << Triple.getTriple();
+ }
+ break;
+ }
+ }
+}
+
arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args);
}
@@ -290,8 +419,8 @@
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args);
- const Arg *WaCPU = nullptr, *WaFPU = nullptr;
- const Arg *WaHDiv = nullptr, *WaArch = nullptr;
+ llvm::Optional<std::pair<const Arg *, StringRef>> WaCPU, WaFPU, WaHDiv,
+ WaArch;
// This vector will accumulate features from the architecture
// extension suffixes on -mcpu and -march (e.g. the 'bar' in
@@ -325,15 +454,18 @@
// to the assembler correctly.
for (const Arg *A :
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
- StringRef Value = A->getValue();
- if (Value.startswith("-mfpu=")) {
- WaFPU = A;
- } else if (Value.startswith("-mcpu=")) {
- WaCPU = A;
- } else if (Value.startswith("-mhwdiv=")) {
- WaHDiv = A;
- } else if (Value.startswith("-march=")) {
- WaArch = A;
+ // We use getValues here because you can have many options per -Wa
+ // We will keep the last one we find for each of these
+ for (StringRef Value : A->getValues()) {
+ if (Value.startswith("-mfpu=")) {
+ WaFPU = std::make_pair(A, Value.substr(6));
+ } else if (Value.startswith("-mcpu=")) {
+ WaCPU = std::make_pair(A, Value.substr(6));
+ } else if (Value.startswith("-mhwdiv=")) {
+ WaHDiv = std::make_pair(A, Value.substr(8));
+ } else if (Value.startswith("-march=")) {
+ WaArch = std::make_pair(A, Value.substr(7));
+ }
}
}
}
@@ -353,8 +485,8 @@
if (CPUArg)
D.Diag(clang::diag::warn_drv_unused_argument)
<< CPUArg->getAsString(Args);
- CPUName = StringRef(WaCPU->getValue()).substr(6);
- CPUArg = WaCPU;
+ CPUName = WaCPU->second;
+ CPUArg = WaCPU->first;
} else if (CPUArg)
CPUName = CPUArg->getValue();
@@ -363,11 +495,12 @@
if (ArchArg)
D.Diag(clang::diag::warn_drv_unused_argument)
<< ArchArg->getAsString(Args);
- ArchName = StringRef(WaArch->getValue()).substr(7);
- checkARMArchName(D, WaArch, Args, ArchName, CPUName, ExtensionFeatures,
- Triple, ArchArgFPUID);
- // FIXME: Set Arch.
- D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args);
+ ArchName = WaArch->second;
+ // This will set any features after the base architecture.
+ checkARMArchName(D, WaArch->first, Args, ArchName, CPUName,
+ ExtensionFeatures, Triple, ArchArgFPUID);
+ // The base architecture was handled in ToolChain::ComputeLLVMTriple because
+ // triple is read only by this point.
} else if (ArchArg) {
ArchName = ArchArg->getValue();
checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures,
@@ -399,8 +532,7 @@
if (FPUArg)
D.Diag(clang::diag::warn_drv_unused_argument)
<< FPUArg->getAsString(Args);
- (void)getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6),
- Features);
+ (void)getARMFPUFeatures(D, WaFPU->first, Args, WaFPU->second, Features);
} else if (FPUArg) {
FPUID = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
} else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) {
@@ -409,6 +541,14 @@
if (!llvm::ARM::getFPUFeatures(FPUID, Features))
D.Diag(clang::diag::err_drv_clang_unsupported)
<< std::string("-mfpu=") + AndroidFPU;
+ } else {
+ if (!ForAS) {
+ std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
+ llvm::ARM::ArchKind ArchKind =
+ arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
+ FPUID = llvm::ARM::getDefaultFPU(CPU, ArchKind);
+ (void)llvm::ARM::getFPUFeatures(FPUID, Features);
+ }
}
// Now we've finished accumulating features from arch, cpu and fpu,
@@ -423,8 +563,7 @@
if (HDivArg)
D.Diag(clang::diag::warn_drv_unused_argument)
<< HDivArg->getAsString(Args);
- getARMHWDivFeatures(D, WaHDiv, Args,
- StringRef(WaHDiv->getValue()).substr(8), Features);
+ getARMHWDivFeatures(D, WaHDiv->first, Args, WaHDiv->second, Features);
} else if (HDivArg)
getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
@@ -487,34 +626,73 @@
Features.push_back("-crc");
}
- // For Arch >= ARMv8.0 && A profile: crypto = sha2 + aes
+ // For Arch >= ARMv8.0 && A or R profile: crypto = sha2 + aes
+ // Rather than replace within the feature vector, determine whether each
+ // algorithm is enabled and append this to the end of the vector.
+ // The algorithms can be controlled by their specific feature or the crypto
+ // feature, so their status can be determined by the last occurance of
+ // either in the vector. This allows one to supercede the other.
+ // e.g. +crypto+noaes in -march/-mcpu should enable sha2, but not aes
// FIXME: this needs reimplementation after the TargetParser rewrite
- auto CryptoIt = llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
- return F.contains("crypto");
- });
- if (CryptoIt != Features.rend()) {
- if (CryptoIt->take_front() == "+") {
- StringRef ArchSuffix = arm::getLLVMArchSuffixForARM(
- arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple);
- if (llvm::ARM::parseArchVersion(ArchSuffix) >= 8 &&
- llvm::ARM::parseArchProfile(ArchSuffix) ==
- llvm::ARM::ProfileKind::A) {
- if (ArchName.find_lower("+nosha2") == StringRef::npos &&
- CPUName.find_lower("+nosha2") == StringRef::npos)
- Features.push_back("+sha2");
- if (ArchName.find_lower("+noaes") == StringRef::npos &&
- CPUName.find_lower("+noaes") == StringRef::npos)
- Features.push_back("+aes");
- } else {
+ bool HasSHA2 = false;
+ bool HasAES = false;
+ const auto ItCrypto =
+ llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
+ return F.contains("crypto");
+ });
+ const auto ItSHA2 =
+ llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
+ return F.contains("crypto") || F.contains("sha2");
+ });
+ const auto ItAES =
+ llvm::find_if(llvm::reverse(Features), [](const StringRef F) {
+ return F.contains("crypto") || F.contains("aes");
+ });
+ const bool FoundSHA2 = ItSHA2 != Features.rend();
+ const bool FoundAES = ItAES != Features.rend();
+ if (FoundSHA2)
+ HasSHA2 = ItSHA2->take_front() == "+";
+ if (FoundAES)
+ HasAES = ItAES->take_front() == "+";
+ if (ItCrypto != Features.rend()) {
+ if (HasSHA2 && HasAES)
+ Features.push_back("+crypto");
+ else
+ Features.push_back("-crypto");
+ if (HasSHA2)
+ Features.push_back("+sha2");
+ else
+ Features.push_back("-sha2");
+ if (HasAES)
+ Features.push_back("+aes");
+ else
+ Features.push_back("-aes");
+ }
+
+ if (HasSHA2 || HasAES) {
+ StringRef ArchSuffix = arm::getLLVMArchSuffixForARM(
+ arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple);
+ llvm::ARM::ProfileKind ArchProfile =
+ llvm::ARM::parseArchProfile(ArchSuffix);
+ if (!((llvm::ARM::parseArchVersion(ArchSuffix) >= 8) &&
+ (ArchProfile == llvm::ARM::ProfileKind::A ||
+ ArchProfile == llvm::ARM::ProfileKind::R))) {
+ if (HasSHA2)
D.Diag(clang::diag::warn_target_unsupported_extension)
- << "crypto"
+ << "sha2"
<< llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));
- // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such as the GNU assembler
- // will permit the use of crypto instructions as the fpu will override the architecture.
- // We keep the crypto feature in this case to preserve compatibility.
- // In all other cases we remove the crypto feature.
- if (!Args.hasArg(options::OPT_fno_integrated_as))
- Features.push_back("-crypto");
+ if (HasAES)
+ D.Diag(clang::diag::warn_target_unsupported_extension)
+ << "aes"
+ << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix));
+ // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such
+ // as the GNU assembler will permit the use of crypto instructions as the
+ // fpu will override the architecture. We keep the crypto feature in this
+ // case to preserve compatibility. In all other cases we remove the crypto
+ // feature.
+ if (!Args.hasArg(options::OPT_fno_integrated_as)) {
+ Features.push_back("-sha2");
+ Features.push_back("-aes");
}
}
}
@@ -618,11 +796,17 @@
StringRef Scope = A->getValue();
bool EnableRetBr = false;
bool EnableBlr = false;
- if (Scope != "none" && Scope != "all") {
+ bool DisableComdat = false;
+ if (Scope != "none") {
SmallVector<StringRef, 4> Opts;
Scope.split(Opts, ",");
for (auto Opt : Opts) {
Opt = Opt.trim();
+ if (Opt == "all") {
+ EnableBlr = true;
+ EnableRetBr = true;
+ continue;
+ }
if (Opt == "retbr") {
EnableRetBr = true;
continue;
@@ -631,13 +815,18 @@
EnableBlr = true;
continue;
}
+ if (Opt == "comdat") {
+ DisableComdat = false;
+ continue;
+ }
+ if (Opt == "nocomdat") {
+ DisableComdat = true;
+ continue;
+ }
D.Diag(diag::err_invalid_sls_hardening)
<< Scope << A->getAsString(Args);
break;
}
- } else if (Scope == "all") {
- EnableRetBr = true;
- EnableBlr = true;
}
if (EnableRetBr || EnableBlr)
@@ -649,6 +838,9 @@
Features.push_back("+harden-sls-retbr");
if (EnableBlr)
Features.push_back("+harden-sls-blr");
+ if (DisableComdat) {
+ Features.push_back("+harden-sls-nocomdat");
+ }
}
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h
index 02d91cd..8e7c10e 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -51,7 +51,11 @@
FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args);
FloatABI getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
+void setFloatABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
+ llvm::Triple &triple);
ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args);
+void setArchNameInTriple(const Driver &D, const llvm::opt::ArgList &Args,
+ types::ID InputType, llvm::Triple &Triple);
bool useAAPCSForMachO(const llvm::Triple &T);
void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args,
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.cpp
new file mode 100644
index 0000000..119e24c
--- /dev/null
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.cpp
@@ -0,0 +1,125 @@
+//===--- M68k.cpp - M68k Helpers for Tools -------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "M68k.h"
+#include "ToolChains/CommonArgs.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Regex.h"
+#include <sstream>
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+/// getM68kTargetCPU - Get the (LLVM) name of the 68000 cpu we are targeting.
+std::string m68k::getM68kTargetCPU(const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+ // The canonical CPU name is captalize. However, we allow
+ // starting with lower case or numbers only
+ StringRef CPUName = A->getValue();
+
+ if (CPUName == "native") {
+ std::string CPU = std::string(llvm::sys::getHostCPUName());
+ if (!CPU.empty() && CPU != "generic")
+ return CPU;
+ }
+
+ if (CPUName == "common")
+ return "generic";
+
+ return llvm::StringSwitch<std::string>(CPUName)
+ .Cases("m68000", "68000", "M68000")
+ .Cases("m68010", "68010", "M68010")
+ .Cases("m68020", "68020", "M68020")
+ .Cases("m68030", "68030", "M68030")
+ .Cases("m68040", "68040", "M68040")
+ .Cases("m68060", "68060", "M68060")
+ .Default(CPUName.str());
+ }
+ // FIXME: Throw error when multiple sub-architecture flag exist
+ if (Args.hasArg(clang::driver::options::OPT_m68000))
+ return "M68000";
+ if (Args.hasArg(clang::driver::options::OPT_m68010))
+ return "M68010";
+ if (Args.hasArg(clang::driver::options::OPT_m68020))
+ return "M68020";
+ if (Args.hasArg(clang::driver::options::OPT_m68030))
+ return "M68030";
+ if (Args.hasArg(clang::driver::options::OPT_m68040))
+ return "M68040";
+ if (Args.hasArg(clang::driver::options::OPT_m68060))
+ return "M68060";
+
+ return "";
+}
+
+void m68k::getM68kTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<StringRef> &Features) {
+
+ m68k::FloatABI FloatABI = m68k::getM68kFloatABI(D, Args);
+ if (FloatABI == m68k::FloatABI::Soft)
+ Features.push_back("-hard-float");
+
+ // Handle '-ffixed-<register>' flags
+ if (Args.hasArg(options::OPT_ffixed_a0))
+ Features.push_back("+reserve-a0");
+ if (Args.hasArg(options::OPT_ffixed_a1))
+ Features.push_back("+reserve-a1");
+ if (Args.hasArg(options::OPT_ffixed_a2))
+ Features.push_back("+reserve-a2");
+ if (Args.hasArg(options::OPT_ffixed_a3))
+ Features.push_back("+reserve-a3");
+ if (Args.hasArg(options::OPT_ffixed_a4))
+ Features.push_back("+reserve-a4");
+ if (Args.hasArg(options::OPT_ffixed_a5))
+ Features.push_back("+reserve-a5");
+ if (Args.hasArg(options::OPT_ffixed_a6))
+ Features.push_back("+reserve-a6");
+ if (Args.hasArg(options::OPT_ffixed_d0))
+ Features.push_back("+reserve-d0");
+ if (Args.hasArg(options::OPT_ffixed_d1))
+ Features.push_back("+reserve-d1");
+ if (Args.hasArg(options::OPT_ffixed_d2))
+ Features.push_back("+reserve-d2");
+ if (Args.hasArg(options::OPT_ffixed_d3))
+ Features.push_back("+reserve-d3");
+ if (Args.hasArg(options::OPT_ffixed_d4))
+ Features.push_back("+reserve-d4");
+ if (Args.hasArg(options::OPT_ffixed_d5))
+ Features.push_back("+reserve-d5");
+ if (Args.hasArg(options::OPT_ffixed_d6))
+ Features.push_back("+reserve-d6");
+ if (Args.hasArg(options::OPT_ffixed_d7))
+ Features.push_back("+reserve-d7");
+}
+
+m68k::FloatABI m68k::getM68kFloatABI(const Driver &D, const ArgList &Args) {
+ m68k::FloatABI ABI = m68k::FloatABI::Invalid;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
+
+ if (A->getOption().matches(options::OPT_msoft_float))
+ ABI = m68k::FloatABI::Soft;
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ ABI = m68k::FloatABI::Hard;
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (ABI == m68k::FloatABI::Invalid)
+ ABI = m68k::FloatABI::Hard;
+
+ return ABI;
+}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.h b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.h
new file mode 100644
index 0000000..41d53ef
--- /dev/null
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.h
@@ -0,0 +1,42 @@
+//===--- M68k.h - M68k-specific Tool Helpers -----------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_M680X0_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_M680X0_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace m68k {
+
+enum class FloatABI {
+ Invalid,
+ Soft,
+ Hard,
+};
+
+FloatABI getM68kFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+
+std::string getM68kTargetCPU(const llvm::opt::ArgList &Args);
+
+void getM68kTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features);
+
+} // end namespace m68k
+} // end namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_M680X0_H
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index c7f2a3e..ade93d6 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -258,10 +258,13 @@
<< MArch << Error << Ext;
return;
}
- if (Ext == "zvamo" || Ext == "zvlsseg") {
+ if (Ext == "zvlsseg") {
Features.push_back("+experimental-v");
- Features.push_back("+experimental-zvamo");
Features.push_back("+experimental-zvlsseg");
+ } else if (Ext == "zvamo") {
+ Features.push_back("+experimental-v");
+ Features.push_back("+experimental-zvlsseg");
+ Features.push_back("+experimental-zvamo");
} else if (isExperimentalExtension(Ext))
Features.push_back(Args.MakeArgString("+experimental-" + Ext));
else
@@ -429,7 +432,6 @@
break;
case 'v':
Features.push_back("+experimental-v");
- Features.push_back("+experimental-zvamo");
Features.push_back("+experimental-zvlsseg");
break;
}
@@ -610,17 +612,19 @@
// rv64* -> lp64
StringRef MArch = getRISCVArch(Args, Triple);
- if (MArch.startswith_lower("rv32")) {
+ if (MArch.startswith_insensitive("rv32")) {
// FIXME: parse `March` to find `D` extension properly
- if (MArch.substr(4).contains_lower("d") || MArch.startswith_lower("rv32g"))
+ if (MArch.substr(4).contains_insensitive("d") ||
+ MArch.startswith_insensitive("rv32g"))
return "ilp32d";
- else if (MArch.startswith_lower("rv32e"))
+ else if (MArch.startswith_insensitive("rv32e"))
return "ilp32e";
else
return "ilp32";
- } else if (MArch.startswith_lower("rv64")) {
+ } else if (MArch.startswith_insensitive("rv64")) {
// FIXME: parse `March` to find `D` extension properly
- if (MArch.substr(4).contains_lower("d") || MArch.startswith_lower("rv64g"))
+ if (MArch.substr(4).contains_insensitive("d") ||
+ MArch.startswith_insensitive("rv64g"))
return "lp64d";
else
return "lp64";
@@ -696,11 +700,11 @@
if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
StringRef MABI = A->getValue();
- if (MABI.equals_lower("ilp32e"))
+ if (MABI.equals_insensitive("ilp32e"))
return "rv32e";
- else if (MABI.startswith_lower("ilp32"))
+ else if (MABI.startswith_insensitive("ilp32"))
return "rv32imafdc";
- else if (MABI.startswith_lower("lp64"))
+ else if (MABI.startswith_insensitive("lp64"))
return "rv64imafdc";
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp
index 94a53f9..12749c7 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -213,5 +213,24 @@
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
- handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
+ for (const Arg *A : Args.filtered(options::OPT_m_x86_Features_Group,
+ options::OPT_mgeneral_regs_only)) {
+ StringRef Name = A->getOption().getName();
+ A->claim();
+
+ // Skip over "-m".
+ assert(Name.startswith("m") && "Invalid feature name.");
+ Name = Name.substr(1);
+
+ // Replace -mgeneral-regs-only with -x87, -mmx, -sse
+ if (A->getOption().getID() == options::OPT_mgeneral_regs_only) {
+ Features.insert(Features.end(), {"-x87", "-mmx", "-sse"});
+ continue;
+ }
+
+ bool IsNegative = Name.startswith("no-");
+ if (IsNegative)
+ Name = Name.substr(3);
+ Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+ }
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
index 7619dd3..ce73e39 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -9,8 +9,8 @@
#include "BareMetal.h"
#include "CommonArgs.h"
-#include "InputInfo.h"
#include "Gnu.h"
+#include "clang/Driver/InputInfo.h"
#include "Arch/RISCV.h"
#include "clang/Driver/Compilation.h"
@@ -160,8 +160,9 @@
std::string BareMetal::getCompilerRTPath() const { return getRuntimesDir(); }
-std::string BareMetal::getCompilerRTBasename(const llvm::opt::ArgList &,
- StringRef, FileType, bool) const {
+std::string BareMetal::buildCompilerRTBasename(const llvm::opt::ArgList &,
+ StringRef, FileType,
+ bool) const {
return ("libclang_rt.builtins-" + getTriple().getArchName() + ".a").str();
}
@@ -298,13 +299,14 @@
CmdArgs.push_back("-Bstatic");
- CmdArgs.push_back(Args.MakeArgString("-L" + TC.getRuntimesDir()));
-
- TC.AddFilePathLibArgs(Args, CmdArgs);
Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_e, options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_r});
+ TC.AddFilePathLibArgs(Args, CmdArgs);
+
+ CmdArgs.push_back(Args.MakeArgString("-L" + TC.getRuntimesDir()));
+
if (TC.ShouldLinkCXXStdlib(Args))
TC.AddCXXStdlibLibArgs(Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h b/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h
index a6d4922..d68c43c 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h
@@ -33,6 +33,11 @@
protected:
Tool *buildLinker() const override;
+ std::string buildCompilerRTBasename(const llvm::opt::ArgList &Args,
+ StringRef Component,
+ FileType Type = ToolChain::FT_Static,
+ bool AddArch = true) const override;
+
public:
bool useIntegratedAs() const override { return true; }
bool isCrossCompiling() const override { return true; }
@@ -44,10 +49,6 @@
StringRef getOSLibName() const override { return "baremetal"; }
std::string getCompilerRTPath() const override;
- std::string getCompilerRTBasename(const llvm::opt::ArgList &Args,
- StringRef Component,
- FileType Type = ToolChain::FT_Static,
- bool AddArch = true) const override;
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
index 1976b48..1870bd8 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
@@ -10,6 +10,7 @@
#include "AMDGPU.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
+#include "Arch/M68k.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
#include "Arch/RISCV.h"
@@ -19,7 +20,6 @@
#include "Arch/X86.h"
#include "CommonArgs.h"
#include "Hexagon.h"
-#include "InputInfo.h"
#include "MSP430.h"
#include "PS4CPU.h"
#include "clang/Basic/CharInfo.h"
@@ -29,6 +29,7 @@
#include "clang/Basic/Version.h"
#include "clang/Driver/Distro.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/XRayArgs.h"
@@ -343,7 +344,7 @@
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
- aarch64::getAArch64TargetFeatures(D, Triple, Args, Features);
+ aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
@@ -365,11 +366,15 @@
case llvm::Triple::amdgcn:
amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features);
break;
+ case llvm::Triple::m68k:
+ m68k::getM68kTargetFeatures(D, Triple, Args, Features);
+ break;
case llvm::Triple::msp430:
msp430::getMSP430TargetFeatures(D, Args, Features);
break;
case llvm::Triple::ve:
ve::getVETargetFeatures(D, Args, Features);
+ break;
}
for (auto Feature : unifyTargetFeatures(Features)) {
@@ -399,7 +404,7 @@
/// master flag, -fexceptions and also language specific flags to enable/disable
/// C++ and Objective-C exceptions. This makes it possible to for example
/// disable C++ exceptions but enable Objective-C exceptions.
-static void addExceptionArgs(const ArgList &Args, types::ID InputType,
+static bool addExceptionArgs(const ArgList &Args, types::ID InputType,
const ToolChain &TC, bool KernelOrKext,
const ObjCRuntime &objcRuntime,
ArgStringList &CmdArgs) {
@@ -414,13 +419,22 @@
Args.ClaimAllArgs(options::OPT_fno_objc_exceptions);
Args.ClaimAllArgs(options::OPT_fcxx_exceptions);
Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions);
- return;
+ Args.ClaimAllArgs(options::OPT_fasync_exceptions);
+ Args.ClaimAllArgs(options::OPT_fno_async_exceptions);
+ return false;
}
// See if the user explicitly enabled exceptions.
bool EH = Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
false);
+ bool EHa = Args.hasFlag(options::OPT_fasync_exceptions,
+ options::OPT_fno_async_exceptions, false);
+ if (EHa) {
+ CmdArgs.push_back("-fasync-exceptions");
+ EH = true;
+ }
+
// Obj-C exceptions are enabled by default, regardless of -fexceptions. This
// is not necessarily sensible, but follows GCC.
if (types::isObjC(InputType) &&
@@ -457,6 +471,7 @@
if (EH)
CmdArgs.push_back("-fexceptions");
+ return EH;
}
static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC,
@@ -475,14 +490,6 @@
Default);
}
-static bool ShouldDisableDwarfDirectory(const ArgList &Args,
- const ToolChain &TC) {
- bool UseDwarfDirectory =
- Args.hasFlag(options::OPT_fdwarf_directory_asm,
- options::OPT_fno_dwarf_directory_asm, TC.useIntegratedAs());
- return !UseDwarfDirectory;
-}
-
// Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases
// to the corresponding DebugInfoKind.
static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
@@ -496,7 +503,7 @@
return codegenoptions::DebugLineTablesOnly;
if (A.getOption().matches(options::OPT_gline_directives_only))
return codegenoptions::DebugDirectivesOnly;
- return codegenoptions::LimitedDebugInfo;
+ return codegenoptions::DebugInfoConstructor;
}
static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
@@ -617,13 +624,16 @@
/// Add a CC1 option to specify the debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs,
const llvm::vfs::FileSystem &VFS) {
- if (Arg *A = Args.getLastArg(options::OPT_fdebug_compilation_dir)) {
- CmdArgs.push_back("-fdebug-compilation-dir");
- CmdArgs.push_back(A->getValue());
+ if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
+ options::OPT_fdebug_compilation_dir_EQ)) {
+ if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ))
+ CmdArgs.push_back(Args.MakeArgString(Twine("-fdebug-compilation-dir=") +
+ A->getValue()));
+ else
+ A->render(Args, CmdArgs);
} else if (llvm::ErrorOr<std::string> CWD =
VFS.getCurrentWorkingDirectory()) {
- CmdArgs.push_back("-fdebug-compilation-dir");
- CmdArgs.push_back(Args.MakeArgString(*CWD));
+ CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + *CWD));
}
}
@@ -657,16 +667,16 @@
}
/// Add a CC1 and CC1AS option to specify the coverage file path prefix map.
-static void addProfilePrefixMapArg(const Driver &D, const ArgList &Args,
+static void addCoveragePrefixMapArg(const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs) {
for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
- options::OPT_fprofile_prefix_map_EQ)) {
+ options::OPT_fcoverage_prefix_map_EQ)) {
StringRef Map = A->getValue();
if (Map.find('=') == StringRef::npos)
D.Diag(diag::err_drv_invalid_argument_to_option)
<< Map << A->getOption().getName();
else
- CmdArgs.push_back(Args.MakeArgString("-fprofile-prefix-map=" + Map));
+ CmdArgs.push_back(Args.MakeArgString("-fcoverage-prefix-map=" + Map));
A->claim();
}
}
@@ -783,6 +793,20 @@
PGOGenerateArg = nullptr;
}
+ if (TC.getTriple().isOSAIX()) {
+ if (PGOGenerateArg)
+ if (!D.isUsingLTO(false /*IsDeviceOffloadAction */) ||
+ D.getLTOMode() != LTOK_Full)
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << PGOGenerateArg->getSpelling() << "-flto";
+ if (ProfileGenerateArg)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << ProfileGenerateArg->getSpelling() << TC.getTriple().str();
+ if (Arg *ProfileSampleUseArg = getLastProfileSampleUseArg(Args))
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << ProfileSampleUseArg->getSpelling() << TC.getTriple().str();
+ }
+
if (ProfileGenerateArg) {
if (ProfileGenerateArg->getOption().matches(
options::OPT_fprofile_instr_generate_EQ))
@@ -860,6 +884,18 @@
CmdArgs.push_back("-fcoverage-mapping");
}
+ if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
+ options::OPT_fcoverage_compilation_dir_EQ)) {
+ if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ))
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-fcoverage-compilation-dir=") + A->getValue()));
+ else
+ A->render(Args, CmdArgs);
+ } else if (llvm::ErrorOr<std::string> CWD =
+ D.getVFS().getCurrentWorkingDirectory()) {
+ CmdArgs.push_back(Args.MakeArgString("-fcoverage-compilation-dir=" + *CWD));
+ }
+
if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) {
auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ);
if (!Args.hasArg(options::OPT_coverage))
@@ -983,6 +1019,14 @@
.Default(0);
}
+// Find a DWARF format version option.
+// This function is a complementary for DwarfVersionNum().
+static const Arg *getDwarfNArg(const ArgList &Args) {
+ return Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
+ options::OPT_gdwarf_4, options::OPT_gdwarf_5,
+ options::OPT_gdwarf);
+}
+
static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind DebugInfoKind,
unsigned DwarfVersion,
@@ -1022,6 +1066,9 @@
case llvm::DebuggerKind::SCE:
CmdArgs.push_back("-debugger-tuning=sce");
break;
+ case llvm::DebuggerKind::DBX:
+ CmdArgs.push_back("-debugger-tuning=dbx");
+ break;
default:
break;
}
@@ -1082,11 +1129,18 @@
static void handleAMDGPUCodeObjectVersionOptions(const Driver &D,
const ArgList &Args,
ArgStringList &CmdArgs) {
- unsigned CodeObjVer = getOrCheckAMDGPUCodeObjectVersion(D, Args);
- CmdArgs.insert(CmdArgs.begin() + 1,
- Args.MakeArgString(Twine("--amdhsa-code-object-version=") +
- Twine(CodeObjVer)));
- CmdArgs.insert(CmdArgs.begin() + 1, "-mllvm");
+ // If no version was requested by the user, use the default value from the
+ // back end. This is consistent with the value returned from
+ // getAMDGPUCodeObjectVersion. This lets clang emit IR for amdgpu without
+ // requiring the corresponding llvm to have the AMDGPU target enabled,
+ // provided the user (e.g. front end tests) can use the default.
+ if (haveAMDGPUCodeObjectVersionArgument(D, Args)) {
+ unsigned CodeObjVer = getAMDGPUCodeObjectVersion(D, Args);
+ CmdArgs.insert(CmdArgs.begin() + 1,
+ Args.MakeArgString(Twine("--amdhsa-code-object-version=") +
+ Twine(CodeObjVer)));
+ CmdArgs.insert(CmdArgs.begin() + 1, "-mllvm");
+ }
}
void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
@@ -1375,7 +1429,7 @@
}
addMacroPrefixMapArg(D, Args, CmdArgs);
- addProfilePrefixMapArg(D, Args, CmdArgs);
+ addCoveragePrefixMapArg(D, Args, CmdArgs);
}
// FIXME: Move to target hook.
@@ -1522,6 +1576,15 @@
}
}
+void AddAAPCSVolatileBitfieldArgs(const ArgList &Args, ArgStringList &CmdArgs) {
+ if (!Args.hasFlag(options::OPT_faapcs_bitfield_width,
+ options::OPT_fno_aapcs_bitfield_width, true))
+ CmdArgs.push_back("-fno-aapcs-bitfield-width");
+
+ if (Args.getLastArg(options::OPT_ForceAAPCSBitfieldLoad))
+ CmdArgs.push_back("-faapcs-bitfield-load");
+}
+
namespace {
void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs) {
@@ -1580,6 +1643,8 @@
if (Args.getLastArg(options::OPT_mcmse))
CmdArgs.push_back("-mcmse");
+
+ AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
}
void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
@@ -1768,6 +1833,8 @@
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
}
+
+ AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
@@ -1988,7 +2055,7 @@
D.Diag(diag::warn_drv_unsupported_sdata);
}
} else if (Args.getLastArgValue(options::OPT_mcmodel_EQ)
- .equals_lower("large") &&
+ .equals_insensitive("large") &&
(Triple.getArch() == llvm::Triple::riscv64)) {
// Not support linker relaxation for RV64 with large code model.
SmallDataLimit = "0";
@@ -2219,8 +2286,8 @@
if (!CompilationDatabase) {
std::error_code EC;
- auto File = std::make_unique<llvm::raw_fd_ostream>(Filename, EC,
- llvm::sys::fs::OF_Text);
+ auto File = std::make_unique<llvm::raw_fd_ostream>(
+ Filename, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
D.Diag(clang::diag::err_drv_compilationdatabase) << Filename
<< EC.message();
@@ -2294,7 +2361,8 @@
Twine(llvm::sys::path::filename(Input.getFilename())) + ".%%%%.json");
int FD;
SmallString<256> TempPath;
- Err = llvm::sys::fs::createUniqueFile(Path, FD, TempPath);
+ Err = llvm::sys::fs::createUniqueFile(Path, FD, TempPath,
+ llvm::sys::fs::OF_Text);
if (Err) {
Driver.Diag(diag::err_drv_compilationdatabase) << Path << Err.message();
return;
@@ -2304,6 +2372,17 @@
DumpCompilationDatabase(C, "", Target, Output, Input, Args);
}
+static bool CheckARMImplicitITArg(StringRef Value) {
+ return Value == "always" || Value == "never" || Value == "arm" ||
+ Value == "thumb";
+}
+
+static void AddARMImplicitITArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ StringRef Value) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-arm-implicit-it=" + Value));
+}
+
static void CollectArgsForIntegratedAssembler(Compilation &C,
const ArgList &Args,
ArgStringList &CmdArgs,
@@ -2320,27 +2399,6 @@
DefaultIncrementalLinkerCompatible))
CmdArgs.push_back("-mincremental-linker-compatible");
- switch (C.getDefaultToolChain().getArch()) {
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- if (Arg *A = Args.getLastArg(options::OPT_mimplicit_it_EQ)) {
- StringRef Value = A->getValue();
- if (Value == "always" || Value == "never" || Value == "arm" ||
- Value == "thumb") {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back(Args.MakeArgString("-arm-implicit-it=" + Value));
- } else {
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
- }
- }
- break;
- default:
- break;
- }
-
// If you add more args here, also add them to the block below that
// starts with "// If CollectArgsForIntegratedAssembler() isn't called below".
@@ -2354,10 +2412,29 @@
bool UseRelaxRelocations = C.getDefaultToolChain().useRelaxRelocations();
bool UseNoExecStack = C.getDefaultToolChain().isNoExecStackDefault();
const char *MipsTargetFeature = nullptr;
+ StringRef ImplicitIt;
for (const Arg *A :
- Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
+ Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler,
+ options::OPT_mimplicit_it_EQ)) {
A->claim();
+ if (A->getOption().getID() == options::OPT_mimplicit_it_EQ) {
+ switch (C.getDefaultToolChain().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ // Only store the value; the last value set takes effect.
+ ImplicitIt = A->getValue();
+ if (!CheckARMImplicitITArg(ImplicitIt))
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << ImplicitIt;
+ continue;
+ default:
+ break;
+ }
+ }
+
for (StringRef Value : A->getValues()) {
if (TakeNextArg) {
CmdArgs.push_back(Value.data());
@@ -2376,6 +2453,12 @@
case llvm::Triple::thumbeb:
case llvm::Triple::arm:
case llvm::Triple::armeb:
+ if (Value.startswith("-mimplicit-it=")) {
+ // Only store the value; the last value set takes effect.
+ ImplicitIt = Value.split("=").second;
+ if (CheckARMImplicitITArg(ImplicitIt))
+ continue;
+ }
if (Value == "-mthumb")
// -mthumb has already been processed in ComputeLLVMTriple()
// recognize but skip over here.
@@ -2461,7 +2544,7 @@
CmdArgs.push_back(Value.data());
} else {
RenderDebugEnablingArgs(Args, CmdArgs,
- codegenoptions::LimitedDebugInfo,
+ codegenoptions::DebugInfoConstructor,
DwarfVersion, llvm::DebuggerKind::Default);
}
} else if (Value.startswith("-mcpu") || Value.startswith("-mfpu") ||
@@ -2497,12 +2580,16 @@
// -fdebug-compilation-dir (without '=') here.
CmdArgs.push_back("-fdebug-compilation-dir");
CmdArgs.push_back(Value.data());
+ } else if (Value == "--version") {
+ D.PrintVersion(C, llvm::outs());
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
}
+ if (ImplicitIt.size())
+ AddARMImplicitITArgs(Args, CmdArgs, ImplicitIt);
if (UseRelaxRelocations)
CmdArgs.push_back("--mrelax-relocations");
if (UseNoExecStack)
@@ -2550,7 +2637,7 @@
llvm::DenormalMode DenormalFPMath = DefaultDenormalFPMath;
llvm::DenormalMode DenormalFP32Math = DefaultDenormalFP32Math;
- StringRef FPContract = "";
+ StringRef FPContract = "on";
bool StrictFPModel = false;
@@ -2575,7 +2662,7 @@
ReciprocalMath = false;
SignedZeros = true;
// -fno_fast_math restores default denormal and fpcontract handling
- FPContract = "";
+ FPContract = "on";
DenormalFPMath = llvm::DenormalMode::getIEEE();
// FIXME: The target may have picked a non-IEEE default mode here based on
@@ -2595,20 +2682,18 @@
// ffp-model= is a Driver option, it is entirely rewritten into more
// granular options before being passed into cc1.
// Use the gcc option in the switch below.
- if (!FPModel.empty() && !FPModel.equals(Val)) {
+ if (!FPModel.empty() && !FPModel.equals(Val))
D.Diag(clang::diag::warn_drv_overriding_flag_option)
<< Args.MakeArgString("-ffp-model=" + FPModel)
<< Args.MakeArgString("-ffp-model=" + Val);
- FPContract = "";
- }
if (Val.equals("fast")) {
optID = options::OPT_ffast_math;
FPModel = Val;
- FPContract = "fast";
+ FPContract = Val;
} else if (Val.equals("precise")) {
optID = options::OPT_ffp_contract;
FPModel = Val;
- FPContract = "fast";
+ FPContract = "on";
PreciseFPModel = true;
} else if (Val.equals("strict")) {
StrictFPModel = true;
@@ -2694,9 +2779,11 @@
case options::OPT_ffp_contract: {
StringRef Val = A->getValue();
if (PreciseFPModel) {
- // -ffp-model=precise enables ffp-contract=fast as a side effect
- // the FPContract value has already been set to a string literal
- // and the Val string isn't a pertinent value.
+ // When -ffp-model=precise is seen on the command line,
+ // the boolean PreciseFPModel is set to true which indicates
+ // "the current option is actually PreciseFPModel". The optID
+ // is changed to OPT_ffp_contract and FPContract is set to "on".
+ // the argument Val string is "precise": it shouldn't be checked.
;
} else if (Val.equals("fast") || Val.equals("on") || Val.equals("off"))
FPContract = Val;
@@ -2794,18 +2881,17 @@
// -fno_fast_math restores default denormal and fpcontract handling
DenormalFPMath = DefaultDenormalFPMath;
DenormalFP32Math = llvm::DenormalMode::getIEEE();
- FPContract = "";
+ FPContract = "on";
break;
}
if (StrictFPModel) {
// If -ffp-model=strict has been specified on command line but
// subsequent options conflict then emit warning diagnostic.
- if (HonorINFs && HonorNaNs &&
- !AssociativeMath && !ReciprocalMath &&
- SignedZeros && TrappingMath && RoundingFPMath &&
- (FPContract.equals("off") || FPContract.empty()) &&
- DenormalFPMath == llvm::DenormalMode::getIEEE() &&
- DenormalFP32Math == llvm::DenormalMode::getIEEE())
+ if (HonorINFs && HonorNaNs && !AssociativeMath && !ReciprocalMath &&
+ SignedZeros && TrappingMath && RoundingFPMath &&
+ DenormalFPMath == llvm::DenormalMode::getIEEE() &&
+ DenormalFP32Math == llvm::DenormalMode::getIEEE() &&
+ FPContract.equals("off"))
// OK: Current Arg doesn't conflict with -ffp-model=strict
;
else {
@@ -3038,18 +3124,20 @@
}
}
- // First support "tls" and "global" for X86 target.
- // TODO: Support "sysreg" for AArch64.
const std::string &TripleStr = EffectiveTriple.getTriple();
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
StringRef Value = A->getValue();
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
- if (Value != "tls" && Value != "global") {
+ if (EffectiveTriple.isX86() && Value != "tls" && Value != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
- << A->getOption().getName() << Value
- << "valid arguments to '-mstack-protector-guard=' are:tls global";
+ << A->getOption().getName() << Value << "tls global";
+ return;
+ }
+ if (EffectiveTriple.isAArch64() && Value != "sysreg" && Value != "global") {
+ D.Diag(diag::err_drv_invalid_value_with_suggestion)
+ << A->getOption().getName() << Value << "sysreg global";
return;
}
A->render(Args, CmdArgs);
@@ -3057,10 +3145,10 @@
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) {
StringRef Value = A->getValue();
- if (!EffectiveTriple.isX86())
+ if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
- unsigned Offset;
+ int Offset;
if (Value.getAsInteger(10, Offset)) {
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
return;
@@ -3070,13 +3158,16 @@
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_reg_EQ)) {
StringRef Value = A->getValue();
- if (!EffectiveTriple.isX86())
+ if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
if (EffectiveTriple.isX86() && (Value != "fs" && Value != "gs")) {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
- << A->getOption().getName() << Value
- << "for X86, valid arguments to '-mstack-protector-guard-reg=' are:fs gs";
+ << A->getOption().getName() << Value << "fs gs";
+ return;
+ }
+ if (EffectiveTriple.isAArch64() && Value != "sp_el0") {
+ D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
return;
}
A->render(Args, CmdArgs);
@@ -3158,7 +3249,8 @@
}
}
-static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) {
+static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
+ types::ID InputType) {
// cl-denorms-are-zero is not forwarded. It is translated into a generic flag
// for denormal flushing handling based on the target.
const unsigned ForwardedArguments[] = {
@@ -3183,6 +3275,14 @@
for (const auto &Arg : ForwardedArguments)
if (const auto *A = Args.getLastArg(Arg))
CmdArgs.push_back(Args.MakeArgString(A->getOption().getPrefixedName()));
+
+ // Only add the default headers if we are compiling OpenCL sources.
+ if ((types::isOpenCL(InputType) ||
+ (Args.hasArg(options::OPT_cl_std_EQ) && types::isSrcFile(InputType))) &&
+ !Args.hasArg(options::OPT_cl_no_stdinc)) {
+ CmdArgs.push_back("-finclude-default-header");
+ CmdArgs.push_back("-fdeclare-opencl-builtins");
+ }
}
static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
@@ -3600,6 +3700,9 @@
WeakArg->render(Args, CmdArgs);
}
}
+
+ if (Args.hasArg(options::OPT_fobjc_disable_direct_methods_for_testing))
+ CmdArgs.push_back("-fobjc-disable-direct-methods-for-testing");
}
static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
@@ -3740,12 +3843,41 @@
return DwarfFissionKind::None;
}
+static void renderDwarfFormat(const Driver &D, const llvm::Triple &T,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ unsigned DwarfVersion) {
+ auto *DwarfFormatArg =
+ Args.getLastArg(options::OPT_gdwarf64, options::OPT_gdwarf32);
+ if (!DwarfFormatArg)
+ return;
+
+ if (DwarfFormatArg->getOption().matches(options::OPT_gdwarf64)) {
+ if (DwarfVersion < 3)
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << DwarfFormatArg->getAsString(Args) << "DWARFv3 or greater";
+ else if (!T.isArch64Bit())
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << DwarfFormatArg->getAsString(Args) << "64 bit architecture";
+ else if (!T.isOSBinFormatELF())
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << DwarfFormatArg->getAsString(Args) << "ELF platforms";
+ }
+
+ DwarfFormatArg->render(Args, CmdArgs);
+}
+
static void renderDebugOptions(const ToolChain &TC, const Driver &D,
const llvm::Triple &T, const ArgList &Args,
bool EmitCodeView, bool IRInput,
ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind &DebugInfoKind,
DwarfFissionKind &DwarfFission) {
+ // These two forms of profiling info can't be used together.
+ if (const Arg *A1 = Args.getLastArg(options::OPT_fpseudo_probe_for_profiling))
+ if (const Arg *A2 = Args.getLastArg(options::OPT_fdebug_info_for_profiling))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A1->getAsString(Args) << A2->getAsString(Args);
+
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
options::OPT_fno_debug_info_for_profiling, false) &&
checkDebugInfoOption(
@@ -3780,7 +3912,7 @@
}
}
if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
- DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ DebugInfoKind = codegenoptions::DebugInfoConstructor;
// If the last option explicitly specified a debug-info level, use it.
if (checkDebugInfoOption(A, Args, D, TC) &&
@@ -3806,15 +3938,15 @@
DebuggerTuning = llvm::DebuggerKind::LLDB;
else if (A->getOption().matches(options::OPT_gsce))
DebuggerTuning = llvm::DebuggerKind::SCE;
+ else if (A->getOption().matches(options::OPT_gdbx))
+ DebuggerTuning = llvm::DebuggerKind::DBX;
else
DebuggerTuning = llvm::DebuggerKind::GDB;
}
}
// If a -gdwarf argument appeared, remember it.
- const Arg *GDwarfN = Args.getLastArg(
- options::OPT_gdwarf_2, options::OPT_gdwarf_3, options::OPT_gdwarf_4,
- options::OPT_gdwarf_5, options::OPT_gdwarf);
+ const Arg *GDwarfN = getDwarfNArg(Args);
bool EmitDwarf = false;
if (GDwarfN) {
if (checkDebugInfoOption(GDwarfN, Args, D, TC))
@@ -3871,19 +4003,29 @@
DebugInfoKind == codegenoptions::DebugDirectivesOnly)
DebugInfoKind = codegenoptions::NoDebugInfo;
- // We ignore flag -gstrict-dwarf for now.
+ // strict DWARF is set to false by default. But for DBX, we need it to be set
+ // as true by default.
+ if (const Arg *A = Args.getLastArg(options::OPT_gstrict_dwarf))
+ (void)checkDebugInfoOption(A, Args, D, TC);
+ if (Args.hasFlag(options::OPT_gstrict_dwarf, options::OPT_gno_strict_dwarf,
+ DebuggerTuning == llvm::DebuggerKind::DBX))
+ CmdArgs.push_back("-gstrict-dwarf");
+
// And we handle flag -grecord-gcc-switches later with DWARFDebugFlags.
Args.ClaimAllArgs(options::OPT_g_flags_Group);
// Column info is included by default for everything except SCE and
// CodeView. Clang doesn't track end columns, just starting columns, which,
// in theory, is fine for CodeView (and PDB). In practice, however, the
- // Microsoft debuggers don't handle missing end columns well, so it's better
- // not to include any column info.
+ // Microsoft debuggers don't handle missing end columns well, and the AIX
+ // debugger DBX also doesn't handle the columns well, so it's better not to
+ // include any column info.
if (const Arg *A = Args.getLastArg(options::OPT_gcolumn_info))
(void)checkDebugInfoOption(A, Args, D, TC);
if (!Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
- !EmitCodeView && DebuggerTuning != llvm::DebuggerKind::SCE))
+ !EmitCodeView &&
+ (DebuggerTuning != llvm::DebuggerKind::SCE &&
+ DebuggerTuning != llvm::DebuggerKind::DBX)))
CmdArgs.push_back("-gno-column-info");
// FIXME: Move backend command line options to the module.
@@ -3892,14 +4034,14 @@
if (checkDebugInfoOption(A, Args, D, TC)) {
if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
DebugInfoKind != codegenoptions::DebugDirectivesOnly) {
- DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ DebugInfoKind = codegenoptions::DebugInfoConstructor;
CmdArgs.push_back("-dwarf-ext-refs");
CmdArgs.push_back("-fmodule-format=obj");
}
}
- if (T.isOSBinFormatELF() && !SplitDWARFInlining)
- CmdArgs.push_back("-fno-split-dwarf-inlining");
+ if (T.isOSBinFormatELF() && SplitDWARFInlining)
+ CmdArgs.push_back("-fsplit-dwarf-inlining");
// After we've dealt with all combinations of things that could
// make DebugInfoKind be other than None or DebugLineTablesOnly,
@@ -3913,7 +4055,8 @@
if (const Arg *A = Args.getLastArg(options::OPT_fstandalone_debug))
(void)checkDebugInfoOption(A, Args, D, TC);
- if (DebugInfoKind == codegenoptions::LimitedDebugInfo) {
+ if (DebugInfoKind == codegenoptions::LimitedDebugInfo ||
+ DebugInfoKind == codegenoptions::DebugInfoConstructor) {
if (Args.hasFlag(options::OPT_fno_eliminate_unused_debug_types,
options::OPT_feliminate_unused_debug_types, false))
DebugInfoKind = codegenoptions::UnusedTypeInfo;
@@ -4024,6 +4167,14 @@
}
}
+ // To avoid join/split of directory+filename, the integrated assembler prefers
+ // the directory form of .file on all DWARF versions. GNU as doesn't allow the
+ // form before DWARF v5.
+ if (!Args.hasFlag(options::OPT_fdwarf_directory_asm,
+ options::OPT_fno_dwarf_directory_asm,
+ TC.useIntegratedAs() || EffectiveDWARFVersion >= 5))
+ CmdArgs.push_back("-fno-dwarf-directory-asm");
+
// Decide how to render forward declarations of template instantiations.
// SCE wants full descriptions, others just get them in the name.
if (DebuggerTuning == llvm::DebuggerKind::SCE)
@@ -4034,25 +4185,7 @@
if (DebuggerTuning == llvm::DebuggerKind::SCE)
CmdArgs.push_back("-dwarf-explicit-import");
- auto *DwarfFormatArg =
- Args.getLastArg(options::OPT_gdwarf64, options::OPT_gdwarf32);
- if (DwarfFormatArg &&
- DwarfFormatArg->getOption().matches(options::OPT_gdwarf64)) {
- const llvm::Triple &RawTriple = TC.getTriple();
- if (EffectiveDWARFVersion < 3)
- D.Diag(diag::err_drv_argument_only_allowed_with)
- << DwarfFormatArg->getAsString(Args) << "DWARFv3 or greater";
- else if (!RawTriple.isArch64Bit())
- D.Diag(diag::err_drv_argument_only_allowed_with)
- << DwarfFormatArg->getAsString(Args) << "64 bit architecture";
- else if (!RawTriple.isOSBinFormatELF())
- D.Diag(diag::err_drv_argument_only_allowed_with)
- << DwarfFormatArg->getAsString(Args) << "ELF platforms";
- }
-
- if (DwarfFormatArg)
- DwarfFormatArg->render(Args, CmdArgs);
-
+ renderDwarfFormat(D, T, Args, CmdArgs, EffectiveDWARFVersion);
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
}
@@ -4077,9 +4210,15 @@
// include as part of the module. All other jobs are expected to have exactly
// one input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
+ bool IsCudaDevice = JA.isDeviceOffloading(Action::OFK_Cuda);
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
+ bool IsHIPDevice = JA.isDeviceOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
+ bool IsDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
+ JA.isDeviceOffloading(Action::OFK_Host));
+ bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction);
+ auto LTOMode = D.getLTOMode(IsDeviceOffloadAction);
// A header module compilation doesn't have a main input file, so invent a
// fake one as a placeholder.
@@ -4183,14 +4322,13 @@
}
if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) {
- CmdArgs.push_back("-fsycl");
CmdArgs.push_back("-fsycl-is-device");
if (Arg *A = Args.getLastArg(options::OPT_sycl_std_EQ)) {
A->render(Args, CmdArgs);
} else {
- // Ensure the default version in SYCL mode is 1.2.1 (aka 2017)
- CmdArgs.push_back("-sycl-std=2017");
+ // Ensure the default version in SYCL mode is 2020.
+ CmdArgs.push_back("-sycl-std=2020");
}
}
@@ -4220,6 +4358,10 @@
// are provided.
TC.addClangWarningOptions(CmdArgs);
+ // FIXME: Subclass ToolChain for SPIR and move this to addClangWarningOptions.
+ if (Triple.isSPIR())
+ CmdArgs.push_back("-Wspir-compat");
+
// Select the appropriate action.
RewriteKind rewriteKind = RK_None;
@@ -4295,13 +4437,19 @@
CmdArgs.push_back("-emit-llvm");
} else if (JA.getType() == types::TY_LLVM_BC ||
JA.getType() == types::TY_LTO_BC) {
- CmdArgs.push_back("-emit-llvm-bc");
+ // Emit textual llvm IR for AMDGPU offloading for -emit-llvm -S
+ if (Triple.isAMDGCN() && IsOpenMPDevice && Args.hasArg(options::OPT_S) &&
+ Args.hasArg(options::OPT_emit_llvm)) {
+ CmdArgs.push_back("-emit-llvm");
+ } else {
+ CmdArgs.push_back("-emit-llvm-bc");
+ }
} else if (JA.getType() == types::TY_IFS ||
JA.getType() == types::TY_IFS_CPP) {
StringRef ArgStr =
Args.hasArg(options::OPT_interface_stub_version_EQ)
? Args.getLastArgValue(options::OPT_interface_stub_version_EQ)
- : "experimental-ifs-v2";
+ : "ifs-v1";
CmdArgs.push_back("-emit-interface-stubs");
CmdArgs.push_back(
Args.MakeArgString(Twine("-interface-stub-version=") + ArgStr.str()));
@@ -4328,13 +4476,30 @@
if (JA.getType() == types::TY_LLVM_BC)
CmdArgs.push_back("-emit-llvm-uselists");
- // Device-side jobs do not support LTO.
- bool isDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
- JA.isDeviceOffloading(Action::OFK_Host));
-
- if (D.isUsingLTO() && !isDeviceOffloadAction) {
- Args.AddLastArg(CmdArgs, options::OPT_flto, options::OPT_flto_EQ);
- CmdArgs.push_back("-flto-unit");
+ if (IsUsingLTO) {
+ if (!IsDeviceOffloadAction) {
+ if (Args.hasArg(options::OPT_flto))
+ CmdArgs.push_back("-flto");
+ else {
+ if (D.getLTOMode() == LTOK_Thin)
+ CmdArgs.push_back("-flto=thin");
+ else
+ CmdArgs.push_back("-flto=full");
+ }
+ CmdArgs.push_back("-flto-unit");
+ } else if (Triple.isAMDGPU()) {
+ // Only AMDGPU supports device-side LTO
+ assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin);
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full")));
+ CmdArgs.push_back("-flto-unit");
+ } else {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Args.getLastArg(options::OPT_foffload_lto,
+ options::OPT_foffload_lto_EQ)
+ ->getAsString(Args)
+ << Triple.getTriple();
+ }
}
}
@@ -4359,7 +4524,7 @@
// Embed-bitcode option.
// Only white-listed flags below are allowed to be embedded.
- if (C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO() &&
+ if (C.getDriver().embedBitcodeInObject() && !IsUsingLTO &&
(isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
// Add flags implied by -fembed-bitcode.
Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
@@ -4476,7 +4641,7 @@
return;
}
- if (C.getDriver().embedBitcodeMarkerOnly() && !C.getDriver().isUsingLTO())
+ if (C.getDriver().embedBitcodeMarkerOnly() && !IsUsingLTO)
CmdArgs.push_back("-fembed-bitcode=marker");
// We normally speed up the clang process a bit by skipping destructors at
@@ -4617,7 +4782,8 @@
options::OPT_fno_semantic_interposition);
if (RelocationModel != llvm::Reloc::Static && !IsPIE) {
// The supported targets need to call AsmPrinter::getSymbolPreferLocal.
- bool SupportsLocalAlias = Triple.isX86();
+ bool SupportsLocalAlias =
+ Triple.isAArch64() || Triple.isRISCV() || Triple.isX86();
if (!A)
CmdArgs.push_back("-fhalf-no-semantic-interposition");
else if (A->getOption().matches(options::OPT_fsemantic_interposition))
@@ -4654,18 +4820,13 @@
// LLVM Code Generator Options.
- if (Args.hasArg(options::OPT_frewrite_map_file) ||
- Args.hasArg(options::OPT_frewrite_map_file_EQ)) {
- for (const Arg *A : Args.filtered(options::OPT_frewrite_map_file,
- options::OPT_frewrite_map_file_EQ)) {
- StringRef Map = A->getValue();
- if (!llvm::sys::fs::exists(Map)) {
- D.Diag(diag::err_drv_no_such_file) << Map;
- } else {
- CmdArgs.push_back("-frewrite-map-file");
- CmdArgs.push_back(A->getValue());
- A->claim();
- }
+ for (const Arg *A : Args.filtered(options::OPT_frewrite_map_file_EQ)) {
+ StringRef Map = A->getValue();
+ if (!llvm::sys::fs::exists(Map)) {
+ D.Diag(diag::err_drv_no_such_file) << Map;
+ } else {
+ A->render(Args, CmdArgs);
+ A->claim();
}
}
@@ -4677,13 +4838,25 @@
if (A->getOption().getID() == options::OPT_mabi_EQ_vec_extabi)
CmdArgs.push_back("-mabi=vec-extabi");
else
- D.Diag(diag::err_aix_default_altivec_abi);
+ CmdArgs.push_back("-mabi=vec-default");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mlong_double_128)) {
+ // Emit the unsupported option error until the Clang's library integration
+ // support for 128-bit long double is available for AIX.
+ if (Triple.isOSAIX())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << RawTriple.str();
}
if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
StringRef v = A->getValue();
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v));
+ // FIXME: Validate the argument here so we don't produce meaningless errors
+ // about -fwarn-stack-size=.
+ if (v.empty())
+ D.Diag(diag::err_drv_missing_argument) << A->getSpelling() << 1;
+ else
+ CmdArgs.push_back(Args.MakeArgString("-fwarn-stack-size=" + v));
A->claim();
}
@@ -4802,12 +4975,35 @@
Args.AddLastArg(CmdArgs, options::OPT_ffine_grained_bitfield_accesses,
options::OPT_fno_fine_grained_bitfield_accesses);
+ Args.AddLastArg(CmdArgs, options::OPT_fexperimental_relative_cxx_abi_vtables,
+ options::OPT_fno_experimental_relative_cxx_abi_vtables);
+
// Handle segmented stacks.
- if (Args.hasArg(options::OPT_fsplit_stack))
- CmdArgs.push_back("-split-stacks");
+ if (Args.hasFlag(options::OPT_fsplit_stack, options::OPT_fno_split_stack,
+ false))
+ CmdArgs.push_back("-fsplit-stack");
+
+ // -fprotect-parens=0 is default.
+ if (Args.hasFlag(options::OPT_fprotect_parens,
+ options::OPT_fno_protect_parens, false))
+ CmdArgs.push_back("-fprotect-parens");
RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs, JA);
+ if (Arg *A = Args.getLastArg(options::OPT_fextend_args_EQ)) {
+ const llvm::Triple::ArchType Arch = TC.getArch();
+ if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+ StringRef V = A->getValue();
+ if (V == "64")
+ CmdArgs.push_back("-fextend-arguments=64");
+ else if (V != "32")
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << A->getValue() << A->getOption().getName();
+ } else
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getOption().getName() << TripleStr;
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_mdouble_EQ)) {
if (TC.getArch() == llvm::Triple::avr)
A->render(Args, CmdArgs);
@@ -4850,7 +5046,9 @@
<< A->getValue() << A->getOption().getName();
}
- if (!TC.useIntegratedAs())
+ // If toolchain choose to use MCAsmParser for inline asm don't pass the
+ // option to disable integrated-as explictly.
+ if (!TC.useIntegratedAs() && !TC.parseInlineAsmUsingAsmParser())
CmdArgs.push_back("-no-integrated-as");
if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
@@ -4863,9 +5061,9 @@
}
// Enable -mconstructor-aliases except on darwin, where we have to work around
- // a linker bug (see <rdar://problem/7651567>), and CUDA device code, where
- // aliases aren't supported. Similarly, aliases aren't yet supported for AIX.
- if (!RawTriple.isOSDarwin() && !RawTriple.isNVPTX() && !RawTriple.isOSAIX())
+ // a linker bug (see <rdar://problem/7651567>), and CUDA/AMDGPU device code,
+ // where aliases aren't supported.
+ if (!RawTriple.isOSDarwin() && !RawTriple.isNVPTX() && !RawTriple.isAMDGPU())
CmdArgs.push_back("-mconstructor-aliases");
// Darwin's kernel doesn't support guard variables; just die if we
@@ -4903,21 +5101,21 @@
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
- bool AsynchronousUnwindTables =
+ bool UnwindTables =
Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
options::OPT_fno_asynchronous_unwind_tables,
(TC.IsUnwindTablesDefault(Args) ||
TC.getSanitizerArgs().needsUnwindTables()) &&
!Freestanding);
- if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
- AsynchronousUnwindTables))
+ UnwindTables = Args.hasFlag(options::OPT_funwind_tables,
+ options::OPT_fno_unwind_tables, UnwindTables);
+ if (UnwindTables)
CmdArgs.push_back("-munwind-tables");
// Prepare `-aux-target-cpu` and `-aux-target-feature` unless
// `--gpu-use-aux-triple-only` is specified.
if (!Args.getLastArg(options::OPT_gpu_use_aux_triple_only) &&
- ((IsCuda && JA.isDeviceOffloading(Action::OFK_Cuda)) ||
- (IsHIP && JA.isDeviceOffloading(Action::OFK_HIP)))) {
+ (IsCudaDevice || IsHIPDevice)) {
const ArgList &HostArgs =
C.getArgsForToolChain(nullptr, StringRef(), Action::OFK_None);
std::string HostCPU =
@@ -4938,11 +5136,15 @@
if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
StringRef CM = A->getValue();
if (CM == "small" || CM == "kernel" || CM == "medium" || CM == "large" ||
- CM == "tiny")
- A->render(Args, CmdArgs);
- else
+ CM == "tiny") {
+ if (Triple.isOSAIX() && CM == "medium")
+ CmdArgs.push_back("-mcmodel=large");
+ else
+ A->render(Args, CmdArgs);
+ } else {
D.Diag(diag::err_drv_invalid_argument_to_option)
<< CM << A->getOption().getName();
+ }
}
if (Arg *A = Args.getLastArg(options::OPT_mtls_size_EQ)) {
@@ -4967,6 +5169,21 @@
RenderTargetOptions(Triple, Args, KernelOrKext, CmdArgs);
+ // FIXME: For now we want to demote any errors to warnings, when they have
+ // been raised for asking the wrong question of scalable vectors, such as
+ // asking for the fixed number of elements. This may happen because code that
+ // is not yet ported to work for scalable vectors uses the wrong interfaces,
+ // whereas the behaviour is actually correct. Emitting a warning helps bring
+ // up scalable vector support in an incremental way. When scalable vector
+ // support is stable enough, all uses of wrong interfaces should be considered
+ // as errors, but until then, we can live with a warning being emitted by the
+ // compiler. This way, Clang can be used to compile code with scalable vectors
+ // and identify possible issues.
+ if (isa<BackendJobAction>(JA)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-treat-scalable-fixed-error-as-warning");
+ }
+
// These two are potentially updated by AddClangCLArgs.
codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
bool EmitCodeView = false;
@@ -5031,11 +5248,13 @@
CmdArgs.push_back("-H");
CmdArgs.push_back("-sys-header-deps");
}
+ Args.AddAllArgs(CmdArgs, options::OPT_fshow_skipped_includes);
if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
CmdArgs.push_back("-header-include-file");
- CmdArgs.push_back(D.CCPrintHeadersFilename ? D.CCPrintHeadersFilename
- : "-");
+ CmdArgs.push_back(!D.CCPrintHeadersFilename.empty()
+ ? D.CCPrintHeadersFilename.c_str()
+ : "-");
CmdArgs.push_back("-sys-header-deps");
}
Args.AddLastArg(CmdArgs, options::OPT_P);
@@ -5043,8 +5262,9 @@
if (D.CCLogDiagnostics && !D.CCGenDiagnostics) {
CmdArgs.push_back("-diagnostic-log-file");
- CmdArgs.push_back(D.CCLogDiagnosticsFilename ? D.CCLogDiagnosticsFilename
- : "-");
+ CmdArgs.push_back(!D.CCLogDiagnosticsFilename.empty()
+ ? D.CCLogDiagnosticsFilename.c_str()
+ : "-");
}
// Give the gen diagnostics more chances to succeed, by avoiding intentional
@@ -5052,6 +5272,14 @@
if (D.CCGenDiagnostics)
CmdArgs.push_back("-disable-pragma-debug-crash");
+ // Allow backend to put its diagnostic files in the same place as frontend
+ // crash diagnostics files.
+ if (Args.hasArg(options::OPT_fcrash_diagnostics_dir)) {
+ StringRef Dir = Args.getLastArgValue(options::OPT_fcrash_diagnostics_dir);
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-crash-diagnostics-dir=" + Dir));
+ }
+
bool UseSeparateSections = isUseSeparateSections(Triple);
if (Args.hasFlag(options::OPT_ffunction_sections,
@@ -5060,15 +5288,20 @@
}
if (Arg *A = Args.getLastArg(options::OPT_fbasic_block_sections_EQ)) {
+ StringRef Val = A->getValue();
if (Triple.isX86() && Triple.isOSBinFormatELF()) {
- StringRef Val = A->getValue();
if (Val != "all" && Val != "labels" && Val != "none" &&
!Val.startswith("list="))
D.Diag(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
else
A->render(Args, CmdArgs);
- } else {
+ } else if (Triple.isNVPTX()) {
+ // Do not pass the option to the GPU compilation. We still want it enabled
+ // for the host-side compilation, so seeing it here is not an error.
+ } else if (Val != "none") {
+ // =none is allowed everywhere. It's useful for overriding the option
+ // and is the same as not specifying the option.
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
}
@@ -5193,11 +5426,18 @@
/*Default=*/false))
Args.AddLastArg(CmdArgs, options::OPT_ffixed_point);
+ if (Arg *A = Args.getLastArg(options::OPT_fcxx_abi_EQ))
+ A->render(Args, CmdArgs);
+
+ Args.AddLastArg(CmdArgs, options::OPT_fexperimental_relative_cxx_abi_vtables,
+ options::OPT_fno_experimental_relative_cxx_abi_vtables);
+
// Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
// (-ansi is equivalent to -std=c89 or -std=c++98).
//
// If a std is supplied, only add -trigraphs if it follows the
// option.
+ bool ImplyVCPPCVer = false;
bool ImplyVCPPCXXVer = false;
const Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi);
if (Std) {
@@ -5222,9 +5462,13 @@
// doesn't match. For the time being just ignore this for C++ inputs;
// eventually we want to do all the standard defaulting here instead of
// splitting it between the driver and clang -cc1.
- if (!types::isCXX(InputType))
- Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=",
- /*Joined=*/true);
+ if (!types::isCXX(InputType)) {
+ if (!Args.hasArg(options::OPT__SLASH_std)) {
+ Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=",
+ /*Joined=*/true);
+ } else
+ ImplyVCPPCVer = true;
+ }
else if (IsWindowsMSVC)
ImplyVCPPCXXVer = true;
@@ -5274,9 +5518,6 @@
CmdArgs.push_back("-fno-gnu-keywords");
}
- if (ShouldDisableDwarfDirectory(Args, TC))
- CmdArgs.push_back("-fno-dwarf-directory-asm");
-
if (!ShouldEnableAutolink(Args, TC, JA))
CmdArgs.push_back("-fno-autolink");
@@ -5351,6 +5592,18 @@
options::OPT_fno_stack_size_section, RawTriple.isPS4()))
CmdArgs.push_back("-fstack-size-section");
+ if (Args.hasArg(options::OPT_fstack_usage)) {
+ CmdArgs.push_back("-stack-usage-file");
+
+ if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
+ SmallString<128> OutputFilename(OutputOpt->getValue());
+ llvm::sys::path::replace_extension(OutputFilename, "su");
+ CmdArgs.push_back(Args.MakeArgString(OutputFilename));
+ } else
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(getBaseInputStem(Args, Inputs)) + ".su"));
+ }
+
CmdArgs.push_back("-ferror-limit");
if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
CmdArgs.push_back(A->getValue());
@@ -5431,18 +5684,25 @@
<< A->getAsString(Args) << TripleStr;
}
- Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
+
+ if (Args.hasFlag(options::OPT_fvisibility_inlines_hidden,
+ options::OPT_fno_visibility_inlines_hidden, false))
+ CmdArgs.push_back("-fvisibility-inlines-hidden");
+
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var,
options::OPT_fno_visibility_inlines_hidden_static_local_var);
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden);
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
+ if (Args.hasFlag(options::OPT_fno_operator_names,
+ options::OPT_foperator_names, false))
+ CmdArgs.push_back("-fno-operator-names");
+
// Forward -f (flag) options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs);
- Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
options::OPT_fno_emulated_tls);
@@ -5490,13 +5750,6 @@
options::OPT_fno_openmp_cuda_mode, /*Default=*/false))
CmdArgs.push_back("-fopenmp-cuda-mode");
- // When in OpenMP offloading mode with NVPTX target, forward
- // cuda-parallel-target-regions flag
- if (Args.hasFlag(options::OPT_fopenmp_cuda_parallel_target_regions,
- options::OPT_fno_openmp_cuda_parallel_target_regions,
- /*Default=*/true))
- CmdArgs.push_back("-fopenmp-cuda-parallel-target-regions");
-
// When in OpenMP offloading mode with NVPTX target, check if full runtime
// is required.
if (Args.hasFlag(options::OPT_fopenmp_cuda_force_full_runtime,
@@ -5536,8 +5789,7 @@
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) {
StringRef S0 = A->getValue(), S = S0;
unsigned Size, Offset = 0;
- if (!Triple.isAArch64() && Triple.getArch() != llvm::Triple::x86 &&
- Triple.getArch() != llvm::Triple::x86_64)
+ if (!Triple.isAArch64() && !Triple.isRISCV() && !Triple.isX86())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
else if (S.consumeInteger(10, Size) ||
@@ -5585,6 +5837,7 @@
(Args.hasArg(options::OPT_mkernel) && types::isCXX(InputType)))
CmdArgs.push_back("-fapple-kext");
+ Args.AddLastArg(CmdArgs, options::OPT_altivec_src_compat);
Args.AddLastArg(CmdArgs, options::OPT_flax_vector_conversions_EQ);
Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
@@ -5678,7 +5931,7 @@
}
// Forward -cl options to -cc1
- RenderOpenCLOptions(Args, CmdArgs);
+ RenderOpenCLOptions(Args, CmdArgs, InputType);
if (IsHIP) {
if (Args.hasFlag(options::OPT_fhip_new_launch_api,
@@ -5690,6 +5943,8 @@
}
if (IsCuda || IsHIP) {
+ if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
+ CmdArgs.push_back("-fgpu-rdc");
if (Args.hasFlag(options::OPT_fgpu_defer_diag,
options::OPT_fno_gpu_defer_diag, false))
CmdArgs.push_back("-fgpu-defer-diag");
@@ -5706,29 +5961,38 @@
Args.MakeArgString(Twine("-fcf-protection=") + A->getValue()));
}
- // Forward -f options with positive and negative forms; we translate
- // these by hand.
- if (Arg *A = getLastProfileSampleUseArg(Args)) {
- auto *PGOArg = Args.getLastArg(
- options::OPT_fprofile_generate, options::OPT_fprofile_generate_EQ,
- options::OPT_fcs_profile_generate, options::OPT_fcs_profile_generate_EQ,
- options::OPT_fprofile_use, options::OPT_fprofile_use_EQ);
- if (PGOArg)
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "SampleUse with PGO options";
+ // Forward -f options with positive and negative forms; we translate these by
+ // hand. Do not propagate PGO options to the GPU-side compilations as the
+ // profile info is for the host-side compilation only.
+ if (!(IsCudaDevice || IsHIPDevice)) {
+ if (Arg *A = getLastProfileSampleUseArg(Args)) {
+ auto *PGOArg = Args.getLastArg(
+ options::OPT_fprofile_generate, options::OPT_fprofile_generate_EQ,
+ options::OPT_fcs_profile_generate,
+ options::OPT_fcs_profile_generate_EQ, options::OPT_fprofile_use,
+ options::OPT_fprofile_use_EQ);
+ if (PGOArg)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "SampleUse with PGO options";
- StringRef fname = A->getValue();
- if (!llvm::sys::fs::exists(fname))
- D.Diag(diag::err_drv_no_such_file) << fname;
- else
- A->render(Args, CmdArgs);
+ StringRef fname = A->getValue();
+ if (!llvm::sys::fs::exists(fname))
+ D.Diag(diag::err_drv_no_such_file) << fname;
+ else
+ A->render(Args, CmdArgs);
+ }
+ Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ);
+
+ if (Args.hasFlag(options::OPT_fpseudo_probe_for_profiling,
+ options::OPT_fno_pseudo_probe_for_profiling, false)) {
+ CmdArgs.push_back("-fpseudo-probe-for-profiling");
+ // Enforce -funique-internal-linkage-names if it's not explicitly turned
+ // off.
+ if (Args.hasFlag(options::OPT_funique_internal_linkage_names,
+ options::OPT_fno_unique_internal_linkage_names, true))
+ CmdArgs.push_back("-funique-internal-linkage-names");
+ }
}
- Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ);
-
- if (Args.hasFlag(options::OPT_fpseudo_probe_for_profiling,
- options::OPT_fno_pseudo_probe_for_profiling, false))
- CmdArgs.push_back("-fpseudo-probe-for-profiling");
-
RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
@@ -5845,6 +6109,20 @@
Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
bool IsMSVC2015Compatible = MSVT.getMajor() >= 19;
+ if (ImplyVCPPCVer) {
+ StringRef LanguageStandard;
+ if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
+ Std = StdArg;
+ LanguageStandard = llvm::StringSwitch<StringRef>(StdArg->getValue())
+ .Case("c11", "-std=c11")
+ .Case("c17", "-std=c17")
+ .Default("");
+ if (LanguageStandard.empty())
+ D.Diag(clang::diag::warn_drv_unused_argument)
+ << StdArg->getAsString(Args);
+ }
+ CmdArgs.push_back(LanguageStandard.data());
+ }
if (ImplyVCPPCXXVer) {
StringRef LanguageStandard;
if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
@@ -5852,7 +6130,8 @@
LanguageStandard = llvm::StringSwitch<StringRef>(StdArg->getValue())
.Case("c++14", "-std=c++14")
.Case("c++17", "-std=c++17")
- .Case("c++latest", "-std=c++20")
+ .Case("c++20", "-std=c++20")
+ .Case("c++latest", "-std=c++2b")
.Default("");
if (LanguageStandard.empty())
D.Diag(clang::diag::warn_drv_unused_argument)
@@ -5939,13 +6218,20 @@
RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None,
Input, CmdArgs);
+ if (types::isObjC(Input.getType()) &&
+ Args.hasFlag(options::OPT_fobjc_encode_cxx_class_template_spec,
+ options::OPT_fno_objc_encode_cxx_class_template_spec,
+ !Runtime.isNeXTFamily()))
+ CmdArgs.push_back("-fobjc-encode-cxx-class-template-spec");
+
if (Args.hasFlag(options::OPT_fapplication_extension,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-fapplication-extension");
// Handle GCC-style exception args.
+ bool EH = false;
if (!C.getDriver().IsCLMode())
- addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs);
+ EH = addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs);
// Handle exception personalities
Arg *A = Args.getLastArg(
@@ -6074,7 +6360,7 @@
// -finput_charset=UTF-8 is default. Reject others
if (Arg *inputCharset = Args.getLastArg(options::OPT_finput_charset_EQ)) {
StringRef value = inputCharset->getValue();
- if (!value.equals_lower("utf-8"))
+ if (!value.equals_insensitive("utf-8"))
D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args)
<< value;
}
@@ -6082,7 +6368,7 @@
// -fexec_charset=UTF-8 is default. Reject others
if (Arg *execCharset = Args.getLastArg(options::OPT_fexec_charset_EQ)) {
StringRef value = execCharset->getValue();
- if (!value.equals_lower("utf-8"))
+ if (!value.equals_insensitive("utf-8"))
D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args)
<< value;
}
@@ -6252,7 +6538,7 @@
// be added so both IR can be captured.
if ((C.getDriver().isSaveTempsEnabled() ||
JA.isHostOffloading(Action::OFK_OpenMP)) &&
- !(C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO()) &&
+ !(C.getDriver().embedBitcodeInObject() && !IsUsingLTO) &&
isa<CompileJobAction>(JA))
CmdArgs.push_back("-disable-llvm-passes");
@@ -6314,9 +6600,31 @@
CmdArgs.push_back("-fcuda-short-ptr");
}
+ if (IsCuda || IsHIP) {
+ // Determine the original source input.
+ const Action *SourceAction = &JA;
+ while (SourceAction->getKind() != Action::InputClass) {
+ assert(!SourceAction->getInputs().empty() && "unexpected root action!");
+ SourceAction = SourceAction->getInputs()[0];
+ }
+ auto CUID = cast<InputAction>(SourceAction)->getId();
+ if (!CUID.empty())
+ CmdArgs.push_back(Args.MakeArgString(Twine("-cuid=") + Twine(CUID)));
+ }
+
if (IsHIP)
CmdArgs.push_back("-fcuda-allow-variadic-functions");
+ if (IsCudaDevice || IsHIPDevice) {
+ StringRef InlineThresh =
+ Args.getLastArgValue(options::OPT_fgpu_inline_threshold_EQ);
+ if (!InlineThresh.empty()) {
+ std::string ArgStr =
+ std::string("-inline-threshold=") + InlineThresh.str();
+ CmdArgs.append({"-mllvm", Args.MakeArgStringRef(ArgStr)});
+ }
+ }
+
// OpenMP offloading device jobs take the argument -fopenmp-host-ir-file-path
// to specify the result of the compile phase on the host, so the meaningful
// device declarations can be identified. Also, -fopenmp-is-device is passed
@@ -6334,7 +6642,7 @@
handleAMDGPUCodeObjectVersionOptions(D, Args, CmdArgs);
if (Args.hasFlag(options::OPT_munsafe_fp_atomics,
- options::OPT_mno_unsafe_fp_atomics))
+ options::OPT_mno_unsafe_fp_atomics, /*Default=*/false))
CmdArgs.push_back("-munsafe-fp-atomics");
}
@@ -6363,7 +6671,7 @@
if (VirtualFunctionElimination) {
// VFE requires full LTO (currently, this might be relaxed to allow ThinLTO
// in the future).
- if (D.getLTOMode() != LTOK_Full)
+ if (LTOMode != LTOK_Full)
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-fvirtual-function-elimination"
<< "-flto=full";
@@ -6382,16 +6690,22 @@
}
if (WholeProgramVTables) {
- if (!D.isUsingLTO())
+ // Propagate -fwhole-program-vtables if this is an LTO compile.
+ if (IsUsingLTO)
+ CmdArgs.push_back("-fwhole-program-vtables");
+ // Check if we passed LTO options but they were suppressed because this is a
+ // device offloading action, or we passed device offload LTO options which
+ // were suppressed because this is not the device offload action.
+ // Otherwise, issue an error.
+ else if (!D.isUsingLTO(!IsDeviceOffloadAction))
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-fwhole-program-vtables"
<< "-flto";
- CmdArgs.push_back("-fwhole-program-vtables");
}
bool DefaultsSplitLTOUnit =
(WholeProgramVTables || Sanitize.needsLTO()) &&
- (D.getLTOMode() == LTOK_Full || TC.canSplitThinLTOUnit());
+ (LTOMode == LTOK_Full || TC.canSplitThinLTOUnit());
bool SplitLTOUnit =
Args.hasFlag(options::OPT_fsplit_lto_unit,
options::OPT_fno_split_lto_unit, DefaultsSplitLTOUnit);
@@ -6437,7 +6751,7 @@
// Enable order file instrumentation when ThinLTO is not on. When ThinLTO is
// on, we need to pass these flags as linker flags and that will be handled
// outside of the compiler.
- if (!D.isUsingLTO()) {
+ if (!IsUsingLTO) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-enable-order-file-instrumentation");
}
@@ -6478,6 +6792,10 @@
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("-outline-atomics");
}
+ } else if (Triple.isAArch64() &&
+ getToolChain().IsAArch64OutlineAtomicsDefault(Args)) {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+outline-atomics");
}
if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
@@ -6489,6 +6807,10 @@
!TC.getTriple().isAndroid() && TC.useIntegratedAs()))
CmdArgs.push_back("-faddrsig");
+ if ((Triple.isOSBinFormatELF() || Triple.isOSBinFormatMachO()) &&
+ (EH || UnwindTables || DebugInfoKind != codegenoptions::NoDebugInfo))
+ CmdArgs.push_back("-D__GCC_HAVE_DWARF2_CFI_ASM=1");
+
if (Arg *A = Args.getLastArg(options::OPT_fsymbol_partition_EQ)) {
std::string Str = A->getAsString(Args);
if (!TC.getTriple().isOSBinFormatELF())
@@ -6531,23 +6853,7 @@
Input.getInputArg().renderAsInput(Args, CmdArgs);
}
- // Finally add the compile command to the compilation.
- if (Args.hasArg(options::OPT__SLASH_fallback) &&
- Output.getType() == types::TY_Object &&
- (InputType == types::TY_C || InputType == types::TY_CXX)) {
- auto CLCommand =
- getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput);
- C.addCommand(std::make_unique<FallbackCommand>(
- JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
- Output, std::move(CLCommand)));
- } else if (Args.hasArg(options::OPT__SLASH_fallback) &&
- isa<PrecompileJobAction>(JA)) {
- // In /fallback builds, run the main compilation even if the pch generation
- // fails, so that the main compilation's fallback to cl.exe runs.
- C.addCommand(std::make_unique<ForceSuccessCommand>(
- JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
- Output));
- } else if (D.CC1Main && !D.CCGenDiagnostics) {
+ if (D.CC1Main && !D.CCGenDiagnostics) {
// Invoke the CC1 directly in this process
C.addCommand(std::make_unique<CC1Command>(JA, *this,
ResponseFileSupport::AtFileUTF8(),
@@ -6875,7 +7181,7 @@
options::OPT_gline_tables_only)) {
*EmitCodeView = true;
if (DebugInfoArg->getOption().matches(options::OPT__SLASH_Z7))
- *DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ *DebugInfoKind = codegenoptions::DebugInfoConstructor;
else
*DebugInfoKind = codegenoptions::DebugLineTablesOnly;
} else {
@@ -6913,11 +7219,7 @@
if (Args.hasFlag(options::OPT__SLASH_Zc_dllexportInlines_,
options::OPT__SLASH_Zc_dllexportInlines,
false)) {
- if (Args.hasArg(options::OPT__SLASH_fallback)) {
- D.Diag(clang::diag::err_drv_dllexport_inlines_and_fallback);
- } else {
- CmdArgs.push_back("-fno-dllexport-inlines");
- }
+ CmdArgs.push_back("-fno-dllexport-inlines");
}
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
@@ -6986,22 +7288,24 @@
if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
- if (Args.hasArg(options::OPT__SLASH_fallback))
- CmdArgs.push_back("msvc-fallback");
- else
- CmdArgs.push_back("msvc");
+ CmdArgs.push_back("msvc");
}
if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
StringRef GuardArgs = A->getValue();
- // The only valid options are "cf", "cf,nochecks", and "cf-".
- if (GuardArgs.equals_lower("cf")) {
+ // The only valid options are "cf", "cf,nochecks", "cf-", "ehcont" and
+ // "ehcont-".
+ if (GuardArgs.equals_insensitive("cf")) {
// Emit CFG instrumentation and the table of address-taken functions.
CmdArgs.push_back("-cfguard");
- } else if (GuardArgs.equals_lower("cf,nochecks")) {
+ } else if (GuardArgs.equals_insensitive("cf,nochecks")) {
// Emit only the table of address-taken functions.
CmdArgs.push_back("-cfguard-no-checks");
- } else if (GuardArgs.equals_lower("cf-")) {
+ } else if (GuardArgs.equals_insensitive("ehcont")) {
+ // Emit EH continuation table.
+ CmdArgs.push_back("-ehcontguard");
+ } else if (GuardArgs.equals_insensitive("cf-") ||
+ GuardArgs.equals_insensitive("ehcont-")) {
// Do nothing, but we might want to emit a security warning in future.
} else {
D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << GuardArgs;
@@ -7009,13 +7313,6 @@
}
}
-visualstudio::Compiler *Clang::getCLFallback() const {
- if (!CLFallback)
- CLFallback.reset(new visualstudio::Compiler(getToolChain()));
- return CLFallback.get();
-}
-
-
const char *Clang::getBaseInputName(const ArgList &Args,
const InputInfo &Input) {
return Args.MakeArgString(llvm::sys::path::filename(Input.getBaseInput()));
@@ -7148,18 +7445,14 @@
// Forward -g and handle debug info related flags, assuming we are dealing
// with an actual assembly file.
bool WantDebug = false;
- unsigned DwarfVersion = 0;
Args.ClaimAllArgs(options::OPT_g_Group);
- if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ if (Arg *A = Args.getLastArg(options::OPT_g_Group))
WantDebug = !A->getOption().matches(options::OPT_g0) &&
!A->getOption().matches(options::OPT_ggdb0);
- if (WantDebug)
- DwarfVersion = DwarfVersionNum(A->getSpelling());
- }
- unsigned DefaultDwarfVersion = ParseDebugDefaultVersion(getToolChain(), Args);
- if (DwarfVersion == 0)
- DwarfVersion = DefaultDwarfVersion;
+ unsigned DwarfVersion = ParseDebugDefaultVersion(getToolChain(), Args);
+ if (const Arg *GDwarfN = getDwarfNArg(Args))
+ DwarfVersion = DwarfVersionNum(GDwarfN->getSpelling());
if (DwarfVersion == 0)
DwarfVersion = getToolChain().GetDefaultDwarfVersion();
@@ -7172,7 +7465,7 @@
// the guard for source type, however there is a test which asserts
// that some assembler invocation receives no -debug-info-kind,
// and it's not clear whether that test is just overly restrictive.
- DebugInfoKind = (WantDebug ? codegenoptions::LimitedDebugInfo
+ DebugInfoKind = (WantDebug ? codegenoptions::DebugInfoConstructor
: codegenoptions::NoDebugInfo);
// Add the -fdebug-compilation-dir flag if needed.
addDebugCompDirArg(Args, CmdArgs, C.getDriver().getVFS());
@@ -7189,6 +7482,7 @@
}
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
llvm::DebuggerKind::Default);
+ renderDwarfFormat(D, Triple, Args, CmdArgs, DwarfVersion);
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, getToolChain());
@@ -7362,10 +7656,16 @@
});
}
Triples += Action::GetOffloadKindName(CurKind);
- Triples += '-';
- Triples += CurTC->getTriple().normalize();
- if (CurKind == Action::OFK_HIP && CurDep->getOffloadingArch()) {
- Triples += '-';
+ Triples += "-";
+ std::string NormalizedTriple = CurTC->getTriple().normalize();
+ Triples += NormalizedTriple;
+
+ if (CurDep->getOffloadingArch() != nullptr) {
+ // If OffloadArch is present it can only appear as the 6th hypen
+ // sepearated field of Bundle Entry ID. So, pad required number of
+ // hyphens in Triple.
+ for (int i = 4 - StringRef(NormalizedTriple).count("-"); i > 0; i--)
+ Triples += "-";
Triples += CurDep->getOffloadingArch();
}
}
@@ -7435,11 +7735,17 @@
auto &Dep = DepInfo[I];
Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
- Triples += '-';
- Triples += Dep.DependentToolChain->getTriple().normalize();
- if (Dep.DependentOffloadKind == Action::OFK_HIP &&
- !Dep.DependentBoundArch.empty()) {
- Triples += '-';
+ Triples += "-";
+ std::string NormalizedTriple =
+ Dep.DependentToolChain->getTriple().normalize();
+ Triples += NormalizedTriple;
+
+ if (!Dep.DependentBoundArch.empty()) {
+ // If OffloadArch is present it can only appear as the 6th hypen
+ // sepearated field of Bundle Entry ID. So, pad required number of
+ // hyphens in Triple.
+ for (int i = 4 - StringRef(NormalizedTriple).count("-"); i > 0; i--)
+ Triples += "-";
Triples += Dep.DependentBoundArch;
}
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Clang.h b/src/llvm-project/clang/lib/Driver/ToolChains/Clang.h
index a607e3c..d4b4988 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Clang.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Clang.h
@@ -88,10 +88,6 @@
codegenoptions::DebugInfoKind *DebugInfoKind,
bool *EmitCodeView) const;
- visualstudio::Compiler *getCLFallback() const;
-
- mutable std::unique_ptr<visualstudio::Compiler> CLFallback;
-
mutable std::unique_ptr<llvm::raw_fd_ostream> CompilationDatabase = nullptr;
void DumpCompilationDatabase(Compilation &C, StringRef Filename,
StringRef Target,
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp
index 3efca87..9ee46ac 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp
@@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===//
#include "CloudABI.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Option/ArgList.h"
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp
index bcaea71..83cab3a 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -9,6 +9,7 @@
#include "CommonArgs.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
+#include "Arch/M68k.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
#include "Arch/SystemZ.h"
@@ -16,7 +17,6 @@
#include "Arch/X86.h"
#include "HIP.h"
#include "Hexagon.h"
-#include "InputInfo.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
@@ -26,6 +26,7 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
@@ -372,6 +373,9 @@
return A->getValue();
return "";
+ case llvm::Triple::m68k:
+ return m68k::getM68kTargetCPU(Args);
+
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -399,9 +403,14 @@
if (!TargetCPUName.empty())
return TargetCPUName;
- if (T.isOSAIX())
- TargetCPUName = "pwr4";
- else if (T.getArch() == llvm::Triple::ppc64le)
+ if (T.isOSAIX()) {
+ unsigned major, minor, unused_micro;
+ T.getOSVersion(major, minor, unused_micro);
+ // The minimal arch level moved from pwr4 for AIX7.1 to
+ // pwr7 for AIX7.2.
+ TargetCPUName =
+ (major < 7 || (major == 7 && minor < 2)) ? "pwr4" : "pwr7";
+ } else if (T.getArch() == llvm::Triple::ppc64le)
TargetCPUName = "ppc64le";
else if (T.getArch() == llvm::Triple::ppc64)
TargetCPUName = "ppc64";
@@ -541,6 +550,8 @@
CmdArgs.push_back("-plugin-opt=-debugger-tune=lldb");
else if (A->getOption().matches(options::OPT_gsce))
CmdArgs.push_back("-plugin-opt=-debugger-tune=sce");
+ else if (A->getOption().matches(options::OPT_gdbx))
+ CmdArgs.push_back("-plugin-opt=-debugger-tune=dbx");
else
CmdArgs.push_back("-plugin-opt=-debugger-tune=gdb");
}
@@ -718,11 +729,6 @@
// the option, so don't try to pass it.
if (TC.getTriple().getOS() == llvm::Triple::Solaris)
return true;
- // Myriad is static linking only. Furthermore, some versions of its
- // linker have the bug where --export-dynamic overrides -static, so
- // don't use --export-dynamic on that platform.
- if (TC.getTriple().getVendor() == llvm::Triple::Myriad)
- return true;
SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
if (llvm::sys::fs::exists(SanRT + ".syms")) {
CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
@@ -732,6 +738,9 @@
}
static const char *getAsNeededOption(const ToolChain &TC, bool as_needed) {
+ assert(!TC.getTriple().isOSAIX() &&
+ "AIX linker does not support any form of --as-needed option yet.");
+
// While the Solaris 11.2 ld added --as-needed/--no-as-needed as aliases
// for the native forms -z ignore/-z record, they are missing in Illumos,
// so always use the native form.
@@ -760,10 +769,9 @@
}
CmdArgs.push_back("-lm");
// There's no libdl on all OSes.
- if (!TC.getTriple().isOSFreeBSD() &&
- !TC.getTriple().isOSNetBSD() &&
+ if (!TC.getTriple().isOSFreeBSD() && !TC.getTriple().isOSNetBSD() &&
!TC.getTriple().isOSOpenBSD() &&
- TC.getTriple().getOS() != llvm::Triple::RTEMS)
+ TC.getTriple().getOS() != llvm::Triple::RTEMS)
CmdArgs.push_back("-ldl");
// Required for backtrace on some OSes
if (TC.getTriple().isOSFreeBSD() ||
@@ -805,8 +813,12 @@
}
if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes())
SharedRuntimes.push_back("tsan");
- if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes())
- SharedRuntimes.push_back("hwasan");
+ if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
+ if (SanArgs.needsHwasanAliasesRt())
+ SharedRuntimes.push_back("hwasan_aliases");
+ else
+ SharedRuntimes.push_back("hwasan");
+ }
}
// The stats_client library is also statically linked into DSOs.
@@ -836,9 +848,15 @@
}
if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
- StaticRuntimes.push_back("hwasan");
- if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("hwasan_cxx");
+ if (SanArgs.needsHwasanAliasesRt()) {
+ StaticRuntimes.push_back("hwasan_aliases");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("hwasan_aliases_cxx");
+ } else {
+ StaticRuntimes.push_back("hwasan");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("hwasan_cxx");
+ }
}
if (SanArgs.needsDfsanRt() && SanArgs.linkRuntimes())
StaticRuntimes.push_back("dfsan");
@@ -1010,12 +1028,13 @@
return Args.MakeArgString(T);
} else {
// Use the compilation dir.
- SmallString<128> T(
- Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
+ Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
+ options::OPT_fdebug_compilation_dir_EQ);
+ SmallString<128> T(A ? A->getValue() : "");
SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
AddPostfix(F);
T += F;
- return Args.MakeArgString(F);
+ return Args.MakeArgString(T);
}
}
@@ -1366,11 +1385,19 @@
enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc };
-static LibGccType getLibGccType(const Driver &D, const ArgList &Args) {
+static LibGccType getLibGccType(const ToolChain &TC, const Driver &D,
+ const ArgList &Args) {
if (Args.hasArg(options::OPT_static_libgcc) ||
Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie))
return LibGccType::StaticLibGcc;
- if (Args.hasArg(options::OPT_shared_libgcc) || D.CCCIsCXX())
+ if (Args.hasArg(options::OPT_shared_libgcc))
+ return LibGccType::SharedLibGcc;
+ // The Android NDK only provides libunwind.a, not libunwind.so.
+ if (TC.getTriple().isAndroid())
+ return LibGccType::StaticLibGcc;
+ // For MinGW, don't imply a shared libgcc here, we only want to return
+ // SharedLibGcc if that was explicitly requested.
+ if (D.CCCIsCXX() && !TC.getTriple().isOSCygMing())
return LibGccType::SharedLibGcc;
return LibGccType::UnspecifiedLibGcc;
}
@@ -1392,14 +1419,15 @@
ArgStringList &CmdArgs, const ArgList &Args) {
ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args);
// Targets that don't use unwind libraries.
- if (TC.getTriple().isAndroid() || TC.getTriple().isOSIAMCU() ||
- TC.getTriple().isOSBinFormatWasm() ||
+ if ((TC.getTriple().isAndroid() && UNW == ToolChain::UNW_Libgcc) ||
+ TC.getTriple().isOSIAMCU() || TC.getTriple().isOSBinFormatWasm() ||
UNW == ToolChain::UNW_None)
return;
- LibGccType LGT = getLibGccType(D, Args);
+ LibGccType LGT = getLibGccType(TC, D, Args);
bool AsNeeded = LGT == LibGccType::UnspecifiedLibGcc &&
- !TC.getTriple().isAndroid() && !TC.getTriple().isOSCygMing();
+ !TC.getTriple().isAndroid() &&
+ !TC.getTriple().isOSCygMing() && !TC.getTriple().isOSAIX();
if (AsNeeded)
CmdArgs.push_back(getAsNeededOption(TC, true));
@@ -1414,17 +1442,23 @@
break;
}
case ToolChain::UNW_CompilerRT:
- if (LGT == LibGccType::StaticLibGcc)
+ if (TC.getTriple().isOSAIX()) {
+ // AIX only has libunwind as a shared library. So do not pass
+ // anything in if -static is specified.
+ if (LGT != LibGccType::StaticLibGcc)
+ CmdArgs.push_back("-lunwind");
+ } else if (LGT == LibGccType::StaticLibGcc) {
CmdArgs.push_back("-l:libunwind.a");
- else if (TC.getTriple().isOSCygMing()) {
+ } else if (TC.getTriple().isOSCygMing()) {
if (LGT == LibGccType::SharedLibGcc)
CmdArgs.push_back("-l:libunwind.dll.a");
else
// Let the linker choose between libunwind.dll.a and libunwind.a
// depending on what's available, and depending on the -static flag
CmdArgs.push_back("-lunwind");
- } else
+ } else {
CmdArgs.push_back("-l:libunwind.so");
+ }
break;
}
@@ -1434,20 +1468,12 @@
static void AddLibgcc(const ToolChain &TC, const Driver &D,
ArgStringList &CmdArgs, const ArgList &Args) {
- LibGccType LGT = getLibGccType(D, Args);
+ LibGccType LGT = getLibGccType(TC, D, Args);
if (LGT != LibGccType::SharedLibGcc)
CmdArgs.push_back("-lgcc");
AddUnwindLibrary(TC, D, CmdArgs, Args);
if (LGT == LibGccType::SharedLibGcc)
CmdArgs.push_back("-lgcc");
-
- // According to Android ABI, we have to link with libdl if we are
- // linking with non-static libgcc.
- //
- // NOTE: This fixes a link error on Android MIPS as well. The non-static
- // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl.
- if (TC.getTriple().isAndroid() && LGT != LibGccType::StaticLibGcc)
- CmdArgs.push_back("-ldl");
}
void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
@@ -1473,6 +1499,13 @@
AddLibgcc(TC, D, CmdArgs, Args);
break;
}
+
+ // On Android, the unwinder uses dl_iterate_phdr (or one of
+ // dl_unwind_find_exidx/__gnu_Unwind_Find_exidx on arm32) from libdl.so. For
+ // statically-linked executables, these functions come from libc.a instead.
+ if (TC.getTriple().isAndroid() && !Args.hasArg(options::OPT_static) &&
+ !Args.hasArg(options::OPT_static_pie))
+ CmdArgs.push_back("-ldl");
}
SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args,
@@ -1554,29 +1587,46 @@
}
}
-unsigned tools::getOrCheckAMDGPUCodeObjectVersion(
- const Driver &D, const llvm::opt::ArgList &Args, bool Diagnose) {
- const unsigned MinCodeObjVer = 2;
- const unsigned MaxCodeObjVer = 4;
- unsigned CodeObjVer = 3;
-
- // Emit warnings for legacy options even if they are overridden.
- if (Diagnose) {
- if (Args.hasArg(options::OPT_mno_code_object_v3_legacy))
- D.Diag(diag::warn_drv_deprecated_arg) << "-mno-code-object-v3"
- << "-mcode-object-version=2";
-
- if (Args.hasArg(options::OPT_mcode_object_v3_legacy))
- D.Diag(diag::warn_drv_deprecated_arg) << "-mcode-object-v3"
- << "-mcode-object-version=3";
- }
-
+static llvm::opt::Arg *
+getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) {
// The last of -mcode-object-v3, -mno-code-object-v3 and
// -mcode-object-version=<version> wins.
- if (auto *CodeObjArg =
- Args.getLastArg(options::OPT_mcode_object_v3_legacy,
- options::OPT_mno_code_object_v3_legacy,
- options::OPT_mcode_object_version_EQ)) {
+ return Args.getLastArg(options::OPT_mcode_object_v3_legacy,
+ options::OPT_mno_code_object_v3_legacy,
+ options::OPT_mcode_object_version_EQ);
+}
+
+void tools::checkAMDGPUCodeObjectVersion(const Driver &D,
+ const llvm::opt::ArgList &Args) {
+ const unsigned MinCodeObjVer = 2;
+ const unsigned MaxCodeObjVer = 4;
+
+ // Emit warnings for legacy options even if they are overridden.
+ if (Args.hasArg(options::OPT_mno_code_object_v3_legacy))
+ D.Diag(diag::warn_drv_deprecated_arg) << "-mno-code-object-v3"
+ << "-mcode-object-version=2";
+
+ if (Args.hasArg(options::OPT_mcode_object_v3_legacy))
+ D.Diag(diag::warn_drv_deprecated_arg) << "-mcode-object-v3"
+ << "-mcode-object-version=3";
+
+ if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) {
+ if (CodeObjArg->getOption().getID() ==
+ options::OPT_mcode_object_version_EQ) {
+ unsigned CodeObjVer = MaxCodeObjVer;
+ auto Remnant =
+ StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
+ if (Remnant || CodeObjVer < MinCodeObjVer || CodeObjVer > MaxCodeObjVer)
+ D.Diag(diag::err_drv_invalid_int_value)
+ << CodeObjArg->getAsString(Args) << CodeObjArg->getValue();
+ }
+ }
+}
+
+unsigned tools::getAMDGPUCodeObjectVersion(const Driver &D,
+ const llvm::opt::ArgList &Args) {
+ unsigned CodeObjVer = 4; // default
+ if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) {
if (CodeObjArg->getOption().getID() ==
options::OPT_mno_code_object_v3_legacy) {
CodeObjVer = 2;
@@ -1584,17 +1634,17 @@
options::OPT_mcode_object_v3_legacy) {
CodeObjVer = 3;
} else {
- auto Remnant =
- StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
- if (Diagnose &&
- (Remnant || CodeObjVer < MinCodeObjVer || CodeObjVer > MaxCodeObjVer))
- D.Diag(diag::err_drv_invalid_int_value)
- << CodeObjArg->getAsString(Args) << CodeObjArg->getValue();
+ StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
}
}
return CodeObjVer;
}
+bool tools::haveAMDGPUCodeObjectVersionArgument(
+ const Driver &D, const llvm::opt::ArgList &Args) {
+ return getAMDGPUCodeObjectArgument(D, Args) != nullptr;
+}
+
void tools::addMachineOutlinerArgs(const Driver &D,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
@@ -1627,3 +1677,63 @@
}
}
}
+
+void tools::addOpenMPDeviceRTL(const Driver &D,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ StringRef BitcodeSuffix,
+ const llvm::Triple &Triple) {
+ SmallVector<StringRef, 8> LibraryPaths;
+ // Add user defined library paths from LIBRARY_PATH.
+ llvm::Optional<std::string> LibPath =
+ llvm::sys::Process::GetEnv("LIBRARY_PATH");
+ if (LibPath) {
+ SmallVector<StringRef, 8> Frags;
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
+ llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
+ for (StringRef Path : Frags)
+ LibraryPaths.emplace_back(Path.trim());
+ }
+
+ // Add path to lib / lib64 folder.
+ SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
+ llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
+ LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
+ OptSpecifier LibomptargetBCPathOpt =
+ Triple.isAMDGCN() ? options::OPT_libomptarget_amdgcn_bc_path_EQ
+ : options::OPT_libomptarget_nvptx_bc_path_EQ;
+
+ StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgcn" : "nvptx";
+ // First check whether user specifies bc library
+ if (const Arg *A = DriverArgs.getLastArg(LibomptargetBCPathOpt)) {
+ std::string LibOmpTargetName(A->getValue());
+ if (llvm::sys::fs::exists(LibOmpTargetName)) {
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetName));
+ } else {
+ D.Diag(diag::err_drv_omp_offload_target_bcruntime_not_found)
+ << LibOmpTargetName;
+ }
+ } else {
+ bool FoundBCLibrary = false;
+
+ std::string LibOmpTargetName =
+ "libomptarget-" + BitcodeSuffix.str() + ".bc";
+
+ for (StringRef LibraryPath : LibraryPaths) {
+ SmallString<128> LibOmpTargetFile(LibraryPath);
+ llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
+ if (llvm::sys::fs::exists(LibOmpTargetFile)) {
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
+ FoundBCLibrary = true;
+ break;
+ }
+ }
+
+ if (!FoundBCLibrary)
+ D.Diag(diag::err_drv_omp_offload_target_missingbcruntime)
+ << LibOmpTargetName << ArchPrefix;
+ }
+}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h b/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h
index 187c340..c94c158 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -9,8 +9,8 @@
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_COMMONARGS_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_COMMONARGS_H
-#include "InputInfo.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
@@ -138,13 +138,22 @@
void addX86AlignBranchArgs(const Driver &D, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs, bool IsLTO);
-unsigned getOrCheckAMDGPUCodeObjectVersion(const Driver &D,
- const llvm::opt::ArgList &Args,
- bool Diagnose = false);
+void checkAMDGPUCodeObjectVersion(const Driver &D,
+ const llvm::opt::ArgList &Args);
+
+unsigned getAMDGPUCodeObjectVersion(const Driver &D,
+ const llvm::opt::ArgList &Args);
+
+bool haveAMDGPUCodeObjectVersionArgument(const Driver &D,
+ const llvm::opt::ArgList &Args);
void addMachineOutlinerArgs(const Driver &D, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
const llvm::Triple &Triple, bool IsLTO);
+
+void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ StringRef BitcodeSuffix, const llvm::Triple &Triple);
} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp
index d14776c..769eae1 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -8,13 +8,13 @@
#include "Cuda.h"
#include "CommonArgs.h"
-#include "InputInfo.h"
#include "clang/Basic/Cuda.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Distro.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Option/ArgList.h"
@@ -75,6 +75,8 @@
return CudaVersion::CUDA_102;
if (raw_version < 11010)
return CudaVersion::CUDA_110;
+ if (raw_version < 11020)
+ return CudaVersion::CUDA_111;
return CudaVersion::LATEST;
}
@@ -689,22 +691,17 @@
if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
-
- if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
- false))
- CC1Args.push_back("-fgpu-rdc");
}
if (DriverArgs.hasArg(options::OPT_nogpulib))
return;
+ if (DeviceOffloadingKind == Action::OFK_OpenMP &&
+ DriverArgs.hasArg(options::OPT_S))
+ return;
+
std::string LibDeviceFile = CudaInstallation.getLibDeviceFile(GpuArch);
-
if (LibDeviceFile.empty()) {
- if (DeviceOffloadingKind == Action::OFK_OpenMP &&
- DriverArgs.hasArg(options::OPT_S))
- return;
-
getDriver().Diag(diag::err_drv_no_cuda_libdevice) << GpuArch;
return;
}
@@ -712,18 +709,19 @@
CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
- std::string CudaVersionStr;
+ clang::CudaVersion CudaInstallationVersion = CudaInstallation.version();
// New CUDA versions often introduce new instructions that are only supported
// by new PTX version, so we need to raise PTX level to enable them in NVPTX
// back-end.
const char *PtxFeature = nullptr;
- switch (CudaInstallation.version()) {
+ switch (CudaInstallationVersion) {
#define CASE_CUDA_VERSION(CUDA_VER, PTX_VER) \
case CudaVersion::CUDA_##CUDA_VER: \
- CudaVersionStr = #CUDA_VER; \
PtxFeature = "+ptx" #PTX_VER; \
break;
+ CASE_CUDA_VERSION(112, 72);
+ CASE_CUDA_VERSION(111, 71);
CASE_CUDA_VERSION(110, 70);
CASE_CUDA_VERSION(102, 65);
CASE_CUDA_VERSION(101, 64);
@@ -733,9 +731,6 @@
CASE_CUDA_VERSION(90, 60);
#undef CASE_CUDA_VERSION
default:
- // If unknown CUDA version, we take it as CUDA 8.0. Same assumption is also
- // made in libomptarget/deviceRTLs.
- CudaVersionStr = "80";
PtxFeature = "+ptx42";
}
CC1Args.append({"-target-feature", PtxFeature});
@@ -743,62 +738,28 @@
options::OPT_fno_cuda_short_ptr, false))
CC1Args.append({"-mllvm", "--nvptx-short-ptr"});
- if (CudaInstallation.version() >= CudaVersion::UNKNOWN)
- CC1Args.push_back(DriverArgs.MakeArgString(
- Twine("-target-sdk-version=") +
- CudaVersionToString(CudaInstallation.version())));
+ if (CudaInstallationVersion >= CudaVersion::UNKNOWN)
+ CC1Args.push_back(
+ DriverArgs.MakeArgString(Twine("-target-sdk-version=") +
+ CudaVersionToString(CudaInstallationVersion)));
if (DeviceOffloadingKind == Action::OFK_OpenMP) {
- SmallVector<StringRef, 8> LibraryPaths;
- // Add user defined library paths from LIBRARY_PATH.
- llvm::Optional<std::string> LibPath =
- llvm::sys::Process::GetEnv("LIBRARY_PATH");
- if (LibPath) {
- SmallVector<StringRef, 8> Frags;
- const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
- llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
- for (StringRef Path : Frags)
- LibraryPaths.emplace_back(Path.trim());
+ if (CudaInstallationVersion < CudaVersion::CUDA_92) {
+ getDriver().Diag(
+ diag::err_drv_omp_offload_target_cuda_version_not_support)
+ << CudaVersionToString(CudaInstallationVersion);
+ return;
}
- // Add path to lib / lib64 folder.
- SmallString<256> DefaultLibPath =
- llvm::sys::path::parent_path(getDriver().Dir);
- llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
- LibraryPaths.emplace_back(DefaultLibPath.c_str());
+ std::string BitcodeSuffix;
+ if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
+ options::OPT_fno_openmp_target_new_runtime, false))
+ BitcodeSuffix = "new-nvptx-" + GpuArch.str();
+ else
+ BitcodeSuffix = "nvptx-" + GpuArch.str();
- // First check whether user specifies bc library
- if (const Arg *A =
- DriverArgs.getLastArg(options::OPT_libomptarget_nvptx_bc_path_EQ)) {
- std::string LibOmpTargetName(A->getValue());
- if (llvm::sys::fs::exists(LibOmpTargetName)) {
- CC1Args.push_back("-mlink-builtin-bitcode");
- CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetName));
- } else {
- getDriver().Diag(diag::err_drv_omp_offload_target_bcruntime_not_found)
- << LibOmpTargetName;
- }
- } else {
- bool FoundBCLibrary = false;
-
- std::string LibOmpTargetName = "libomptarget-nvptx-cuda_" +
- CudaVersionStr + "-" + GpuArch.str() +
- ".bc";
-
- for (StringRef LibraryPath : LibraryPaths) {
- SmallString<128> LibOmpTargetFile(LibraryPath);
- llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
- if (llvm::sys::fs::exists(LibOmpTargetFile)) {
- CC1Args.push_back("-mlink-builtin-bitcode");
- CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
- FoundBCLibrary = true;
- break;
- }
- }
- if (!FoundBCLibrary)
- getDriver().Diag(diag::err_drv_omp_offload_target_missingbcruntime)
- << LibOmpTargetName;
- }
+ addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix,
+ getTriple());
}
}
@@ -807,9 +768,8 @@
const llvm::fltSemantics *FPType) const {
if (JA.getOffloadingDeviceKind() == Action::OFK_Cuda) {
if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
- DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
- options::OPT_fno_cuda_flush_denormals_to_zero,
- false))
+ DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
+ options::OPT_fno_gpu_flush_denormals_to_zero, false))
return llvm::DenormalMode::getPreserveSign();
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
index eb7bd4a..261f522 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -34,6 +34,10 @@
using namespace clang;
using namespace llvm::opt;
+static const VersionTuple minimumMacCatalystDeploymentTarget() {
+ return VersionTuple(13, 1);
+}
+
llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
// See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
// archs which Darwin doesn't use.
@@ -74,12 +78,12 @@
const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
T.setArch(Arch);
-
- if (Str == "x86_64h" || Str == "arm64e")
+ if (Arch != llvm::Triple::UnknownArch)
T.setArchName(Str);
- else if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
- ArchKind == llvm::ARM::ArchKind::ARMV7M ||
- ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
+
+ if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
+ ArchKind == llvm::ARM::ArchKind::ARMV7M ||
+ ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
T.setOS(llvm::Triple::UnknownOS);
T.setObjectFormat(llvm::Triple::MachO);
}
@@ -373,6 +377,18 @@
D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
}
+ // If GlobalISel is enabled, pass it through to LLVM.
+ if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
+ options::OPT_fno_global_isel)) {
+ if (A->getOption().matches(options::OPT_fglobal_isel)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-global-isel");
+ // Disable abort and fall back to SDAG silently.
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-global-isel-abort=0");
+ }
+ }
+
Args.AddLastArg(CmdArgs, options::OPT_prebind);
Args.AddLastArg(CmdArgs, options::OPT_noprebind);
Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
@@ -417,7 +433,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
- Args.AddLastArg(CmdArgs, options::OPT_whyload);
+ Args.AddLastArg(CmdArgs, options::OPT_why_load);
Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
Args.AddLastArg(CmdArgs, options::OPT_dylinker);
@@ -699,10 +715,7 @@
}
ResponseFileSupport ResponseSupport;
- if (LinkerIsLLDDarwinNew) {
- // Xcode12's ld64 added support for @response files, but it's crashy:
- // https://openradar.appspot.com/radar?id=4933317065441280
- // FIXME: Pass this for ld64 once it no longer crashes.
+ if (Version[0] >= 705 || LinkerIsLLDDarwinNew) {
ResponseSupport = ResponseFileSupport::AtFileUTF8();
} else {
// For older versions of the linker, use the legacy filelist method instead.
@@ -811,9 +824,9 @@
ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
// Default to use libc++ on OS X 10.9+ and iOS 7+.
- if ((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
- (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) ||
- isTargetWatchOSBased())
+ if ((isTargetMacOSBased() && !isMacosxVersionLT(10, 9)) ||
+ (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) ||
+ isTargetWatchOSBased())
return ToolChain::CST_Libcxx;
return ToolChain::CST_Libstdcxx;
@@ -837,7 +850,7 @@
else if (isTargetIOSBased())
return !isIPhoneOSVersionLT(3, 2);
else {
- assert(isTargetMacOS() && "unexpected darwin target");
+ assert(isTargetMacOSBased() && "unexpected darwin target");
return !isMacosxVersionLT(10, 6);
}
}
@@ -938,11 +951,11 @@
Str += "watchos";
else if (isTargetTvOSBased())
Str += "tvos";
- else if (isTargetIOSBased())
+ else if (isTargetIOSBased() || isTargetMacCatalyst())
Str += "ios";
else
Str += "macosx";
- Str += getTargetVersion().getAsString();
+ Str += getTripleTargetVersion().getAsString();
Triple.setOSName(Str);
return Triple.getTriple();
@@ -1011,7 +1024,7 @@
void DarwinClang::AddLinkARCArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Avoid linking compatibility stubs on i386 mac.
- if (isTargetMacOS() && getArch() == llvm::Triple::x86)
+ if (isTargetMacOSBased() && getArch() == llvm::Triple::x86)
return;
if (isTargetAppleSiliconMac())
return;
@@ -1069,7 +1082,7 @@
unsigned DarwinClang::GetDefaultDwarfVersion() const {
// Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
- if ((isTargetMacOS() && isMacosxVersionLT(10, 11)) ||
+ if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||
(isTargetIOSBased() && isIPhoneOSVersionLT(9)))
return 2;
return 4;
@@ -1100,10 +1113,7 @@
// we explicitly force linking with this library).
if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
const char *LibArg = Args.MakeArgString(P);
- if (Opts & RLO_FirstLink)
- CmdArgs.insert(CmdArgs.begin(), LibArg);
- else
- CmdArgs.push_back(LibArg);
+ CmdArgs.push_back(LibArg);
}
// Adding the rpaths might negatively interact when other rpaths are involved,
@@ -1130,6 +1140,8 @@
case DarwinPlatformKind::MacOS:
return "MacOSX";
case DarwinPlatformKind::IPhoneOS:
+ if (TargetEnvironment == MacCatalyst)
+ return "MacOSX";
return "iPhone";
case DarwinPlatformKind::TvOS:
return "AppleTV";
@@ -1156,6 +1168,8 @@
case DarwinPlatformKind::MacOS:
return "osx";
case DarwinPlatformKind::IPhoneOS:
+ if (TargetEnvironment == MacCatalyst)
+ return "osx";
return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
: "iossim";
case DarwinPlatformKind::TvOS:
@@ -1208,7 +1222,7 @@
return;
AddLinkRuntimeLib(Args, CmdArgs, "profile",
- RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
+ RuntimeLinkOptions(RLO_AlwaysLink));
bool ForGCOV = needsGCovInstrumentation(Args);
@@ -1400,6 +1414,12 @@
bool hasOSVersion() const { return HasOSVersion; }
+ VersionTuple getNativeTargetVersion() const {
+ assert(Environment == DarwinEnvironmentKind::MacCatalyst &&
+ "native target version is specified only for Mac Catalyst");
+ return NativeTargetVersion;
+ }
+
/// Returns true if the target OS was explicitly specified.
bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
@@ -1446,21 +1466,40 @@
llvm_unreachable("Unsupported Darwin Source Kind");
}
- static DarwinPlatform createFromTarget(const llvm::Triple &TT,
- StringRef OSVersion, Arg *A) {
+ static DarwinPlatform
+ createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
+ const Optional<DarwinSDKInfo> &SDKInfo) {
DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
A);
- switch (TT.getEnvironment()) {
- case llvm::Triple::Simulator:
- Result.Environment = DarwinEnvironmentKind::Simulator;
- break;
- default:
- break;
- }
unsigned Major, Minor, Micro;
TT.getOSVersion(Major, Minor, Micro);
if (Major == 0)
Result.HasOSVersion = false;
+
+ switch (TT.getEnvironment()) {
+ case llvm::Triple::Simulator:
+ Result.Environment = DarwinEnvironmentKind::Simulator;
+ break;
+ case llvm::Triple::MacABI: {
+ // The minimum native macOS target for MacCatalyst is macOS 10.15.
+ auto NativeTargetVersion = VersionTuple(10, 15);
+ if (Result.HasOSVersion && SDKInfo) {
+ if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
+ DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
+ if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
+ VersionTuple(Major, Minor, Micro), NativeTargetVersion,
+ None)) {
+ NativeTargetVersion = *MacOSVersion;
+ }
+ }
+ }
+ Result.Environment = DarwinEnvironmentKind::MacCatalyst;
+ Result.NativeTargetVersion = NativeTargetVersion;
+ break;
+ }
+ default:
+ break;
+ }
return Result;
}
static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
@@ -1497,7 +1536,9 @@
bool IsValid = !Version.tryParse(OSVersion);
(void)IsValid;
assert(IsValid && "invalid SDK version");
- return DarwinSDKInfo(Version);
+ return DarwinSDKInfo(
+ Version,
+ /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99));
}
private:
@@ -1526,6 +1567,7 @@
SourceKind Kind;
DarwinPlatformKind Platform;
DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
+ VersionTuple NativeTargetVersion;
std::string OSVersion;
bool HasOSVersion = true, InferSimulatorFromArch = true;
Arg *Argument;
@@ -1628,6 +1670,15 @@
return None;
}
+/// Returns the SDK name without the optional prefix that ends with a '.' or an
+/// empty string otherwise.
+static StringRef dropSDKNamePrefix(StringRef SDKName) {
+ size_t PrefixPos = SDKName.find('.');
+ if (PrefixPos == StringRef::npos)
+ return "";
+ return SDKName.substr(PrefixPos + 1);
+}
+
/// Tries to infer the deployment target from the SDK specified by -isysroot
/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
/// it's available.
@@ -1657,22 +1708,29 @@
if (Version.empty())
return None;
- if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::IPhoneOS, Version,
- /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
- else if (SDK.startswith("MacOSX"))
- return DarwinPlatform::createFromSDK(Darwin::MacOS,
- getSystemOrSDKMacOSVersion(Version));
- else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::WatchOS, Version,
- /*IsSimulator=*/SDK.startswith("WatchSimulator"));
- else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::TvOS, Version,
- /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
- return None;
+ auto CreatePlatformFromSDKName =
+ [&](StringRef SDK) -> Optional<DarwinPlatform> {
+ if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::IPhoneOS, Version,
+ /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
+ else if (SDK.startswith("MacOSX"))
+ return DarwinPlatform::createFromSDK(Darwin::MacOS,
+ getSystemOrSDKMacOSVersion(Version));
+ else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::WatchOS, Version,
+ /*IsSimulator=*/SDK.startswith("WatchSimulator"));
+ else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::TvOS, Version,
+ /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
+ return None;
+ };
+ if (auto Result = CreatePlatformFromSDKName(SDK))
+ return Result;
+ // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.
+ return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));
}
std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
@@ -1743,15 +1801,16 @@
/// Returns the deployment target that's specified using the -target option.
Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
- DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver) {
+ DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
+ const Optional<DarwinSDKInfo> &SDKInfo) {
if (!Args.hasArg(options::OPT_target))
return None;
if (Triple.getOS() == llvm::Triple::Darwin ||
Triple.getOS() == llvm::Triple::UnknownOS)
return None;
std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
- return DarwinPlatform::createFromTarget(Triple, OSVersion,
- Args.getLastArg(options::OPT_target));
+ return DarwinPlatform::createFromTarget(
+ Triple, OSVersion, Args.getLastArg(options::OPT_target), SDKInfo);
}
Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
@@ -1761,7 +1820,7 @@
if (!A)
return None;
StringRef isysroot = A->getValue();
- auto SDKInfoOrErr = driver::parseDarwinSDKInfo(VFS, isysroot);
+ auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);
if (!SDKInfoOrErr) {
llvm::consumeError(SDKInfoOrErr.takeError());
TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
@@ -1800,7 +1859,7 @@
// The OS and the version can be specified using the -target argument.
Optional<DarwinPlatform> OSTarget =
- getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver());
+ getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);
if (OSTarget) {
Optional<DarwinPlatform> OSVersionArgTarget =
getDeploymentTargetFromOSVersionArg(Args, getDriver());
@@ -1886,13 +1945,24 @@
getDriver().Diag(diag::err_drv_invalid_version_number)
<< OSTarget->getAsString(Args, Opts);
;
+ if (OSTarget->getEnvironment() == MacCatalyst &&
+ (Major < 13 || (Major == 13 && Minor < 1))) {
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << OSTarget->getAsString(Args, Opts);
+ Major = 13;
+ Minor = 1;
+ Micro = 0;
+ }
// For 32-bit targets, the deployment target for iOS has to be earlier than
// iOS 11.
if (getTriple().isArch32Bit() && Major >= 11) {
// If the deployment target is explicitly specified, print a diagnostic.
if (OSTarget->isExplicitlySpecified()) {
- getDriver().Diag(diag::warn_invalid_ios_deployment_target)
- << OSTarget->getAsString(Args, Opts);
+ if (OSTarget->getEnvironment() == MacCatalyst)
+ getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);
+ else
+ getDriver().Diag(diag::warn_invalid_ios_deployment_target)
+ << OSTarget->getAsString(Args, Opts);
// Otherwise, set it to 10.99.99.
} else {
Major = 10;
@@ -1921,14 +1991,18 @@
OSTarget->canInferSimulatorFromArch() && getTriple().isX86())
Environment = Simulator;
- setTarget(Platform, Environment, Major, Minor, Micro);
+ VersionTuple NativeTargetVersion;
+ if (Environment == MacCatalyst)
+ NativeTargetVersion = OSTarget->getNativeTargetVersion();
+ setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef SDK = getSDKName(A->getValue());
if (SDK.size() > 0) {
size_t StartVer = SDK.find_first_of("0123456789");
StringRef SDKName = SDK.slice(0, StartVer);
- if (!SDKName.startswith(getPlatformFamily()))
+ if (!SDKName.startswith(getPlatformFamily()) &&
+ !dropSDKNamePrefix(SDKName).startswith(getPlatformFamily()))
getDriver().Diag(diag::warn_incompatible_sysroot)
<< SDKName << getPlatformFamily();
}
@@ -2410,6 +2484,8 @@
bool Darwin::isAlignedAllocationUnavailable() const {
llvm::Triple::OSType OS;
+ if (isTargetMacCatalyst())
+ return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX);
switch (TargetPlatform) {
case MacOS: // Earlier than 10.13.
OS = llvm::Triple::MacOSX;
@@ -2441,10 +2517,24 @@
if (SDKInfo) {
/// Pass the SDK version to the compiler when the SDK information is
/// available.
- std::string Arg;
- llvm::raw_string_ostream OS(Arg);
- OS << "-target-sdk-version=" << SDKInfo->getVersion();
- CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
+ auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {
+ std::string Arg;
+ llvm::raw_string_ostream OS(Arg);
+ OS << "-target-sdk-version=" << V;
+ CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
+ };
+
+ if (isTargetMacCatalyst()) {
+ if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
+ DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
+ Optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
+ SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(), None);
+ EmitTargetSDKVersionArg(
+ SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
+ }
+ } else {
+ EmitTargetSDKVersionArg(SDKInfo->getVersion());
+ }
}
// Enable compatibility mode for NSItemProviderCompletionHandler in
@@ -2580,7 +2670,7 @@
void Darwin::addMinVersionArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- VersionTuple TargetVersion = getTargetVersion();
+ VersionTuple TargetVersion = getTripleTargetVersion();
if (isTargetWatchOS())
CmdArgs.push_back("-watchos_version_min");
@@ -2594,6 +2684,8 @@
CmdArgs.push_back("-ios_simulator_version_min");
else if (isTargetIOSBased())
CmdArgs.push_back("-iphoneos_version_min");
+ else if (isTargetMacCatalyst())
+ CmdArgs.push_back("-maccatalyst_version_min");
else {
assert(isTargetMacOS() && "unexpected target");
CmdArgs.push_back("-macosx_version_min");
@@ -2611,11 +2703,9 @@
case Darwin::MacOS:
return "macos";
case Darwin::IPhoneOS:
- if (Environment == Darwin::NativeEnvironment ||
- Environment == Darwin::Simulator)
- return "ios";
- // FIXME: Add macCatalyst support here ("\"mac catalyst\"").
- llvm_unreachable("macCatalyst isn't yet supported");
+ if (Environment == Darwin::MacCatalyst)
+ return "mac catalyst";
+ return "ios";
case Darwin::TvOS:
return "tvos";
case Darwin::WatchOS:
@@ -2633,17 +2723,44 @@
if (TargetEnvironment == Darwin::Simulator)
PlatformName += "-simulator";
CmdArgs.push_back(Args.MakeArgString(PlatformName));
- VersionTuple TargetVersion = getTargetVersion().withoutBuild();
+ VersionTuple TargetVersion = getTripleTargetVersion().withoutBuild();
VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
TargetVersion = MinTgtVers;
CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+
+ if (isTargetMacCatalyst()) {
+ // Mac Catalyst programs must use the appropriate iOS SDK version
+ // that corresponds to the macOS SDK version used for the compilation.
+ Optional<VersionTuple> iOSSDKVersion;
+ if (SDKInfo) {
+ if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
+ DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
+ iOSSDKVersion = MacOStoMacCatalystMapping->map(
+ SDKInfo->getVersion().withoutBuild(),
+ minimumMacCatalystDeploymentTarget(), None);
+ }
+ }
+ CmdArgs.push_back(Args.MakeArgString(
+ (iOSSDKVersion ? *iOSSDKVersion : minimumMacCatalystDeploymentTarget())
+ .getAsString()));
+ return;
+ }
+
if (SDKInfo) {
VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
} else {
- // Use a blank SDK version if it's not present.
- CmdArgs.push_back("0.0.0");
+ // Use an SDK version that's matching the deployment target if the SDK
+ // version is missing. This is preferred over an empty SDK version (0.0.0)
+ // as the system's runtime might expect the linked binary to contain a
+ // valid SDK version in order for the binary to work correctly. It's
+ // reasonable to use the deployment target version as a proxy for the
+ // SDK version because older SDKs don't guarantee support for deployment
+ // targets newer than the SDK versions, so that rules out using some
+ // predetermined older SDK version, which leaves the deployment target
+ // version as the only reasonable choice.
+ CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
}
}
@@ -2697,7 +2814,7 @@
CmdArgs.push_back("-no_new_main");
} else {
D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
- << D.isTargetMacOS();
+ << D.isTargetMacOSBased();
}
}
@@ -2750,7 +2867,7 @@
void Darwin::CheckObjCARC() const {
if (isTargetIOSBased() || isTargetWatchOSBased() ||
- (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
+ (isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))
return;
getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
}
@@ -2771,11 +2888,11 @@
// Prior to 10.9, macOS shipped a version of the C++ standard library without
// C++11 support. The same is true of iOS prior to version 5. These OS'es are
// incompatible with -fsanitize=vptr.
- if (!(isTargetMacOS() && isMacosxVersionLT(10, 9))
- && !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
+ if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) &&
+ !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
Res |= SanitizerKind::Vptr;
- if ((IsX86_64 || IsAArch64) && isTargetMacOS()) {
+ if ((IsX86_64 || IsAArch64) && isTargetMacOSBased()) {
Res |= SanitizerKind::Thread;
} else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
if (IsX86_64)
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Darwin.h b/src/llvm-project/clang/lib/Driver/ToolChains/Darwin.h
index 25c63fe..4de122c 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Darwin.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Darwin.h
@@ -11,8 +11,8 @@
#include "Cuda.h"
#include "ROCm.h"
+#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/LangOptions.h"
-#include "clang/Driver/DarwinSDKInfo.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/XRayArgs.h"
@@ -184,9 +184,6 @@
/// Emit rpaths for @executable_path as well as the resource directory.
RLO_AddRPath = 1 << 2,
-
- /// Link the library in before any others.
- RLO_FirstLink = 1 << 3,
};
/// Add a runtime library to the list of items to link.
@@ -284,13 +281,16 @@
enum DarwinEnvironmentKind {
NativeEnvironment,
Simulator,
+ MacCatalyst,
};
mutable DarwinPlatformKind TargetPlatform;
mutable DarwinEnvironmentKind TargetEnvironment;
- /// The OS version we are targeting.
+ /// The native OS version we are targeting.
mutable VersionTuple TargetVersion;
+ /// The OS version we are targeting as specified in the triple.
+ mutable VersionTuple OSTargetVersion;
/// The information about the darwin SDK that was used.
mutable Optional<DarwinSDKInfo> SDKInfo;
@@ -337,12 +337,14 @@
// FIXME: Eliminate these ...Target functions and derive separate tool chains
// for these targets and put version in constructor.
void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
- unsigned Major, unsigned Minor, unsigned Micro) const {
+ unsigned Major, unsigned Minor, unsigned Micro,
+ VersionTuple NativeTargetVersion) const {
// FIXME: For now, allow reinitialization as long as values don't
// change. This will go away when we move away from argument translation.
if (TargetInitialized && TargetPlatform == Platform &&
TargetEnvironment == Environment &&
- TargetVersion == VersionTuple(Major, Minor, Micro))
+ (Environment == MacCatalyst ? OSTargetVersion : TargetVersion) ==
+ VersionTuple(Major, Minor, Micro))
return;
assert(!TargetInitialized && "Target already initialized!");
@@ -352,6 +354,11 @@
TargetVersion = VersionTuple(Major, Minor, Micro);
if (Environment == Simulator)
const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
+ else if (Environment == MacCatalyst) {
+ const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::MacABI);
+ TargetVersion = NativeTargetVersion;
+ OSTargetVersion = VersionTuple(Major, Minor, Micro);
+ }
}
public:
@@ -402,6 +409,10 @@
return TargetPlatform == WatchOS;
}
+ bool isTargetMacCatalyst() const {
+ return TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst;
+ }
+
bool isTargetMacOS() const {
assert(TargetInitialized && "Target not initialized!");
return TargetPlatform == MacOS;
@@ -409,8 +420,7 @@
bool isTargetMacOSBased() const {
assert(TargetInitialized && "Target not initialized!");
- // FIXME (Alex L): Add remaining MacCatalyst suppport.
- return TargetPlatform == MacOS;
+ return TargetPlatform == MacOS || isTargetMacCatalyst();
}
bool isTargetAppleSiliconMac() const {
@@ -420,9 +430,13 @@
bool isTargetInitialized() const { return TargetInitialized; }
- VersionTuple getTargetVersion() const {
+ /// The version of the OS that's used by the OS specified in the target
+ /// triple. It might be different from the actual target OS on which the
+ /// program will run, e.g. MacCatalyst code runs on a macOS target, but its
+ /// target triple is iOS.
+ VersionTuple getTripleTargetVersion() const {
assert(TargetInitialized && "Target not initialized!");
- return TargetVersion;
+ return isTargetMacCatalyst() ? OSTargetVersion : TargetVersion;
}
bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,
@@ -436,7 +450,8 @@
/// supported macOS version, the deployment target version is compared to the
/// specifed version instead.
bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
- assert(isTargetMacOS() && getTriple().isMacOSX() &&
+ assert(isTargetMacOSBased() &&
+ (getTriple().isMacOSX() || getTriple().isMacCatalystEnvironment()) &&
"Unexpected call for non OS X target!");
// The effective triple might not be initialized yet, so construct a
// pseudo-effective triple to get the minimum supported OS version.
@@ -490,7 +505,7 @@
// This is only used with the non-fragile ABI and non-legacy dispatch.
// Mixed dispatch is used everywhere except OS X before 10.6.
- return !(isTargetMacOS() && isMacosxVersionLT(10, 6));
+ return !(isTargetMacOSBased() && isMacosxVersionLT(10, 6));
}
LangOptions::StackProtectorMode
@@ -499,9 +514,9 @@
// and for everything in 10.6 and beyond
if (isTargetIOSBased() || isTargetWatchOSBased())
return LangOptions::SSPOn;
- else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
+ else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 6))
return LangOptions::SSPOn;
- else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
+ else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
return LangOptions::SSPOn;
return LangOptions::SSPOff;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp
index 669d911..1bfad61 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp
@@ -19,9 +19,33 @@
using namespace clang;
using namespace llvm::opt;
+void Flang::AddFortranDialectOptions(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ Args.AddAllArgs(
+ CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
+ options::OPT_ffixed_line_length_EQ, options::OPT_fopenmp,
+ options::OPT_fopenacc, options::OPT_finput_charset_EQ,
+ options::OPT_fimplicit_none, options::OPT_fno_implicit_none,
+ options::OPT_fbackslash, options::OPT_fno_backslash,
+ options::OPT_flogical_abbreviations,
+ options::OPT_fno_logical_abbreviations,
+ options::OPT_fxor_operator, options::OPT_fno_xor_operator,
+ options::OPT_falternative_parameter_statement,
+ options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
+ options::OPT_fdefault_double_8, options::OPT_flarge_sizes});
+}
+
void Flang::AddPreprocessingOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
- Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});
+ Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I,
+ options::OPT_cpp, options::OPT_nocpp});
+}
+
+void Flang::AddOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_module_dir, options::OPT_fdebug_module_writer,
+ options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
+ options::OPT_std_EQ, options::OPT_W_Joined});
}
void Flang::ConstructJob(Compilation &C, const JobAction &JA,
@@ -45,9 +69,6 @@
// CmdArgs.push_back(Args.MakeArgString(TripleStr));
if (isa<PreprocessJobAction>(JA)) {
- if (C.getArgs().hasArg(options::OPT_test_io))
- CmdArgs.push_back("-test-io");
- else
CmdArgs.push_back("-E");
} else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
if (JA.getType() == types::TY_Nothing) {
@@ -79,6 +100,14 @@
if (types::getPreprocessedType(InputType) != types::TY_INVALID)
AddPreprocessingOptions(Args, CmdArgs);
+ AddFortranDialectOptions(Args, CmdArgs);
+
+ // Add other compile options
+ AddOtherOptions(Args, CmdArgs);
+
+ // Forward -Xflang arguments to -fc1
+ Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);
+
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Flang.h b/src/llvm-project/clang/lib/Driver/ToolChains/Flang.h
index 83b7950..efbdbe8 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Flang.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Flang.h
@@ -24,6 +24,14 @@
/// Flang compiler tool.
class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
private:
+ /// Extract fortran dialect options from the driver arguments and add them to
+ /// the list of arguments for the generated command/job.
+ ///
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void AddFortranDialectOptions(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
/// Extract preprocessing options from the driver arguments and add them to
/// the preprocessor command arguments.
///
@@ -31,6 +39,13 @@
/// \param [out] CmdArgs The list of output command arguments
void AddPreprocessingOptions(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ /// Extract other compilation options from the driver arguments and add them
+ /// to the command arguments.
+ ///
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void AddOtherOptions(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
public:
Flang(const ToolChain &TC);
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 4524d9b..5dcf74d 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -290,8 +290,11 @@
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
+ addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+ bool Profiling = Args.hasArg(options::OPT_pg) &&
+ ToolChain.getTriple().getOSMajorVersion() < 14;
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
@@ -301,7 +304,7 @@
if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (Args.hasArg(options::OPT_pg))
+ if (Profiling)
CmdArgs.push_back("-lm_p");
else
CmdArgs.push_back("-lm");
@@ -312,13 +315,13 @@
linkXRayRuntimeDeps(ToolChain, CmdArgs);
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
// the default system libraries. Just mimic this for now.
- if (Args.hasArg(options::OPT_pg))
+ if (Profiling)
CmdArgs.push_back("-lgcc_p");
else
CmdArgs.push_back("-lgcc");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-lgcc_eh");
- } else if (Args.hasArg(options::OPT_pg)) {
+ } else if (Profiling) {
CmdArgs.push_back("-lgcc_eh_p");
} else {
CmdArgs.push_back("--as-needed");
@@ -327,13 +330,13 @@
}
if (Args.hasArg(options::OPT_pthread)) {
- if (Args.hasArg(options::OPT_pg))
+ if (Profiling)
CmdArgs.push_back("-lpthread_p");
else
CmdArgs.push_back("-lpthread");
}
- if (Args.hasArg(options::OPT_pg)) {
+ if (Profiling) {
if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-lc");
else
@@ -346,7 +349,7 @@
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-lgcc_eh");
- } else if (Args.hasArg(options::OPT_pg)) {
+ } else if (Profiling) {
CmdArgs.push_back("-lgcc_eh_p");
} else {
CmdArgs.push_back("--as-needed");
@@ -408,14 +411,15 @@
void FreeBSD::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/c++/4.2", "", "",
- "", "", DriverArgs, CC1Args);
+ addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/c++/4.2", "", "",
+ DriverArgs, CC1Args);
}
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
- bool Profiling = Args.hasArg(options::OPT_pg);
+ bool Profiling =
+ Args.hasArg(options::OPT_pg) && getTriple().getOSMajorVersion() < 14;
switch (Type) {
case ToolChain::CST_Libcxx:
@@ -466,6 +470,7 @@
bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
SanitizerMask FreeBSD::getSupportedSanitizers() const {
+ const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
const bool IsMIPS64 = getTriple().isMIPS64();
@@ -484,8 +489,13 @@
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
}
- if (IsX86_64)
+ if (IsAArch64 || IsX86_64) {
+ Res |= SanitizerKind::KernelAddress;
+ Res |= SanitizerKind::KernelMemory;
+ }
+ if (IsX86_64) {
Res |= SanitizerKind::Memory;
+ }
return Res;
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 8e08601..fd9804a 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -54,8 +54,8 @@
CmdArgs.push_back("now");
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- if (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
- llvm::sys::path::stem(Exec).equals_lower("ld.lld")) {
+ if (llvm::sys::path::filename(Exec).equals_insensitive("ld.lld") ||
+ llvm::sys::path::stem(Exec).equals_insensitive("ld.lld")) {
CmdArgs.push_back("-z");
CmdArgs.push_back("rodynamic");
CmdArgs.push_back("-z");
@@ -95,6 +95,8 @@
std::string Dyld = D.DyldPrefix;
if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt())
Dyld += "asan/";
+ if (SanArgs.needsHwasanRt() && SanArgs.needsSharedRt())
+ Dyld += "hwasan/";
if (SanArgs.needsTsanRt() && SanArgs.needsSharedRt())
Dyld += "tsan/";
Dyld += "ld.so.1";
@@ -187,13 +189,9 @@
auto FilePaths = [&](const Multilib &M) -> std::vector<std::string> {
std::vector<std::string> FP;
- if (D.CCCIsCXX()) {
- if (auto CXXStdlibPath = getCXXStdlibPath()) {
- SmallString<128> P(*CXXStdlibPath);
- llvm::sys::path::append(P, M.gccSuffix());
- FP.push_back(std::string(P.str()));
- }
- }
+ SmallString<128> P(getStdlibPath());
+ llvm::sys::path::append(P, M.gccSuffix());
+ FP.push_back(std::string(P.str()));
return FP;
};
@@ -210,23 +208,43 @@
.flag("+fsanitize=address")
.flag("-fexceptions")
.flag("+fno-exceptions"));
+ // HWASan has higher priority because we always want the instrumentated
+ // version.
+ Multilibs.push_back(
+ Multilib("hwasan", {}, {}, 4).flag("+fsanitize=hwaddress"));
+ // Use the hwasan+noexcept variant with HWASan and -fno-exceptions.
+ Multilibs.push_back(Multilib("hwasan+noexcept", {}, {}, 5)
+ .flag("+fsanitize=hwaddress")
+ .flag("-fexceptions")
+ .flag("+fno-exceptions"));
// Use the relative vtables ABI.
// TODO: Remove these multilibs once relative vtables are enabled by default
// for Fuchsia.
- Multilibs.push_back(Multilib("relative-vtables", {}, {}, 4)
+ Multilibs.push_back(Multilib("relative-vtables", {}, {}, 6)
.flag("+fexperimental-relative-c++-abi-vtables"));
- Multilibs.push_back(Multilib("relative-vtables+noexcept", {}, {}, 5)
+ Multilibs.push_back(Multilib("relative-vtables+noexcept", {}, {}, 7)
.flag("+fexperimental-relative-c++-abi-vtables")
.flag("-fexceptions")
.flag("+fno-exceptions"));
- Multilibs.push_back(Multilib("relative-vtables+asan", {}, {}, 6)
+ Multilibs.push_back(Multilib("relative-vtables+asan", {}, {}, 8)
.flag("+fexperimental-relative-c++-abi-vtables")
.flag("+fsanitize=address"));
- Multilibs.push_back(Multilib("relative-vtables+asan+noexcept", {}, {}, 7)
+ Multilibs.push_back(Multilib("relative-vtables+asan+noexcept", {}, {}, 9)
.flag("+fexperimental-relative-c++-abi-vtables")
.flag("+fsanitize=address")
.flag("-fexceptions")
.flag("+fno-exceptions"));
+ Multilibs.push_back(Multilib("relative-vtables+hwasan", {}, {}, 10)
+ .flag("+fexperimental-relative-c++-abi-vtables")
+ .flag("+fsanitize=hwaddress"));
+ Multilibs.push_back(Multilib("relative-vtables+hwasan+noexcept", {}, {}, 11)
+ .flag("+fexperimental-relative-c++-abi-vtables")
+ .flag("+fsanitize=hwaddress")
+ .flag("-fexceptions")
+ .flag("+fno-exceptions"));
+ // Use Itanium C++ ABI for the compat multilib.
+ Multilibs.push_back(Multilib("compat", {}, {}, 12).flag("+fc++-abi=itanium"));
+
Multilibs.FilterOut([&](const Multilib &M) {
std::vector<std::string> RD = FilePaths(M);
return std::all_of(RD.begin(), RD.end(), [&](std::string P) {
@@ -239,12 +257,16 @@
Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true),
"fexceptions", Flags);
addMultilibFlag(getSanitizerArgs().needsAsanRt(), "fsanitize=address", Flags);
+ addMultilibFlag(getSanitizerArgs().needsHwasanRt(), "fsanitize=hwaddress",
+ Flags);
addMultilibFlag(
Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
options::OPT_fno_experimental_relative_cxx_abi_vtables,
/*default=*/false),
"fexperimental-relative-c++-abi-vtables", Flags);
+ addMultilibFlag(Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium",
+ "fc++-abi=itanium", Flags);
Multilibs.setFilePathsCallback(FilePaths);
@@ -340,11 +362,31 @@
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
+ const Driver &D = getDriver();
+ std::string Target = getTripleString();
+
+ auto AddCXXIncludePath = [&](StringRef Path) {
+ std::string Version = detectLibcxxVersion(Path);
+ if (Version.empty())
+ return;
+
+ // First add the per-target include path.
+ SmallString<128> TargetDir(Path);
+ llvm::sys::path::append(TargetDir, Target, "c++", Version);
+ if (getVFS().exists(TargetDir))
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+
+ // Second add the generic one.
+ SmallString<128> Dir(Path);
+ llvm::sys::path::append(Dir, "c++", Version);
+ addSystemInclude(DriverArgs, CC1Args, Dir);
+ };
+
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx: {
- SmallString<128> P(getDriver().Dir);
- llvm::sys::path::append(P, "..", "include", "c++", "v1");
- addSystemInclude(DriverArgs, CC1Args, P.str());
+ SmallString<128> P(D.Dir);
+ llvm::sys::path::append(P, "..", "include");
+ AddCXXIncludePath(P);
break;
}
@@ -368,6 +410,7 @@
SanitizerMask Fuchsia::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::HWAddress;
Res |= SanitizerKind::PointerCompare;
Res |= SanitizerKind::PointerSubtract;
Res |= SanitizerKind::Fuzzer;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
index 1d8a3cd..da39f29 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -51,9 +51,9 @@
ArgStringList &CmdArgs) {
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
StringRef CPUArg(A->getValue());
- if (CPUArg.equals_lower("krait"))
+ if (CPUArg.equals_insensitive("krait"))
CmdArgs.push_back("-mcpu=cortex-a15");
- else if(CPUArg.equals_lower("kryo"))
+ else if (CPUArg.equals_insensitive("kryo"))
CmdArgs.push_back("-mcpu=cortex-a57");
else
Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
@@ -254,6 +254,8 @@
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
return isArmBigEndian(T, Args) ? "armelfb_linux_eabi" : "armelf_linux_eabi";
+ case llvm::Triple::m68k:
+ return "m68kelf";
case llvm::Triple::ppc:
if (T.isOSLinux())
return "elf32ppclinux";
@@ -292,7 +294,7 @@
case llvm::Triple::systemz:
return "elf64_s390";
case llvm::Triple::x86_64:
- if (T.getEnvironment() == llvm::Triple::GNUX32)
+ if (T.isX32())
return "elf32_x86_64";
return "elf_x86_64";
case llvm::Triple::ve:
@@ -723,7 +725,7 @@
CmdArgs.push_back("--32");
break;
case llvm::Triple::x86_64:
- if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32)
+ if (getToolChain().getTriple().isX32())
CmdArgs.push_back("--x32");
else
CmdArgs.push_back("--64");
@@ -1731,7 +1733,7 @@
// Determine default multilib from: 32, 64, x32
// Also handle cases such as 64 on 32, 32 on 64, etc.
enum { UNKNOWN, WANT32, WANT64, WANTX32 } Want = UNKNOWN;
- const bool IsX32 = TargetTriple.getEnvironment() == llvm::Triple::GNUX32;
+ const bool IsX32 = TargetTriple.isX32();
if (TargetTriple.isArch32Bit() && !NonExistent(Alt32))
Want = WANT64;
else if (TargetTriple.isArch64Bit() && IsX32 && !NonExistent(Altx32))
@@ -1907,9 +1909,7 @@
CandidateBiarchTripleAliases);
// Compute the set of prefixes for our search.
- SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
- D.PrefixDirs.end());
-
+ SmallVector<std::string, 8> Prefixes;
StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot);
if (GCCToolchainDir != "") {
if (GCCToolchainDir.back() == '/')
@@ -1932,13 +1932,10 @@
// Typically /usr.
AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
}
- }
- // Try to respect gcc-config on Gentoo. However, do that only
- // if --gcc-toolchain is not provided or equal to the Gentoo install
- // in /usr. This avoids accidentally enforcing the system GCC version
- // when using a custom toolchain.
- if (GCCToolchainDir == "" || GCCToolchainDir == D.SysRoot + "/usr") {
+ // Try to respect gcc-config on Gentoo if --gcc-toolchain is not provided.
+ // This avoids accidentally enforcing the system GCC version when using a
+ // custom toolchain.
SmallVector<StringRef, 16> GentooTestTriples;
// Try to match an exact triple as target triple first.
// e.g. crossdev -S x86_64-gentoo-linux-gnu will install gcc libs for
@@ -1958,7 +1955,8 @@
// Loop over the various components which exist and select the best GCC
// installation available. GCC installs are ranked by version number.
- Version = GCCVersion::Parse("0.0.0");
+ const GCCVersion VersionZero = GCCVersion::Parse("0.0.0");
+ Version = VersionZero;
for (const std::string &Prefix : Prefixes) {
auto &VFS = D.getVFS();
if (!VFS.exists(Prefix))
@@ -1991,6 +1989,10 @@
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, true,
GCCDirExists, GCCCrossDirExists);
}
+
+ // Skip other prefixes once a GCC installation is found.
+ if (Version > VersionZero)
+ break;
}
}
@@ -2104,15 +2106,21 @@
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
"x86_64-slackware-linux", "x86_64-unknown-linux",
"x86_64-amazon-linux", "x86_64-linux-android"};
- static const char *const X32LibDirs[] = {"/libx32"};
+ static const char *const X32Triples[] = {"x86_64-linux-gnux32",
+ "x86_64-pc-linux-gnux32"};
+ static const char *const X32LibDirs[] = {"/libx32", "/lib"};
static const char *const X86LibDirs[] = {"/lib32", "/lib"};
static const char *const X86Triples[] = {
- "i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu",
- "i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux",
- "i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux",
- "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu",
- "i686-linux-android", "i386-gnu", "i486-gnu",
- "i586-gnu", "i686-gnu"};
+ "i586-linux-gnu", "i686-linux-gnu",
+ "i686-pc-linux-gnu", "i386-redhat-linux6E",
+ "i686-redhat-linux", "i386-redhat-linux",
+ "i586-suse-linux", "i686-montavista-linux",
+ "i686-linux-android", "i686-gnu",
+ };
+
+ static const char *const M68kLibDirs[] = {"/lib"};
+ static const char *const M68kTriples[] = {
+ "m68k-linux-gnu", "m68k-unknown-linux-gnu", "m68k-suse-linux"};
static const char *const MIPSLibDirs[] = {"/lib"};
static const char *const MIPSTriples[] = {
@@ -2331,17 +2339,19 @@
TripleAliases.append(begin(AVRTriples), end(AVRTriples));
break;
case llvm::Triple::x86_64:
- LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
- TripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
- // x32 is always available when x86_64 is available, so adding it as
- // secondary arch with x86_64 triples
- if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32) {
- BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));
+ if (TargetTriple.isX32()) {
+ LibDirs.append(begin(X32LibDirs), end(X32LibDirs));
+ TripleAliases.append(begin(X32Triples), end(X32Triples));
+ BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
} else {
- BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));
- BiarchTripleAliases.append(begin(X86Triples), end(X86Triples));
+ LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
+ TripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
+ BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));
+ BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));
}
+ BiarchLibDirs.append(begin(X86LibDirs), end(X86LibDirs));
+ BiarchTripleAliases.append(begin(X86Triples), end(X86Triples));
break;
case llvm::Triple::x86:
LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
@@ -2351,8 +2361,14 @@
TripleAliases.append(begin(X86Triples), end(X86Triples));
BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples));
+ BiarchLibDirs.append(begin(X32LibDirs), end(X32LibDirs));
+ BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));
}
break;
+ case llvm::Triple::m68k:
+ LibDirs.append(begin(M68kLibDirs), end(M68kLibDirs));
+ TripleAliases.append(begin(M68kTriples), end(M68kTriples));
+ break;
case llvm::Triple::mips:
LibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));
TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
@@ -2496,7 +2512,6 @@
const llvm::Triple &TargetTriple, const ArgList &Args,
const std::string &LibDir, StringRef CandidateTriple,
bool NeedsBiarchSuffix, bool GCCDirExists, bool GCCCrossDirExists) {
- llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
// Locations relative to the system lib directory where GCC's triple-specific
// directories might reside.
struct GCCLibSuffix {
@@ -2520,24 +2535,7 @@
// files in that location, not just GCC installation data.
{CandidateTriple.str(), "..",
TargetTriple.getVendor() == llvm::Triple::Freescale ||
- TargetTriple.getVendor() == llvm::Triple::OpenEmbedded},
-
- // Natively multiarch systems sometimes put the GCC triple-specific
- // directory within their multiarch lib directory, resulting in the
- // triple appearing twice.
- {CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), "../../..",
- TargetTriple.getOS() != llvm::Triple::Solaris},
-
- // Deal with cases (on Ubuntu) where the system architecture could be i386
- // but the GCC target architecture could be (say) i686.
- // FIXME: It may be worthwhile to generalize this and look for a second
- // triple.
- {"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..",
- (TargetArch == llvm::Triple::x86 &&
- TargetTriple.getOS() != llvm::Triple::Solaris)},
- {"i386-gnu/gcc/" + CandidateTriple.str(), "../../..",
- (TargetArch == llvm::Triple::x86 &&
- TargetTriple.getOS() != llvm::Triple::Solaris)}};
+ TargetTriple.getVendor() == llvm::Triple::OpenEmbedded}};
for (auto &Suffix : Suffixes) {
if (!Suffix.Active)
@@ -2760,6 +2758,7 @@
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::msp430:
+ case llvm::Triple::m68k:
return true;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
@@ -2773,15 +2772,6 @@
}
}
-static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
- const Multilib &Multilib,
- StringRef InstallPath,
- ToolChain::path_list &Paths) {
- if (const auto &PathsCallback = Multilibs.filePathsCallback())
- for (const auto &Path : PathsCallback(Multilib))
- addPathIfExists(D, InstallPath + Path, Paths);
-}
-
void Generic_GCC::PushPPaths(ToolChain::path_list &PPaths) {
// Cross-compiling binutils and GCC installations (vanilla and openSUSE at
// least) put various tools in a triple-prefixed directory off of the parent
@@ -2808,12 +2798,13 @@
const std::string &LibPath =
std::string(GCCInstallation.getParentLibPath());
- // Add toolchain / multilib specific file paths.
- addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
- GCCInstallation.getInstallPath(), Paths);
-
// Sourcery CodeBench MIPS toolchain holds some libraries under
// a biarch-like suffix of the GCC installation.
+ if (const auto &PathsCallback = Multilibs.filePathsCallback())
+ for (const auto &Path : PathsCallback(SelectedMultilib))
+ addPathIfExists(D, GCCInstallation.getInstallPath() + Path, Paths);
+
+ // Add lib/gcc/$triple/$version, with an optional /multilib suffix.
addPathIfExists(
D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
Paths);
@@ -2850,10 +2841,8 @@
// the cross. Note that GCC does include some of these directories in some
// configurations but this seems somewhere between questionable and simply
// a bug.
- if (StringRef(LibPath).startswith(SysRoot)) {
- addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths);
+ if (StringRef(LibPath).startswith(SysRoot))
addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
- }
}
}
@@ -2861,24 +2850,7 @@
const std::string &SysRoot,
const std::string &OSLibDir,
path_list &Paths) {
- // Try walking via the GCC triple path in case of biarch or multiarch GCC
- // installations with strange symlinks.
if (GCCInstallation.isValid()) {
- addPathIfExists(D,
- SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
- "/../../" + OSLibDir,
- Paths);
-
- // Add the 'other' biarch variant path
- Multilib BiarchSibling;
- if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
- addPathIfExists(
- D, GCCInstallation.getInstallPath() + BiarchSibling.gccSuffix(),
- Paths);
- }
-
- // See comments above on the multilib variant for details of why this is
- // included even from outside the sysroot.
const std::string &LibPath =
std::string(GCCInstallation.getParentLibPath());
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
@@ -2886,31 +2858,32 @@
addPathIfExists(
D, LibPath + "/../" + GCCTriple.str() + "/lib" + Multilib.osSuffix(),
Paths);
-
- // See comments above on the multilib variant for details of why this is
- // only included from within the sysroot.
- if (StringRef(LibPath).startswith(SysRoot))
- addPathIfExists(D, LibPath, Paths);
}
}
void Generic_GCC::AddMultilibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Add include directories specific to the selected multilib set and multilib.
- if (GCCInstallation.isValid()) {
- const auto &Callback = Multilibs.includeDirsCallback();
- if (Callback) {
- for (const auto &Path : Callback(GCCInstallation.getMultilib()))
- addExternCSystemIncludeIfExists(
- DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path);
- }
+ if (!GCCInstallation.isValid())
+ return;
+ // gcc TOOL_INCLUDE_DIR.
+ const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
+ std::string LibPath(GCCInstallation.getParentLibPath());
+ addSystemInclude(DriverArgs, CC1Args,
+ Twine(LibPath) + "/../" + GCCTriple.str() + "/include");
+
+ const auto &Callback = Multilibs.includeDirsCallback();
+ if (Callback) {
+ for (const auto &Path : Callback(GCCInstallation.getMultilib()))
+ addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
+ GCCInstallation.getInstallPath() + Path);
}
}
void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
+ if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
+ options::OPT_nostdlibinc))
return;
switch (GetCXXStdlibType(DriverArgs)) {
@@ -2924,90 +2897,80 @@
}
}
-static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs,
- StringRef base) {
- std::error_code EC;
- int MaxVersion = 0;
- std::string MaxVersionString;
- for (llvm::vfs::directory_iterator LI = vfs.dir_begin(base, EC), LE;
- !EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->path());
- int Version;
- if (VersionText[0] == 'v' &&
- !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
- if (Version > MaxVersion) {
- MaxVersion = Version;
- MaxVersionString = std::string(VersionText);
- }
- }
- }
- return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
-}
-
void
Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+ std::string Target = getTripleString();
+
auto AddIncludePath = [&](std::string Path) {
- std::string IncludePath = DetectLibcxxIncludePath(getVFS(), Path);
- if (IncludePath.empty() || !getVFS().exists(IncludePath))
+ std::string Version = detectLibcxxVersion(Path);
+ if (Version.empty())
return false;
- addSystemInclude(DriverArgs, CC1Args, IncludePath);
+
+ // First add the per-target include path if it exists.
+ std::string TargetDir = Path + "/" + Target + "/c++/" + Version;
+ if (D.getVFS().exists(TargetDir))
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+
+ // Second add the generic one.
+ addSystemInclude(DriverArgs, CC1Args, Path + "/c++/" + Version);
return true;
};
+
// Android never uses the libc++ headers installed alongside the toolchain,
// which are generally incompatible with the NDK libraries anyway.
if (!getTriple().isAndroid())
- if (AddIncludePath(getDriver().Dir + "/../include/c++"))
+ if (AddIncludePath(getDriver().Dir + "/../include"))
return;
// If this is a development, non-installed, clang, libcxx will
// not be found at ../include/c++ but it likely to be found at
// one of the following two locations:
- std::string SysRoot = computeSysRoot();
- if (AddIncludePath(SysRoot + "/usr/local/include/c++"))
+ if (AddIncludePath(SysRoot + "/usr/local/include"))
return;
- if (AddIncludePath(SysRoot + "/usr/include/c++"))
+ if (AddIncludePath(SysRoot + "/usr/include"))
return;
}
-/// Helper to add the variant paths of a libstdc++ installation.
-bool Generic_GCC::addLibStdCXXIncludePaths(
- Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple,
- StringRef TargetMultiarchTriple, Twine IncludeSuffix,
- const ArgList &DriverArgs, ArgStringList &CC1Args) const {
- if (!getVFS().exists(Base + Suffix))
+bool Generic_GCC::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
+ Twine IncludeSuffix,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ bool DetectDebian) const {
+ if (!getVFS().exists(IncludeDir))
return false;
- addSystemInclude(DriverArgs, CC1Args, Base + Suffix);
+ // Debian native gcc uses g++-multiarch-incdir.diff which uses
+ // include/x86_64-linux-gnu/c++/10$IncludeSuffix instead of
+ // include/c++/10/x86_64-linux-gnu$IncludeSuffix.
+ std::string Dir = IncludeDir.str();
+ StringRef Include =
+ llvm::sys::path::parent_path(llvm::sys::path::parent_path(Dir));
+ std::string Path =
+ (Include + "/" + Triple + Dir.substr(Include.size()) + IncludeSuffix)
+ .str();
+ if (DetectDebian && !getVFS().exists(Path))
+ return false;
- // The vanilla GCC layout of libstdc++ headers uses a triple subdirectory. If
- // that path exists or we have neither a GCC nor target multiarch triple, use
- // this vanilla search path.
- if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) ||
- getVFS().exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) {
+ // GPLUSPLUS_INCLUDE_DIR
+ addSystemInclude(DriverArgs, CC1Args, IncludeDir);
+ // GPLUSPLUS_TOOL_INCLUDE_DIR. If Triple is not empty, add a target-dependent
+ // include directory.
+ if (DetectDebian)
+ addSystemInclude(DriverArgs, CC1Args, Path);
+ else if (!Triple.empty())
addSystemInclude(DriverArgs, CC1Args,
- Base + Suffix + "/" + GCCTriple + IncludeSuffix);
- } else {
- // Otherwise try to use multiarch naming schemes which have normalized the
- // triples and put the triple before the suffix.
- //
- // GCC surprisingly uses *both* the GCC triple with a multilib suffix and
- // the target triple, so we support that here.
- addSystemInclude(DriverArgs, CC1Args,
- Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix);
- addSystemInclude(DriverArgs, CC1Args,
- Base + "/" + TargetMultiarchTriple + Suffix);
- }
-
- addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward");
+ IncludeDir + "/" + Triple + IncludeSuffix);
+ // GPLUSPLUS_BACKWARD_INCLUDE_DIR
+ addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
return true;
}
-bool
-Generic_GCC::addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- // Use GCCInstallation to know where libstdc++ headers are installed.
- if (!GCCInstallation.isValid())
- return false;
+bool Generic_GCC::addGCCLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ StringRef DebianMultiarch) const {
+ assert(GCCInstallation.isValid());
// By default, look for the C++ headers in an include directory adjacent to
// the lib directory of the GCC installation. Note that this is expect to be
@@ -3016,17 +2979,24 @@
StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
- const std::string GCCMultiarchTriple = getMultiarchTriple(
- getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot);
- const std::string TargetMultiarchTriple =
- getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
const GCCVersion &Version = GCCInstallation.getVersion();
- // The primary search for libstdc++ supports multiarch variants.
- if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
- "/c++/" + Version.Text, TripleStr,
- GCCMultiarchTriple, TargetMultiarchTriple,
- Multilib.includeSuffix(), DriverArgs, CC1Args))
+ // Try /../$triple/include/c++/$version (gcc --print-multiarch is not empty).
+ if (addLibStdCXXIncludePaths(
+ LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,
+ TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
+ return true;
+
+ // Detect Debian g++-multiarch-incdir.diff.
+ if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
+ DebianMultiarch, Multilib.includeSuffix(),
+ DriverArgs, CC1Args, /*Debian=*/true))
+ return true;
+
+ // Try /../include/c++/$version (gcc --print-multiarch is empty).
+ if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
+ TripleStr, Multilib.includeSuffix(), DriverArgs,
+ CC1Args))
return true;
// Otherwise, fall back on a bunch of options which don't use multiarch
@@ -3041,9 +3011,7 @@
};
for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
- if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr,
- /*GCCMultiarchTriple*/ "",
- /*TargetMultiarchTriple*/ "",
+ if (addLibStdCXXIncludePaths(IncludePath, TripleStr,
Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
}
@@ -3053,7 +3021,10 @@
void
Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
+ if (GCCInstallation.isValid()) {
+ addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
+ GCCInstallation.getTriple().str());
+ }
}
llvm::opt::DerivedArgList *
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.h b/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.h
index 90d3baf..40fd756 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Gnu.h
@@ -310,11 +310,6 @@
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
- virtual std::string getMultiarchTriple(const Driver &D,
- const llvm::Triple &TargetTriple,
- StringRef SysRoot) const
- { return TargetTriple.str(); }
-
/// \name ToolChain Implementation Helper Functions
/// @{
@@ -347,16 +342,15 @@
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
- bool
- addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const;
+ bool addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ StringRef DebianMultiarch) const;
- bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
- StringRef GCCMultiarchTriple,
- StringRef TargetMultiarchTriple,
+ bool addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
Twine IncludeSuffix,
const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const;
+ llvm::opt::ArgStringList &CC1Args,
+ bool DetectDebian = false) const;
/// @}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/HIP.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/HIP.cpp
index a84c0c2..59d58aa 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/HIP.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/HIP.cpp
@@ -9,12 +9,12 @@
#include "HIP.h"
#include "AMDGPU.h"
#include "CommonArgs.h"
-#include "InputInfo.h"
#include "clang/Basic/Cuda.h"
#include "clang/Basic/TargetID.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/FileSystem.h"
@@ -35,23 +35,6 @@
namespace {
const unsigned HIPCodeObjectAlign = 4096;
-
-static void addBCLib(const Driver &D, const ArgList &Args,
- ArgStringList &CmdArgs, ArgStringList LibraryPaths,
- StringRef BCName) {
- StringRef FullName;
- for (std::string LibraryPath : LibraryPaths) {
- SmallString<128> Path(LibraryPath);
- llvm::sys::path::append(Path, BCName);
- FullName = Path;
- if (llvm::sys::fs::exists(FullName)) {
- CmdArgs.push_back("-mlink-builtin-bitcode");
- CmdArgs.push_back(Args.MakeArgString(FullName));
- return;
- }
- }
- D.Diag(diag::err_drv_no_such_file) << BCName;
-}
} // namespace
void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
@@ -66,8 +49,8 @@
auto &TC = getToolChain();
auto &D = TC.getDriver();
assert(!Inputs.empty() && "Must have at least one input.");
- addLTOOptions(TC, Args, LldArgs, Output, Inputs[0],
- D.getLTOMode() == LTOK_Thin);
+ bool IsThinLTO = D.getLTOMode(/*IsOffload=*/true) == LTOK_Thin;
+ addLTOOptions(TC, Args, LldArgs, Output, Inputs[0], IsThinLTO);
// Extract all the -m options
std::vector<llvm::StringRef> Features;
@@ -83,6 +66,12 @@
if (!Features.empty())
LldArgs.push_back(Args.MakeArgString(MAttrString));
+ // ToDo: Remove this option after AMDGPU backend supports ISA-level linking.
+ // Since AMDGPU backend currently does not support ISA-level linking, all
+ // called functions need to be imported.
+ if (IsThinLTO)
+ LldArgs.push_back(Args.MakeArgString("-plugin-opt=-force-import-all"));
+
for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
LldArgs.push_back(
Args.MakeArgString(Twine("-plugin-opt=") + A->getValue(0)));
@@ -96,6 +85,13 @@
LldArgs.append({"-o", Output.getFilename()});
for (auto Input : Inputs)
LldArgs.push_back(Input.getFilename());
+
+ if (Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
+ false))
+ llvm::for_each(TC.getHIPDeviceLibs(Args), [&](StringRef BCFile) {
+ LldArgs.push_back(Args.MakeArgString(BCFile));
+ });
+
const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
Lld, LldArgs, Inputs, Output));
@@ -118,11 +114,12 @@
std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
std::string BundlerInputArg = "-inputs=" NULL_FILE;
- // TODO: Change the bundle ID as requested by HIP runtime.
// For code object version 2 and 3, the offload kind in bundle ID is 'hip'
// for backward compatibility. For code object version 4 and greater, the
// offload kind in bundle ID is 'hipv4'.
std::string OffloadKind = "hip";
+ if (getAMDGPUCodeObjectVersion(C.getDriver(), Args) >= 4)
+ OffloadKind = OffloadKind + "v4";
for (const auto &II : Inputs) {
const auto* A = II.getAction();
BundlerTargetArg = BundlerTargetArg + "," + OffloadKind +
@@ -183,6 +180,7 @@
// in several main host machines.
ObjStream << "# HIP Object Generator\n";
ObjStream << "# *** Automatically generated by Clang ***\n";
+ ObjStream << " .protected __hip_fatbin\n";
ObjStream << " .type __hip_fatbin,@object\n";
ObjStream << " .section .hip_fatbin,\"a\",@progbits\n";
ObjStream << " .globl __hip_fatbin\n";
@@ -247,13 +245,8 @@
Action::OffloadKind DeviceOffloadingKind) const {
HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
- StringRef GpuArch = getGPUArch(DriverArgs);
- assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
- (void) GpuArch;
assert(DeviceOffloadingKind == Action::OFK_HIP &&
"Only HIP offloading kinds are supported for GPUs.");
- auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
- const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
CC1Args.push_back("-fcuda-is-device");
@@ -261,10 +254,8 @@
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
- if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
- false))
- CC1Args.push_back("-fgpu-rdc");
- else
+ if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
+ false))
CC1Args.append({"-mllvm", "-amdgpu-internalize-symbols"});
StringRef MaxThreadsPerBlock =
@@ -285,66 +276,10 @@
CC1Args.push_back("-fapply-global-visibility-to-externs");
}
- if (DriverArgs.hasArg(options::OPT_nogpulib))
- return;
- ArgStringList LibraryPaths;
-
- // Find in --hip-device-lib-path and HIP_LIBRARY_PATH.
- for (auto Path : RocmInstallation.getRocmDeviceLibPathArg())
- LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
-
- addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH");
-
- // Maintain compatability with --hip-device-lib.
- auto BCLibs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
- if (!BCLibs.empty()) {
- for (auto Lib : BCLibs)
- addBCLib(getDriver(), DriverArgs, CC1Args, LibraryPaths, Lib);
- } else {
- if (!RocmInstallation.hasDeviceLibrary()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
- return;
- }
-
- std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch);
- if (LibDeviceFile.empty()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GpuArch;
- return;
- }
-
- // If --hip-device-lib is not set, add the default bitcode libraries.
- // TODO: There are way too many flags that change this. Do we need to check
- // them all?
- bool DAZ = DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
- options::OPT_fno_cuda_flush_denormals_to_zero,
- getDefaultDenormsAreZeroForTarget(Kind));
- // TODO: Check standard C++ flags?
- bool FiniteOnly = false;
- bool UnsafeMathOpt = false;
- bool FastRelaxedMath = false;
- bool CorrectSqrt = true;
- bool Wave64 = isWave64(DriverArgs, Kind);
-
- // Add the HIP specific bitcode library.
+ llvm::for_each(getHIPDeviceLibs(DriverArgs), [&](StringRef BCFile) {
CC1Args.push_back("-mlink-builtin-bitcode");
- CC1Args.push_back(DriverArgs.MakeArgString(RocmInstallation.getHIPPath()));
-
- // Add the generic set of libraries.
- RocmInstallation.addCommonBitcodeLibCC1Args(
- DriverArgs, CC1Args, LibDeviceFile, Wave64, DAZ, FiniteOnly,
- UnsafeMathOpt, FastRelaxedMath, CorrectSqrt);
-
- // Add instrument lib.
- auto InstLib =
- DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
- if (InstLib.empty())
- return;
- if (llvm::sys::fs::exists(InstLib)) {
- CC1Args.push_back("-mlink-builtin-bitcode");
- CC1Args.push_back(DriverArgs.MakeArgString(InstLib));
- } else
- getDriver().Diag(diag::err_drv_no_such_file) << InstLib;
- }
+ CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
+ });
}
llvm::opt::DerivedArgList *
@@ -423,3 +358,130 @@
const ArgList &Args) const {
return HostTC.computeMSVCVersion(D, Args);
}
+
+llvm::SmallVector<std::string, 12>
+HIPToolChain::getHIPDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
+ llvm::SmallVector<std::string, 12> BCLibs;
+ if (DriverArgs.hasArg(options::OPT_nogpulib))
+ return {};
+ ArgStringList LibraryPaths;
+
+ // Find in --hip-device-lib-path and HIP_LIBRARY_PATH.
+ for (auto Path : RocmInstallation.getRocmDeviceLibPathArg())
+ LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
+
+ addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH");
+
+ // Maintain compatability with --hip-device-lib.
+ auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
+ if (!BCLibArgs.empty()) {
+ llvm::for_each(BCLibArgs, [&](StringRef BCName) {
+ StringRef FullName;
+ for (std::string LibraryPath : LibraryPaths) {
+ SmallString<128> Path(LibraryPath);
+ llvm::sys::path::append(Path, BCName);
+ FullName = Path;
+ if (llvm::sys::fs::exists(FullName)) {
+ BCLibs.push_back(FullName.str());
+ return;
+ }
+ }
+ getDriver().Diag(diag::err_drv_no_such_file) << BCName;
+ });
+ } else {
+ if (!RocmInstallation.hasDeviceLibrary()) {
+ getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
+ return {};
+ }
+ StringRef GpuArch = getGPUArch(DriverArgs);
+ assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
+ (void)GpuArch;
+ auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
+ const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
+
+ std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch);
+ if (LibDeviceFile.empty()) {
+ getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GpuArch;
+ return {};
+ }
+
+ // If --hip-device-lib is not set, add the default bitcode libraries.
+ // TODO: There are way too many flags that change this. Do we need to check
+ // them all?
+ bool DAZ = DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
+ options::OPT_fno_gpu_flush_denormals_to_zero,
+ getDefaultDenormsAreZeroForTarget(Kind));
+ bool FiniteOnly =
+ DriverArgs.hasFlag(options::OPT_ffinite_math_only,
+ options::OPT_fno_finite_math_only, false);
+ bool UnsafeMathOpt =
+ DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations, false);
+ bool FastRelaxedMath = DriverArgs.hasFlag(
+ options::OPT_ffast_math, options::OPT_fno_fast_math, false);
+ bool CorrectSqrt = DriverArgs.hasFlag(
+ options::OPT_fhip_fp32_correctly_rounded_divide_sqrt,
+ options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt);
+ bool Wave64 = isWave64(DriverArgs, Kind);
+
+ if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
+ options::OPT_fno_gpu_sanitize, false)) {
+ auto AsanRTL = RocmInstallation.getAsanRTLPath();
+ if (AsanRTL.empty()) {
+ unsigned DiagID = getDriver().getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "AMDGPU address sanitizer runtime library (asanrtl) is not found. "
+ "Please install ROCm device library which supports address "
+ "sanitizer");
+ getDriver().Diag(DiagID);
+ return {};
+ } else
+ BCLibs.push_back(AsanRTL.str());
+ }
+
+ // Add the HIP specific bitcode library.
+ BCLibs.push_back(RocmInstallation.getHIPPath().str());
+
+ // Add the generic set of libraries.
+ BCLibs.append(RocmInstallation.getCommonBitcodeLibs(
+ DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
+ FastRelaxedMath, CorrectSqrt));
+
+ // Add instrument lib.
+ auto InstLib =
+ DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
+ if (InstLib.empty())
+ return BCLibs;
+ if (llvm::sys::fs::exists(InstLib))
+ BCLibs.push_back(InstLib.str());
+ else
+ getDriver().Diag(diag::err_drv_no_such_file) << InstLib;
+ }
+
+ return BCLibs;
+}
+
+void HIPToolChain::checkTargetID(const llvm::opt::ArgList &DriverArgs) const {
+ auto PTID = getParsedTargetID(DriverArgs);
+ if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
+ getDriver().Diag(clang::diag::err_drv_bad_target_id)
+ << PTID.OptionalTargetID.getValue();
+ return;
+ }
+
+ assert(PTID.OptionalFeatures && "Invalid return from getParsedTargetID");
+ auto &FeatureMap = PTID.OptionalFeatures.getValue();
+ // Sanitizer is not supported with xnack-.
+ if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
+ options::OPT_fno_gpu_sanitize, false)) {
+ auto Loc = FeatureMap.find("xnack");
+ if (Loc != FeatureMap.end() && !Loc->second) {
+ auto &Diags = getDriver().getDiags();
+ auto DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "'-fgpu-sanitize' is not compatible with offload arch '%0'. "
+ "Use an offload arch without 'xnack-' instead");
+ Diags.Report(DiagID) << PTID.OptionalTargetID.getValue();
+ }
+ }
+}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/HIP.h b/src/llvm-project/clang/lib/Driver/ToolChains/HIP.h
index 5e2be71..3cced0a 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/HIP.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/HIP.h
@@ -71,15 +71,6 @@
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;
-
- bool useIntegratedAs() const override { return true; }
- bool isCrossCompiling() const override { return true; }
- bool isPICDefault() const override { return false; }
- bool isPIEDefault() const override { return false; }
- bool isPICDefaultForced() const override { return false; }
- bool SupportsProfiling() const override { return false; }
- bool IsMathErrnoDefault() const override { return false; }
-
void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
void
@@ -92,6 +83,8 @@
llvm::opt::ArgStringList &CC1Args) const override;
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ llvm::SmallVector<std::string, 12>
+ getHIPDeviceLibs(const llvm::opt::ArgList &Args) const override;
SanitizerMask getSupportedSanitizers() const override;
@@ -102,6 +95,7 @@
unsigned GetDefaultDwarfVersion() const override { return 4; }
const ToolChain &HostTC;
+ void checkTargetID(const llvm::opt::ArgList &DriverArgs) const override;
protected:
Tool *buildLinker() const override;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp
index 18f550c..a79f0f7 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -29,6 +29,6 @@
void Haiku::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- addLibStdCXXIncludePaths(getDriver().SysRoot, "/system/develop/headers/c++",
- getTriple().str(), "", "", "", DriverArgs, CC1Args);
+ addLibStdCXXIncludePaths(getDriver().SysRoot + "/system/develop/headers/c++",
+ getTriple().str(), "", DriverArgs, CC1Args);
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
index fb54f73..828bfdb 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -8,10 +8,10 @@
#include "Hexagon.h"
#include "CommonArgs.h"
-#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Option/ArgList.h"
@@ -38,7 +38,7 @@
// Handle the unsupported values passed to mhvx-length.
if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
StringRef Val = A->getValue();
- if (!Val.equals_lower("64b") && !Val.equals_lower("128b"))
+ if (!Val.equals_insensitive("64b") && !Val.equals_insensitive("128b"))
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
}
@@ -218,8 +218,8 @@
bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
bool UseG0 = false;
const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
- bool UseLLD = (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
- llvm::sys::path::stem(Exec).equals_lower("ld.lld"));
+ bool UseLLD = (llvm::sys::path::filename(Exec).equals_insensitive("ld.lld") ||
+ llvm::sys::path::stem(Exec).equals_insensitive("ld.lld"));
bool UseShared = IsShared && !IsStatic;
StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
@@ -613,15 +613,15 @@
llvm::opt::ArgStringList &CC1Args) const {
const Driver &D = getDriver();
if (!D.SysRoot.empty() && getTriple().isMusl())
- addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "", "", "",
- "", DriverArgs, CC1Args);
- else if (getTriple().isMusl())
- addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", "", "", "",
+ addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "",
DriverArgs, CC1Args);
+ else if (getTriple().isMusl())
+ addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,
+ CC1Args);
else {
std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
- addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++/v1", "", "", "",
- "", DriverArgs, CC1Args);
+ addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",
+ DriverArgs, CC1Args);
}
}
void HexagonToolChain::addLibStdCxxIncludePaths(
@@ -629,7 +629,7 @@
llvm::opt::ArgStringList &CC1Args) const {
const Driver &D = getDriver();
std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
- addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "",
+ addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",
DriverArgs, CC1Args);
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp
index a700d7b..48b9cca 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp
@@ -170,11 +170,13 @@
AddMultilibIncludeArgs(DriverArgs, CC1Args);
- if (getTriple().getArch() == llvm::Triple::x86) {
- std::string Path = SysRoot + "/usr/include/i386-gnu";
- if (D.getVFS().exists(Path))
- addExternCSystemInclude(DriverArgs, CC1Args, Path);
- }
+ // On systems using multiarch, add /usr/include/$triple before
+ // /usr/include.
+ std::string MultiarchIncludeDir = getMultiarchTriple(D, getTriple(), SysRoot);
+ if (!MultiarchIncludeDir.empty() &&
+ D.getVFS().exists(SysRoot + "/usr/include/" + MultiarchIncludeDir))
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ SysRoot + "/usr/include/" + MultiarchIncludeDir);
// Add an include of '/include' directly. This isn't provided by default by
// system GCCs, but is often used with cross-compiling GCCs, and harmless to
@@ -184,6 +186,21 @@
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}
+void Hurd::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ // We need a detected GCC installation on Linux to provide libstdc++'s
+ // headers in odd Linuxish places.
+ if (!GCCInstallation.isValid())
+ return;
+
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ StringRef DebianMultiarch =
+ GCCInstallation.getTriple().getArch() == llvm::Triple::x86 ? "i386-gnu"
+ : TripleStr;
+
+ addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args, DebianMultiarch);
+}
+
void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
for (const auto &Opt : ExtraOpts)
CmdArgs.push_back(Opt.c_str());
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Hurd.h b/src/llvm-project/clang/lib/Driver/ToolChains/Hurd.h
index 0612a55..f301bc5 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Hurd.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Hurd.h
@@ -26,6 +26,9 @@
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/InterfaceStubs.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
index 57acf33..05a13db 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
@@ -20,10 +20,11 @@
const llvm::opt::ArgList &Args,
const char *LinkingOutput) const {
std::string Merger = getToolChain().GetProgramPath(getShortName());
+ // TODO: Use IFS library directly in the future.
llvm::opt::ArgStringList CmdArgs;
- CmdArgs.push_back("-action");
+ CmdArgs.push_back("--input-format=IFS");
const bool WriteBin = !Args.getLastArg(options::OPT_emit_merged_ifs);
- CmdArgs.push_back(WriteBin ? "write-bin" : "write-ifs");
+ CmdArgs.push_back(WriteBin ? "--output-format=ELF" : "--output-format=IFS");
CmdArgs.push_back("-o");
// Normally we want to write to a side-car file ending in ".ifso" so for
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp
index 9663a73..c9360fc 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp
@@ -58,64 +58,42 @@
// regardless of what the actual target triple is.
case llvm::Triple::arm:
case llvm::Triple::thumb:
- if (IsAndroid) {
+ if (IsAndroid)
return "arm-linux-androideabi";
- } else if (TargetEnvironment == llvm::Triple::GNUEABIHF) {
- if (D.getVFS().exists(SysRoot + "/lib/arm-linux-gnueabihf"))
- return "arm-linux-gnueabihf";
- } else {
- if (D.getVFS().exists(SysRoot + "/lib/arm-linux-gnueabi"))
- return "arm-linux-gnueabi";
- }
- break;
+ if (TargetEnvironment == llvm::Triple::GNUEABIHF)
+ return "arm-linux-gnueabihf";
+ return "arm-linux-gnueabi";
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- if (TargetEnvironment == llvm::Triple::GNUEABIHF) {
- if (D.getVFS().exists(SysRoot + "/lib/armeb-linux-gnueabihf"))
- return "armeb-linux-gnueabihf";
- } else {
- if (D.getVFS().exists(SysRoot + "/lib/armeb-linux-gnueabi"))
- return "armeb-linux-gnueabi";
- }
- break;
+ if (TargetEnvironment == llvm::Triple::GNUEABIHF)
+ return "armeb-linux-gnueabihf";
+ return "armeb-linux-gnueabi";
case llvm::Triple::x86:
if (IsAndroid)
return "i686-linux-android";
- if (D.getVFS().exists(SysRoot + "/lib/i386-linux-gnu"))
- return "i386-linux-gnu";
- break;
+ return "i386-linux-gnu";
case llvm::Triple::x86_64:
if (IsAndroid)
return "x86_64-linux-android";
- // We don't want this for x32, otherwise it will match x86_64 libs
- if (TargetEnvironment != llvm::Triple::GNUX32 &&
- D.getVFS().exists(SysRoot + "/lib/x86_64-linux-gnu"))
- return "x86_64-linux-gnu";
- break;
+ if (TargetEnvironment == llvm::Triple::GNUX32)
+ return "x86_64-linux-gnux32";
+ return "x86_64-linux-gnu";
case llvm::Triple::aarch64:
if (IsAndroid)
return "aarch64-linux-android";
- if (D.getVFS().exists(SysRoot + "/lib/aarch64-linux-gnu"))
- return "aarch64-linux-gnu";
- break;
+ return "aarch64-linux-gnu";
case llvm::Triple::aarch64_be:
- if (D.getVFS().exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
- return "aarch64_be-linux-gnu";
- break;
- case llvm::Triple::mips: {
- std::string MT = IsMipsR6 ? "mipsisa32r6-linux-gnu" : "mips-linux-gnu";
- if (D.getVFS().exists(SysRoot + "/lib/" + MT))
- return MT;
- break;
- }
- case llvm::Triple::mipsel: {
+ return "aarch64_be-linux-gnu";
+
+ case llvm::Triple::m68k:
+ return "m68k-linux-gnu";
+
+ case llvm::Triple::mips:
+ return IsMipsR6 ? "mipsisa32r6-linux-gnu" : "mips-linux-gnu";
+ case llvm::Triple::mipsel:
if (IsAndroid)
return "mipsel-linux-android";
- std::string MT = IsMipsR6 ? "mipsisa32r6el-linux-gnu" : "mipsel-linux-gnu";
- if (D.getVFS().exists(SysRoot + "/lib/" + MT))
- return MT;
- break;
- }
+ return IsMipsR6 ? "mipsisa32r6el-linux-gnu" : "mipsel-linux-gnu";
case llvm::Triple::mips64: {
std::string MT = std::string(IsMipsR6 ? "mipsisa64r6" : "mips64") +
"-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64");
@@ -139,33 +117,19 @@
case llvm::Triple::ppc:
if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
return "powerpc-linux-gnuspe";
- if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnu"))
- return "powerpc-linux-gnu";
- break;
+ return "powerpc-linux-gnu";
case llvm::Triple::ppcle:
- if (D.getVFS().exists(SysRoot + "/lib/powerpcle-linux-gnu"))
- return "powerpcle-linux-gnu";
- break;
+ return "powerpcle-linux-gnu";
case llvm::Triple::ppc64:
- if (D.getVFS().exists(SysRoot + "/lib/powerpc64-linux-gnu"))
- return "powerpc64-linux-gnu";
- break;
+ return "powerpc64-linux-gnu";
case llvm::Triple::ppc64le:
- if (D.getVFS().exists(SysRoot + "/lib/powerpc64le-linux-gnu"))
- return "powerpc64le-linux-gnu";
- break;
+ return "powerpc64le-linux-gnu";
case llvm::Triple::sparc:
- if (D.getVFS().exists(SysRoot + "/lib/sparc-linux-gnu"))
- return "sparc-linux-gnu";
- break;
+ return "sparc-linux-gnu";
case llvm::Triple::sparcv9:
- if (D.getVFS().exists(SysRoot + "/lib/sparc64-linux-gnu"))
- return "sparc64-linux-gnu";
- break;
+ return "sparc64-linux-gnu";
case llvm::Triple::systemz:
- if (D.getVFS().exists(SysRoot + "/lib/s390x-linux-gnu"))
- return "s390x-linux-gnu";
- break;
+ return "s390x-linux-gnu";
}
return TargetTriple.str();
}
@@ -202,8 +166,7 @@
Triple.getArch() == llvm::Triple::sparc)
return "lib32";
- if (Triple.getArch() == llvm::Triple::x86_64 &&
- Triple.getEnvironment() == llvm::Triple::GNUX32)
+ if (Triple.getArch() == llvm::Triple::x86_64 && Triple.isX32())
return "libx32";
if (Triple.getArch() == llvm::Triple::riscv32)
@@ -301,16 +264,6 @@
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
- // Similar to the logic for GCC above, if we currently running Clang inside
- // of the requested system root, add its parent library paths to
- // those searched.
- // FIXME: It's not clear whether we should use the driver's installed
- // directory ('Dir' below) or the ResourceDir.
- if (StringRef(D.Dir).startswith(SysRoot)) {
- addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
- addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
- }
-
addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
@@ -357,6 +310,12 @@
addPathIfExists(D, SysRoot + "/usr/lib", Paths);
}
+ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
+ if (getTriple().isAndroid())
+ return ToolChain::RLT_CompilerRT;
+ return Generic_ELF::GetDefaultRuntimeLibType();
+}
+
ToolChain::CXXStdlibType Linux::GetDefaultCXXStdlibType() const {
if (getTriple().isAndroid())
return ToolChain::CST_Libcxx;
@@ -438,6 +397,12 @@
ArchName = "armeb";
IsArm = true;
break;
+ case llvm::Triple::x86:
+ ArchName = "i386";
+ break;
+ case llvm::Triple::x86_64:
+ ArchName = Triple.isX32() ? "x32" : Triple.getArchName().str();
+ break;
default:
ArchName = Triple.getArchName().str();
}
@@ -476,6 +441,10 @@
Loader = HF ? "ld-linux-armhf.so.3" : "ld-linux.so.3";
break;
}
+ case llvm::Triple::m68k:
+ LibDir = "lib";
+ Loader = "ld.so.1";
+ break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -543,7 +512,7 @@
Loader = "ld-linux.so.2";
break;
case llvm::Triple::x86_64: {
- bool X32 = Triple.getEnvironment() == llvm::Triple::GNUX32;
+ bool X32 = Triple.isX32();
LibDir = X32 ? "libx32" : "lib64";
Loader = X32 ? "ld-linux-x32.so.2" : "ld-linux-x86-64.so.2";
@@ -568,9 +537,10 @@
if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
return;
- if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
- addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
-
+ // Add 'include' in the resource directory, which is similar to
+ // GCC_INCLUDE_DIR (private headers) in GCC. Note: the include directory
+ // contains some files conflicting with system /usr/include. musl systems
+ // prefer the /usr/include copies which are more relevant.
SmallString<128> ResourceDirInclude(D.ResourceDir);
llvm::sys::path::append(ResourceDirInclude, "include");
if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&
@@ -580,6 +550,11 @@
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
+ // LOCAL_INCLUDE_DIR
+ addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
+ // TOOL_INCLUDE_DIR
+ AddMultilibIncludeArgs(DriverArgs, CC1Args);
+
// Check for configure-time C include directories.
StringRef CIncludeDirs(C_INCLUDE_DIRS);
if (CIncludeDirs != "") {
@@ -593,173 +568,13 @@
return;
}
- // Lacking those, try to detect the correct set of system includes for the
- // target triple.
-
- AddMultilibIncludeArgs(DriverArgs, CC1Args);
-
- // Implement generic Debian multiarch support.
- const StringRef X86_64MultiarchIncludeDirs[] = {
- "/usr/include/x86_64-linux-gnu",
-
- // FIXME: These are older forms of multiarch. It's not clear that they're
- // in use in any released version of Debian, so we should consider
- // removing them.
- "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"};
- const StringRef X86MultiarchIncludeDirs[] = {
- "/usr/include/i386-linux-gnu",
-
- // FIXME: These are older forms of multiarch. It's not clear that they're
- // in use in any released version of Debian, so we should consider
- // removing them.
- "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu",
- "/usr/include/i486-linux-gnu"};
- const StringRef AArch64MultiarchIncludeDirs[] = {
- "/usr/include/aarch64-linux-gnu"};
- const StringRef ARMMultiarchIncludeDirs[] = {
- "/usr/include/arm-linux-gnueabi"};
- const StringRef ARMHFMultiarchIncludeDirs[] = {
- "/usr/include/arm-linux-gnueabihf"};
- const StringRef ARMEBMultiarchIncludeDirs[] = {
- "/usr/include/armeb-linux-gnueabi"};
- const StringRef ARMEBHFMultiarchIncludeDirs[] = {
- "/usr/include/armeb-linux-gnueabihf"};
- const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"};
- const StringRef MIPSELMultiarchIncludeDirs[] = {
- "/usr/include/mipsel-linux-gnu"};
- const StringRef MIPS64MultiarchIncludeDirs[] = {
- "/usr/include/mips64-linux-gnuabi64"};
- const StringRef MIPS64ELMultiarchIncludeDirs[] = {
- "/usr/include/mips64el-linux-gnuabi64"};
- const StringRef MIPSN32MultiarchIncludeDirs[] = {
- "/usr/include/mips64-linux-gnuabin32"};
- const StringRef MIPSN32ELMultiarchIncludeDirs[] = {
- "/usr/include/mips64el-linux-gnuabin32"};
- const StringRef MIPSR6MultiarchIncludeDirs[] = {
- "/usr/include/mipsisa32-linux-gnu"};
- const StringRef MIPSR6ELMultiarchIncludeDirs[] = {
- "/usr/include/mipsisa32r6el-linux-gnu"};
- const StringRef MIPS64R6MultiarchIncludeDirs[] = {
- "/usr/include/mipsisa64r6-linux-gnuabi64"};
- const StringRef MIPS64R6ELMultiarchIncludeDirs[] = {
- "/usr/include/mipsisa64r6el-linux-gnuabi64"};
- const StringRef MIPSN32R6MultiarchIncludeDirs[] = {
- "/usr/include/mipsisa64r6-linux-gnuabin32"};
- const StringRef MIPSN32R6ELMultiarchIncludeDirs[] = {
- "/usr/include/mipsisa64r6el-linux-gnuabin32"};
- const StringRef PPCMultiarchIncludeDirs[] = {
- "/usr/include/powerpc-linux-gnu",
- "/usr/include/powerpc-linux-gnuspe"};
- const StringRef PPCLEMultiarchIncludeDirs[] = {
- "/usr/include/powerpcle-linux-gnu"};
- const StringRef PPC64MultiarchIncludeDirs[] = {
- "/usr/include/powerpc64-linux-gnu"};
- const StringRef PPC64LEMultiarchIncludeDirs[] = {
- "/usr/include/powerpc64le-linux-gnu"};
- const StringRef SparcMultiarchIncludeDirs[] = {
- "/usr/include/sparc-linux-gnu"};
- const StringRef Sparc64MultiarchIncludeDirs[] = {
- "/usr/include/sparc64-linux-gnu"};
- const StringRef SYSTEMZMultiarchIncludeDirs[] = {
- "/usr/include/s390x-linux-gnu"};
- ArrayRef<StringRef> MultiarchIncludeDirs;
- switch (getTriple().getArch()) {
- case llvm::Triple::x86_64:
- MultiarchIncludeDirs = X86_64MultiarchIncludeDirs;
- break;
- case llvm::Triple::x86:
- MultiarchIncludeDirs = X86MultiarchIncludeDirs;
- break;
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- MultiarchIncludeDirs = AArch64MultiarchIncludeDirs;
- break;
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
- MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs;
- else
- MultiarchIncludeDirs = ARMMultiarchIncludeDirs;
- break;
- case llvm::Triple::armeb:
- case llvm::Triple::thumbeb:
- if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
- MultiarchIncludeDirs = ARMEBHFMultiarchIncludeDirs;
- else
- MultiarchIncludeDirs = ARMEBMultiarchIncludeDirs;
- break;
- case llvm::Triple::mips:
- if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
- MultiarchIncludeDirs = MIPSR6MultiarchIncludeDirs;
- else
- MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
- break;
- case llvm::Triple::mipsel:
- if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
- MultiarchIncludeDirs = MIPSR6ELMultiarchIncludeDirs;
- else
- MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
- break;
- case llvm::Triple::mips64:
- if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
- if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
- MultiarchIncludeDirs = MIPSN32R6MultiarchIncludeDirs;
- else
- MultiarchIncludeDirs = MIPS64R6MultiarchIncludeDirs;
- else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
- MultiarchIncludeDirs = MIPSN32MultiarchIncludeDirs;
- else
- MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs;
- break;
- case llvm::Triple::mips64el:
- if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
- if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
- MultiarchIncludeDirs = MIPSN32R6ELMultiarchIncludeDirs;
- else
- MultiarchIncludeDirs = MIPS64R6ELMultiarchIncludeDirs;
- else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
- MultiarchIncludeDirs = MIPSN32ELMultiarchIncludeDirs;
- else
- MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs;
- break;
- case llvm::Triple::ppc:
- MultiarchIncludeDirs = PPCMultiarchIncludeDirs;
- break;
- case llvm::Triple::ppcle:
- MultiarchIncludeDirs = PPCLEMultiarchIncludeDirs;
- break;
- case llvm::Triple::ppc64:
- MultiarchIncludeDirs = PPC64MultiarchIncludeDirs;
- break;
- case llvm::Triple::ppc64le:
- MultiarchIncludeDirs = PPC64LEMultiarchIncludeDirs;
- break;
- case llvm::Triple::sparc:
- MultiarchIncludeDirs = SparcMultiarchIncludeDirs;
- break;
- case llvm::Triple::sparcv9:
- MultiarchIncludeDirs = Sparc64MultiarchIncludeDirs;
- break;
- case llvm::Triple::systemz:
- MultiarchIncludeDirs = SYSTEMZMultiarchIncludeDirs;
- break;
- default:
- break;
- }
-
- const std::string AndroidMultiarchIncludeDir =
- std::string("/usr/include/") +
- getMultiarchTriple(D, getTriple(), SysRoot);
- const StringRef AndroidMultiarchIncludeDirs[] = {AndroidMultiarchIncludeDir};
- if (getTriple().isAndroid())
- MultiarchIncludeDirs = AndroidMultiarchIncludeDirs;
-
- for (StringRef Dir : MultiarchIncludeDirs) {
- if (D.getVFS().exists(SysRoot + Dir)) {
- addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir);
- break;
- }
- }
+ // On systems using multiarch and Android, add /usr/include/$triple before
+ // /usr/include.
+ std::string MultiarchIncludeDir = getMultiarchTriple(D, getTriple(), SysRoot);
+ if (!MultiarchIncludeDir.empty() &&
+ D.getVFS().exists(SysRoot + "/usr/include/" + MultiarchIncludeDir))
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ SysRoot + "/usr/include/" + MultiarchIncludeDir);
if (getTriple().getOS() == llvm::Triple::RTEMS)
return;
@@ -777,17 +592,24 @@
void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- // Try generic GCC detection first.
- if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args))
- return;
-
// We need a detected GCC installation on Linux to provide libstdc++'s
// headers in odd Linuxish places.
if (!GCCInstallation.isValid())
return;
- StringRef LibDir = GCCInstallation.getParentLibPath();
+ // Detect Debian g++-multiarch-incdir.diff.
StringRef TripleStr = GCCInstallation.getTriple().str();
+ StringRef DebianMultiarch =
+ GCCInstallation.getTriple().getArch() == llvm::Triple::x86
+ ? "i386-linux-gnu"
+ : TripleStr;
+
+ // Try generic GCC detection first.
+ if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args,
+ DebianMultiarch))
+ return;
+
+ StringRef LibDir = GCCInstallation.getParentLibPath();
const Multilib &Multilib = GCCInstallation.getMultilib();
const GCCVersion &Version = GCCInstallation.getVersion();
@@ -803,9 +625,7 @@
};
for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
- if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr,
- /*GCCMultiarchTriple*/ "",
- /*TargetMultiarchTriple*/ "",
+ if (addLibStdCXXIncludePaths(IncludePath, TripleStr,
Multilib.includeSuffix(), DriverArgs, CC1Args))
break;
}
@@ -836,6 +656,19 @@
getTriple().isMusl() || getSanitizerArgs().requiresPIE();
}
+bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const {
+ // Outline atomics for AArch64 are supported by compiler-rt
+ // and libgcc since 9.3.1
+ assert(getTriple().isAArch64() && "expected AArch64 target!");
+ ToolChain::RuntimeLibType RtLib = GetRuntimeLibType(Args);
+ if (RtLib == ToolChain::RLT_CompilerRT)
+ return true;
+ assert(RtLib == ToolChain::RLT_Libgcc && "unexpected runtime library type!");
+ if (GCCInstallation.getVersion().isOlderThan(9, 3, 1))
+ return false;
+ return true;
+}
+
bool Linux::isNoExecStackDefault() const {
return getTriple().isAndroid();
}
@@ -859,6 +692,7 @@
getTriple().getArch() == llvm::Triple::thumb ||
getTriple().getArch() == llvm::Triple::armeb ||
getTriple().getArch() == llvm::Triple::thumbeb;
+ const bool IsRISCV64 = getTriple().getArch() == llvm::Triple::riscv64;
const bool IsSystemZ = getTriple().getArch() == llvm::Triple::systemz;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
@@ -873,9 +707,9 @@
if (IsX86_64 || IsMIPS64 || IsAArch64)
Res |= SanitizerKind::DataFlow;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 ||
- IsSystemZ)
+ IsRISCV64 || IsSystemZ)
Res |= SanitizerKind::Leak;
- if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ)
Res |= SanitizerKind::Thread;
if (IsX86_64)
Res |= SanitizerKind::KernelMemory;
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Linux.h b/src/llvm-project/clang/lib/Driver/ToolChains/Linux.h
index 6b16b0e..169a37c 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Linux.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Linux.h
@@ -23,6 +23,10 @@
bool HasNativeLLVMSupport() const override;
+ std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const override;
+
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -35,7 +39,10 @@
llvm::opt::ArgStringList &CC1Args) const override;
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ RuntimeLibType GetDefaultRuntimeLibType() const override;
CXXStdlibType GetDefaultCXXStdlibType() const override;
+ bool
+ IsAArch64OutlineAtomicsDefault(const llvm::opt::ArgList &Args) const override;
bool isPIEDefault() const override;
bool isNoExecStackDefault() const override;
bool IsMathErrnoDefault() const override;
@@ -58,10 +65,6 @@
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
Tool *buildStaticLibTool() const override;
-
- std::string getMultiarchTriple(const Driver &D,
- const llvm::Triple &TargetTriple,
- StringRef SysRoot) const override;
};
} // end namespace toolchains
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp
index f3ed996..96994ba 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp
@@ -9,8 +9,8 @@
#include "MSP430.h"
#include "CommonArgs.h"
#include "Gnu.h"
-#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/MSP430.h b/src/llvm-project/clang/lib/Driver/ToolChains/MSP430.h
index 3789e74..9d247ca 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/MSP430.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/MSP430.h
@@ -10,9 +10,9 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H
#include "Gnu.h"
-#include "InputInfo.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringRef.h"
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp
index 13943b6c..0dc94a4 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -28,6 +28,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <cstdio>
#ifdef _WIN32
@@ -62,19 +63,65 @@
using namespace clang;
using namespace llvm::opt;
+static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
+ auto Status = VFS.status(Path);
+ if (!Status)
+ return false;
+ return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
+}
+
// Defined below.
// Forward declare this so there aren't too many things above the constructor.
static bool getSystemRegistryString(const char *keyPath, const char *valueName,
std::string &value, std::string *phValue);
+static std::string getHighestNumericTupleInDirectory(llvm::vfs::FileSystem &VFS,
+ StringRef Directory) {
+ std::string Highest;
+ llvm::VersionTuple HighestTuple;
+
+ std::error_code EC;
+ for (llvm::vfs::directory_iterator DirIt = VFS.dir_begin(Directory, EC),
+ DirEnd;
+ !EC && DirIt != DirEnd; DirIt.increment(EC)) {
+ auto Status = VFS.status(DirIt->path());
+ if (!Status || !Status->isDirectory())
+ continue;
+ StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
+ llvm::VersionTuple Tuple;
+ if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error.
+ continue;
+ if (Tuple > HighestTuple) {
+ HighestTuple = Tuple;
+ Highest = CandidateName.str();
+ }
+ }
+
+ return Highest;
+}
+
// Check command line arguments to try and find a toolchain.
static bool
-findVCToolChainViaCommandLine(const ArgList &Args, std::string &Path,
+findVCToolChainViaCommandLine(llvm::vfs::FileSystem &VFS, const ArgList &Args,
+ std::string &Path,
MSVCToolChain::ToolsetLayout &VSLayout) {
// Don't validate the input; trust the value supplied by the user.
// The primary motivation is to prevent unnecessary file and registry access.
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir)) {
- Path = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir,
+ options::OPT__SLASH_winsysroot)) {
+ if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
+ llvm::SmallString<128> ToolsPath(A->getValue());
+ llvm::sys::path::append(ToolsPath, "VC", "Tools", "MSVC");
+ std::string VCToolsVersion;
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
+ VCToolsVersion = A->getValue();
+ else
+ VCToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath);
+ llvm::sys::path::append(ToolsPath, VCToolsVersion);
+ Path = std::string(ToolsPath.str());
+ } else {
+ Path = A->getValue();
+ }
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
return true;
}
@@ -82,8 +129,9 @@
}
// Check various environment variables to try and find a toolchain.
-static bool findVCToolChainViaEnvironment(std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
+static bool
+findVCToolChainViaEnvironment(llvm::vfs::FileSystem &VFS, std::string &Path,
+ MSVCToolChain::ToolsetLayout &VSLayout) {
// These variables are typically set by vcvarsall.bat
// when launching a developer command prompt.
if (llvm::Optional<std::string> VCToolsInstallDir =
@@ -121,34 +169,37 @@
// If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
ExeTestPath = PathEntry;
llvm::sys::path::append(ExeTestPath, "cl.exe");
- if (!llvm::sys::fs::exists(ExeTestPath))
+ if (!VFS.exists(ExeTestPath))
continue;
// cl.exe existing isn't a conclusive test for a VC toolchain; clang also
// has a cl.exe. So let's check for link.exe too.
ExeTestPath = PathEntry;
llvm::sys::path::append(ExeTestPath, "link.exe");
- if (!llvm::sys::fs::exists(ExeTestPath))
+ if (!VFS.exists(ExeTestPath))
continue;
// whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
llvm::StringRef TestPath = PathEntry;
- bool IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
+ bool IsBin =
+ llvm::sys::path::filename(TestPath).equals_insensitive("bin");
if (!IsBin) {
// Strip any architecture subdir like "amd64".
TestPath = llvm::sys::path::parent_path(TestPath);
- IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
+ IsBin = llvm::sys::path::filename(TestPath).equals_insensitive("bin");
}
if (IsBin) {
llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
- if (ParentFilename == "VC") {
+ if (ParentFilename.equals_insensitive("VC")) {
Path = std::string(ParentPath);
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
return true;
}
- if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
- || ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
+ if (ParentFilename.equals_insensitive("x86ret") ||
+ ParentFilename.equals_insensitive("x86chk") ||
+ ParentFilename.equals_insensitive("amd64ret") ||
+ ParentFilename.equals_insensitive("amd64chk")) {
Path = std::string(ParentPath);
VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
return true;
@@ -167,7 +218,7 @@
for (llvm::StringRef Prefix : ExpectedPrefixes) {
if (It == End)
goto NotAToolChain;
- if (!It->startswith(Prefix))
+ if (!It->startswith_insensitive(Prefix))
goto NotAToolChain;
++It;
}
@@ -194,8 +245,9 @@
// and find its default VC toolchain.
// This is the preferred way to discover new Visual Studios, as they're no
// longer listed in the registry.
-static bool findVCToolChainViaSetupConfig(std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
+static bool
+findVCToolChainViaSetupConfig(llvm::vfs::FileSystem &VFS, std::string &Path,
+ MSVCToolChain::ToolsetLayout &VSLayout) {
#if !defined(USE_MSVC_SETUP_API)
return false;
#else
@@ -273,7 +325,8 @@
llvm::SmallString<256> ToolchainPath(VCRootPath);
llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
ToolsVersionFile->get()->getBuffer().rtrim());
- if (!llvm::sys::fs::is_directory(ToolchainPath))
+ auto Status = VFS.status(ToolchainPath);
+ if (!Status || !Status->isDirectory())
return false;
Path = std::string(ToolchainPath.str());
@@ -315,8 +368,7 @@
SmallString<128> FilePath(MSVC.getSubDirectoryPath(
toolchains::MSVCToolChain::SubDirectoryType::Bin));
llvm::sys::path::append(FilePath, Exe);
- return std::string(llvm::sys::fs::can_execute(FilePath) ? FilePath.str()
- : Exe);
+ return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe);
}
void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -339,30 +391,34 @@
CmdArgs.push_back("-defaultlib:oldnames");
}
- if (!llvm::sys::Process::GetEnv("LIB")) {
- // If the VC environment hasn't been configured (perhaps because the user
- // did not run vcvarsall), try to build a consistent link environment. If
- // the environment variable is set however, assume the user knows what
- // they're doing.
+ // If the VC environment hasn't been configured (perhaps because the user
+ // did not run vcvarsall), try to build a consistent link environment. If
+ // the environment variable is set however, assume the user knows what
+ // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that
+ // over env vars.
+ if (!llvm::sys::Process::GetEnv("LIB") ||
+ Args.getLastArg(options::OPT__SLASH_vctoolsdir,
+ options::OPT__SLASH_winsysroot)) {
CmdArgs.push_back(Args.MakeArgString(
Twine("-libpath:") +
TC.getSubDirectoryPath(
toolchains::MSVCToolChain::SubDirectoryType::Lib)));
-
CmdArgs.push_back(Args.MakeArgString(
Twine("-libpath:") +
TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib,
"atlmfc")));
-
+ }
+ if (!llvm::sys::Process::GetEnv("LIB") ||
+ Args.getLastArg(options::OPT__SLASH_winsdkdir,
+ options::OPT__SLASH_winsysroot)) {
if (TC.useUniversalCRT()) {
std::string UniversalCRTLibPath;
- if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
+ if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
CmdArgs.push_back(
Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
}
-
std::string WindowsSdkLibPath;
- if (TC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
+ if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath))
CmdArgs.push_back(
Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
}
@@ -452,11 +508,16 @@
// Control Flow Guard checks
if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
StringRef GuardArgs = A->getValue();
- if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) {
+ if (GuardArgs.equals_insensitive("cf") ||
+ GuardArgs.equals_insensitive("cf,nochecks")) {
// MSVC doesn't yet support the "nochecks" modifier.
CmdArgs.push_back("-guard:cf");
- } else if (GuardArgs.equals_lower("cf-")) {
+ } else if (GuardArgs.equals_insensitive("cf-")) {
CmdArgs.push_back("-guard:cf-");
+ } else if (GuardArgs.equals_insensitive("ehcont")) {
+ CmdArgs.push_back("-guard:ehcont");
+ } else if (GuardArgs.equals_insensitive("ehcont-")) {
+ CmdArgs.push_back("-guard:ehcont-");
}
}
@@ -525,22 +586,22 @@
= Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
if (Linker.empty())
Linker = "link";
- if (Linker.equals_lower("lld"))
+ if (Linker.equals_insensitive("lld"))
Linker = "lld-link";
- if (Linker.equals_lower("link")) {
+ if (Linker.equals_insensitive("link")) {
// If we're using the MSVC linker, it's not sufficient to just use link
// from the program PATH, because other environments like GnuWin32 install
// their own link.exe which may come first.
linkPath = FindVisualStudioExecutable(TC, "link.exe");
- if (!TC.FoundMSVCInstall() && !llvm::sys::fs::can_execute(linkPath)) {
+ if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) {
llvm::SmallString<128> ClPath;
ClPath = TC.GetProgramPath("cl.exe");
- if (llvm::sys::fs::can_execute(ClPath)) {
+ if (canExecute(TC.getVFS(), ClPath)) {
linkPath = llvm::sys::path::parent_path(ClPath);
llvm::sys::path::append(linkPath, "link.exe");
- if (!llvm::sys::fs::can_execute(linkPath))
+ if (!canExecute(TC.getVFS(), linkPath))
C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
} else {
C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
@@ -587,7 +648,7 @@
// find it.
for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
llvm::StringRef EnvVar(Cursor);
- if (EnvVar.startswith_lower("path=")) {
+ if (EnvVar.startswith_insensitive("path=")) {
using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
constexpr size_t PrefixLen = 5; // strlen("path=")
Environment.push_back(Args.MakeArgString(
@@ -619,145 +680,6 @@
C.addCommand(std::move(LinkCmd));
}
-void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
-}
-
-std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
- Compilation &C, const JobAction &JA, const InputInfo &Output,
- const InputInfoList &Inputs, const ArgList &Args,
- const char *LinkingOutput) const {
- ArgStringList CmdArgs;
- CmdArgs.push_back("/nologo");
- CmdArgs.push_back("/c"); // Compile only.
- CmdArgs.push_back("/W0"); // No warnings.
-
- // The goal is to be able to invoke this tool correctly based on
- // any flag accepted by clang-cl.
-
- // These are spelled the same way in clang and cl.exe,.
- Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I});
-
- // Optimization level.
- if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin))
- CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi"
- : "/Oi-");
- if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) {
- if (A->getOption().getID() == options::OPT_O0) {
- CmdArgs.push_back("/Od");
- } else {
- CmdArgs.push_back("/Og");
-
- StringRef OptLevel = A->getValue();
- if (OptLevel == "s" || OptLevel == "z")
- CmdArgs.push_back("/Os");
- else
- CmdArgs.push_back("/Ot");
-
- CmdArgs.push_back("/Ob2");
- }
- }
- if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
- options::OPT_fno_omit_frame_pointer))
- CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer
- ? "/Oy"
- : "/Oy-");
- if (!Args.hasArg(options::OPT_fwritable_strings))
- CmdArgs.push_back("/GF");
-
- // Flags for which clang-cl has an alias.
- // FIXME: How can we ensure this stays in sync with relevant clang-cl options?
-
- if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
- /*Default=*/false))
- CmdArgs.push_back("/GR-");
-
- if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS,
- /*Default=*/false))
- CmdArgs.push_back("/GS-");
-
- if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections,
- options::OPT_fno_function_sections))
- CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections
- ? "/Gy"
- : "/Gy-");
- if (Arg *A = Args.getLastArg(options::OPT_fdata_sections,
- options::OPT_fno_data_sections))
- CmdArgs.push_back(
- A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-");
- if (Args.hasArg(options::OPT_fsyntax_only))
- CmdArgs.push_back("/Zs");
- if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only,
- options::OPT__SLASH_Z7))
- CmdArgs.push_back("/Z7");
-
- std::vector<std::string> Includes =
- Args.getAllArgValues(options::OPT_include);
- for (const auto &Include : Includes)
- CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include));
-
- // Flags that can simply be passed through.
- Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD);
- Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd);
- Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX);
- Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_);
- Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH);
- Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl);
-
- // The order of these flags is relevant, so pick the last one.
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd,
- options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
- A->render(Args, CmdArgs);
-
- // Use MSVC's default threadsafe statics behaviour unless there was a flag.
- if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
- options::OPT_fno_threadsafe_statics)) {
- CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
- ? "/Zc:threadSafeInit"
- : "/Zc:threadSafeInit-");
- }
-
- // Control Flow Guard checks
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
- StringRef GuardArgs = A->getValue();
- if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) {
- // MSVC doesn't yet support the "nochecks" modifier.
- CmdArgs.push_back("/guard:cf");
- } else if (GuardArgs.equals_lower("cf-")) {
- CmdArgs.push_back("/guard:cf-");
- }
- }
-
- // Pass through all unknown arguments so that the fallback command can see
- // them too.
- Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);
-
- // Input filename.
- assert(Inputs.size() == 1);
- const InputInfo &II = Inputs[0];
- assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
- CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp");
- if (II.isFilename())
- CmdArgs.push_back(II.getFilename());
- else
- II.getInputArg().renderAsInput(Args, CmdArgs);
-
- // Output filename.
- assert(Output.getType() == types::TY_Object);
- const char *Fo =
- Args.MakeArgString(std::string("/Fo") + Output.getFilename());
- CmdArgs.push_back(Fo);
-
- std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe");
- return std::make_unique<Command>(
- JA, *this, ResponseFileSupport::AtFileUTF16(), Args.MakeArgString(Exec),
- CmdArgs, Inputs, Output);
-}
-
MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
@@ -770,9 +692,9 @@
// use. Check the environment next, in case we're being invoked from a VS
// command prompt. Failing that, just try to find the newest Visual Studio
// version we can and use its default VC toolchain.
- findVCToolChainViaCommandLine(Args, VCToolChainPath, VSLayout) ||
- findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) ||
- findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) ||
+ findVCToolChainViaCommandLine(getVFS(), Args, VCToolChainPath, VSLayout) ||
+ findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, VSLayout) ||
+ findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath, VSLayout) ||
findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
}
@@ -1068,36 +990,67 @@
// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
// directory by name and uses the last one of the list.
// So we compare entry names lexicographically to find the greatest one.
-static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
+static bool getWindows10SDKVersionFromPath(llvm::vfs::FileSystem &VFS,
+ const std::string &SDKPath,
std::string &SDKVersion) {
- SDKVersion.clear();
-
- std::error_code EC;
llvm::SmallString<128> IncludePath(SDKPath);
llvm::sys::path::append(IncludePath, "Include");
- for (llvm::sys::fs::directory_iterator DirIt(IncludePath, EC), DirEnd;
- DirIt != DirEnd && !EC; DirIt.increment(EC)) {
- if (!llvm::sys::fs::is_directory(DirIt->path()))
- continue;
- StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
- // If WDK is installed, there could be subfolders like "wdf" in the
- // "Include" directory.
- // Allow only directories which names start with "10.".
- if (!CandidateName.startswith("10."))
- continue;
- if (CandidateName > SDKVersion)
- SDKVersion = std::string(CandidateName);
- }
-
+ SDKVersion = getHighestNumericTupleInDirectory(VFS, IncludePath);
return !SDKVersion.empty();
}
+static bool getWindowsSDKDirViaCommandLine(llvm::vfs::FileSystem &VFS,
+ const ArgList &Args,
+ std::string &Path, int &Major,
+ std::string &Version) {
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir,
+ options::OPT__SLASH_winsysroot)) {
+ // Don't validate the input; trust the value supplied by the user.
+ // The motivation is to prevent unnecessary file and registry access.
+ llvm::VersionTuple SDKVersion;
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
+ SDKVersion.tryParse(A->getValue());
+
+ if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
+ llvm::SmallString<128> SDKPath(A->getValue());
+ llvm::sys::path::append(SDKPath, "Windows Kits");
+ if (!SDKVersion.empty())
+ llvm::sys::path::append(SDKPath, Twine(SDKVersion.getMajor()));
+ else
+ llvm::sys::path::append(
+ SDKPath, getHighestNumericTupleInDirectory(VFS, SDKPath));
+ Path = std::string(SDKPath.str());
+ } else {
+ Path = A->getValue();
+ }
+
+ if (!SDKVersion.empty()) {
+ Major = SDKVersion.getMajor();
+ Version = SDKVersion.getAsString();
+ } else if (getWindows10SDKVersionFromPath(VFS, Path, Version)) {
+ Major = 10;
+ }
+ return true;
+ }
+ return false;
+}
+
/// Get Windows SDK installation directory.
-static bool getWindowsSDKDir(std::string &Path, int &Major,
+static bool getWindowsSDKDir(llvm::vfs::FileSystem &VFS, const ArgList &Args,
+ std::string &Path, int &Major,
std::string &WindowsSDKIncludeVersion,
std::string &WindowsSDKLibVersion) {
- std::string RegistrySDKVersion;
+ // Trust /winsdkdir and /winsdkversion if present.
+ if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major,
+ WindowsSDKIncludeVersion)) {
+ WindowsSDKLibVersion = WindowsSDKIncludeVersion;
+ return true;
+ }
+
+ // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to registry.
+
// Try the Windows registry.
+ std::string RegistrySDKVersion;
if (!getSystemRegistryString(
"SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
"InstallationFolder", Path, &RegistrySDKVersion))
@@ -1119,7 +1072,7 @@
for (const char *Test : Tests) {
llvm::SmallString<128> TestPath(Path);
llvm::sys::path::append(TestPath, "Lib", Test);
- if (llvm::sys::fs::exists(TestPath.c_str())) {
+ if (VFS.exists(TestPath)) {
WindowsSDKLibVersion = Test;
break;
}
@@ -1127,7 +1080,7 @@
return !WindowsSDKLibVersion.empty();
}
if (Major == 10) {
- if (!getWindows10SDKVersionFromPath(Path, WindowsSDKIncludeVersion))
+ if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion))
return false;
WindowsSDKLibVersion = WindowsSDKIncludeVersion;
return true;
@@ -1137,15 +1090,16 @@
}
// Gets the library path required to link against the Windows SDK.
-bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
+bool MSVCToolChain::getWindowsSDKLibraryPath(
+ const ArgList &Args, std::string &path) const {
std::string sdkPath;
int sdkMajor = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
path.clear();
- if (!getWindowsSDKDir(sdkPath, sdkMajor, windowsSDKIncludeVersion,
- windowsSDKLibVersion))
+ if (!getWindowsSDKDir(getVFS(), Args, sdkPath, sdkMajor,
+ windowsSDKIncludeVersion, windowsSDKLibVersion))
return false;
llvm::SmallString<128> libPath(sdkPath);
@@ -1179,10 +1133,21 @@
llvm::SmallString<128> TestPath(
getSubDirectoryPath(SubDirectoryType::Include));
llvm::sys::path::append(TestPath, "stdlib.h");
- return !llvm::sys::fs::exists(TestPath);
+ return !getVFS().exists(TestPath);
}
-static bool getUniversalCRTSdkDir(std::string &Path, std::string &UCRTVersion) {
+static bool getUniversalCRTSdkDir(llvm::vfs::FileSystem &VFS,
+ const ArgList &Args, std::string &Path,
+ std::string &UCRTVersion) {
+ // If /winsdkdir is passed, use it as location for the UCRT too.
+ // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir?
+ int Major;
+ if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major, UCRTVersion))
+ return true;
+
+ // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
+ // registry.
+
// vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
// for the specific key "KitsRoot10". So do we.
if (!getSystemRegistryString(
@@ -1190,15 +1155,16 @@
Path, nullptr))
return false;
- return getWindows10SDKVersionFromPath(Path, UCRTVersion);
+ return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion);
}
-bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
+bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
+ std::string &Path) const {
std::string UniversalCRTSdkPath;
std::string UCRTVersion;
Path.clear();
- if (!getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion))
+ if (!getUniversalCRTSdkDir(getVFS(), Args, UniversalCRTSdkPath, UCRTVersion))
return false;
StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
@@ -1279,22 +1245,35 @@
for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
addSystemInclude(DriverArgs, CC1Args, Path);
+ auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool {
+ if (auto Val = llvm::sys::Process::GetEnv(Var)) {
+ SmallVector<StringRef, 8> Dirs;
+ StringRef(*Val).split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+ if (!Dirs.empty()) {
+ addSystemIncludes(DriverArgs, CC1Args, Dirs);
+ return true;
+ }
+ }
+ return false;
+ };
+
+ // Add %INCLUDE%-like dirs via /external:env: flags.
+ for (const auto &Var :
+ DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) {
+ AddSystemIncludesFromEnv(Var);
+ }
+
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
- // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
- // Skip if the user expressly set a vctoolsdir
- if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir)) {
- if (llvm::Optional<std::string> cl_include_dir =
- llvm::sys::Process::GetEnv("INCLUDE")) {
- SmallVector<StringRef, 8> Dirs;
- StringRef(*cl_include_dir)
- .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
- for (StringRef Dir : Dirs)
- addSystemInclude(DriverArgs, CC1Args, Dir);
- if (!Dirs.empty())
- return;
- }
+ // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search
+ // paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir.
+ if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir,
+ options::OPT__SLASH_winsysroot)) {
+ bool Found = AddSystemIncludesFromEnv("INCLUDE");
+ Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE");
+ if (Found)
+ return;
}
// When built with access to the proper Windows APIs, try to actually find
@@ -1308,33 +1287,34 @@
if (useUniversalCRT()) {
std::string UniversalCRTSdkPath;
std::string UCRTVersion;
- if (getUniversalCRTSdkDir(UniversalCRTSdkPath, UCRTVersion)) {
+ if (getUniversalCRTSdkDir(getVFS(), DriverArgs, UniversalCRTSdkPath,
+ UCRTVersion)) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
"Include", UCRTVersion, "ucrt");
}
}
std::string WindowsSDKDir;
- int major;
+ int major = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
- if (getWindowsSDKDir(WindowsSDKDir, major, windowsSDKIncludeVersion,
- windowsSDKLibVersion)) {
+ if (getWindowsSDKDir(getVFS(), DriverArgs, WindowsSDKDir, major,
+ windowsSDKIncludeVersion, windowsSDKLibVersion)) {
if (major >= 8) {
// Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
// Anyway, llvm::sys::path::append is able to manage it.
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include", windowsSDKIncludeVersion,
+ "Include", windowsSDKIncludeVersion,
"shared");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include", windowsSDKIncludeVersion,
+ "Include", windowsSDKIncludeVersion,
"um");
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include", windowsSDKIncludeVersion,
+ "Include", windowsSDKIncludeVersion,
"winrt");
} else {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
- "include");
+ "Include");
}
}
@@ -1371,8 +1351,8 @@
if (MSVT.empty() &&
Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC)) {
- // -fms-compatibility-version=19.11 is default, aka 2017, 15.3
- MSVT = VersionTuple(19, 11);
+ // -fms-compatibility-version=19.14 is default, aka 2017, 15.7
+ MSVT = VersionTuple(19, 14);
}
return MSVT;
}
@@ -1523,6 +1503,18 @@
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
}
+static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL,
+ const OptTable &Opts) {
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_));
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names));
+}
+
+static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL,
+ const OptTable &Opts) {
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase));
+ DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names));
+}
+
llvm::opt::DerivedArgList *
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
StringRef BoundArch,
@@ -1565,6 +1557,12 @@
} else if (A->getOption().matches(options::OPT_D)) {
// Translate -Dfoo#bar into -Dfoo=bar.
TranslateDArg(A, *DAL, Opts);
+ } else if (A->getOption().matches(options::OPT__SLASH_permissive)) {
+ // Expand /permissive
+ TranslatePermissive(A, *DAL, Opts);
+ } else if (A->getOption().matches(options::OPT__SLASH_permissive_)) {
+ // Expand /permissive-
+ TranslatePermissiveMinus(A, *DAL, Opts);
} else if (OFK != Action::OFK_HIP) {
// HIP Toolchain translates input args by itself.
DAL->append(A);
@@ -1573,3 +1571,13 @@
return DAL;
}
+
+void MSVCToolChain::addClangTargetOptions(
+ const ArgList &DriverArgs, ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const {
+ // MSVC STL kindly allows removing all usages of typeid by defining
+ // _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti
+ if (DriverArgs.hasArg(options::OPT_fno_rtti, options::OPT_frtti,
+ /*Default=*/false))
+ CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
+}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/MSVC.h b/src/llvm-project/clang/lib/Driver/ToolChains/MSVC.h
index dba99ed..19d94c5 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/MSVC.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/MSVC.h
@@ -34,27 +34,6 @@
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-
-class LLVM_LIBRARY_VISIBILITY Compiler : public Tool {
-public:
- Compiler(const ToolChain &TC)
- : Tool("visualstudio::Compiler", "compiler", TC) {}
-
- bool hasIntegratedAssembler() const override { return true; }
- bool hasIntegratedCPP() const override { return true; }
- bool isLinkJob() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-
- std::unique_ptr<Command> GetCommand(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const;
-};
} // end namespace visualstudio
} // end namespace tools
@@ -126,9 +105,10 @@
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- bool getWindowsSDKLibraryPath(std::string &path) const;
- /// Check if Universal CRT should be used if available
- bool getUniversalCRTLibraryPath(std::string &path) const;
+ bool getWindowsSDKLibraryPath(
+ const llvm::opt::ArgList &Args, std::string &path) const;
+ bool getUniversalCRTLibraryPath(const llvm::opt::ArgList &Args,
+ std::string &path) const;
bool useUniversalCRT() const;
VersionTuple
computeMSVCVersion(const Driver *D,
@@ -142,6 +122,11 @@
bool FoundMSVCInstall() const { return !VCToolChainPath.empty(); }
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+
protected:
void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp
index f6cead4..7ba729f 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -7,12 +7,12 @@
//===----------------------------------------------------------------------===//
#include "MinGW.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
@@ -136,10 +136,13 @@
llvm_unreachable("Unsupported target architecture.");
}
- if (Args.hasArg(options::OPT_mwindows)) {
+ Arg *SubsysArg =
+ Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole);
+ if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) {
CmdArgs.push_back("--subsystem");
CmdArgs.push_back("windows");
- } else if (Args.hasArg(options::OPT_mconsole)) {
+ } else if (SubsysArg &&
+ SubsysArg->getOption().matches(options::OPT_mconsole)) {
CmdArgs.push_back("--subsystem");
CmdArgs.push_back("console");
}
@@ -338,6 +341,7 @@
continue;
if (CandidateVersion <= Version)
continue;
+ Version = CandidateVersion;
Ver = std::string(VersionText);
GccLibDir = LI->path();
}
@@ -426,7 +430,7 @@
NativeLLVMSupport =
Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
- .equals_lower("lld");
+ .equals_insensitive("lld");
}
bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Minix.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Minix.cpp
index 44479a2..5bceb9a 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Minix.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Minix.cpp
@@ -8,9 +8,9 @@
#include "Minix.h"
#include "CommonArgs.h"
-#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/VirtualFileSystem.h"
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Myriad.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Myriad.cpp
index ab0df5d..f314666 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Myriad.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Myriad.cpp
@@ -260,7 +260,7 @@
const Multilib &Multilib = GCCInstallation.getMultilib();
addLibStdCXXIncludePaths(
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
- "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
+ TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args);
}
// MyriadToolChain handles several triples:
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
index 8a150c3..753459c 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
#include "NaCl.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
index 48bf061..1ce5a2a 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -452,8 +452,8 @@
void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/g++", "", "", "",
- "", DriverArgs, CC1Args);
+ addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/g++", "", "",
+ DriverArgs, CC1Args);
}
llvm::ExceptionHandling NetBSD::GetExceptionModel(const ArgList &Args) const {
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
index 0dc12c7..714325a 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -8,8 +8,8 @@
#include "RISCVToolchain.h"
#include "CommonArgs.h"
-#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
@@ -112,7 +112,8 @@
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
- "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
+ TripleStr, Multilib.includeSuffix(), DriverArgs,
+ CC1Args);
}
std::string RISCVToolChain::computeSysRoot() const {
@@ -180,14 +181,15 @@
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
}
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_u);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
Args.AddAllArgs(CmdArgs,
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
-
// TODO: add C++ includes and libs if compiling C++.
if (!Args.hasArg(options::OPT_nostdlib) &&
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/ROCm.h b/src/llvm-project/clang/lib/Driver/ToolChains/ROCm.h
index 21e62a4..bb482be 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/ROCm.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/ROCm.h
@@ -42,9 +42,16 @@
struct Candidate {
llvm::SmallString<0> Path;
bool StrictChecking;
+ // Release string for ROCm packages built with SPACK if not empty. The
+ // installation directories of ROCm packages built with SPACK follow the
+ // convention <package_name>-<rocm_release_string>-<hash>.
+ std::string SPACKReleaseStr;
- Candidate(std::string Path, bool StrictChecking = false)
- : Path(Path), StrictChecking(StrictChecking) {}
+ bool isSPACK() const { return !SPACKReleaseStr.empty(); }
+ Candidate(std::string Path, bool StrictChecking = false,
+ StringRef SPACKReleaseStr = {})
+ : Path(Path), StrictChecking(StrictChecking),
+ SPACKReleaseStr(SPACKReleaseStr.str()) {}
};
const Driver &D;
@@ -67,6 +74,8 @@
StringRef RocmPathArg;
// ROCm device library paths specified by --rocm-device-lib-path.
std::vector<std::string> RocmDeviceLibPathArg;
+ // HIP runtime path specified by --hip-path.
+ StringRef HIPPathArg;
// HIP version specified by --hip-version.
StringRef HIPVersionArg;
// Wheter -nogpulib is specified.
@@ -88,6 +97,9 @@
SmallString<0> OpenCL;
SmallString<0> HIP;
+ // Asan runtime library
+ SmallString<0> AsanRTL;
+
// Libraries swapped based on compile flags.
ConditionalLibrary WavefrontSize64;
ConditionalLibrary FiniteOnly;
@@ -95,6 +107,11 @@
ConditionalLibrary DenormalsAreZero;
ConditionalLibrary CorrectlyRoundedSqrt;
+ // Cache ROCm installation search paths.
+ SmallVector<Candidate, 4> ROCmSearchDirs;
+ bool PrintROCmSearchDirs;
+ bool Verbose;
+
bool allGenericLibsValid() const {
return !OCML.empty() && !OCKL.empty() && !OpenCL.empty() && !HIP.empty() &&
WavefrontSize64.isValid() && FiniteOnly.isValid() &&
@@ -104,7 +121,14 @@
void scanLibDevicePath(llvm::StringRef Path);
bool parseHIPVersionFile(llvm::StringRef V);
- SmallVector<Candidate, 4> getInstallationPathCandidates();
+ const SmallVectorImpl<Candidate> &getInstallationPathCandidates();
+
+ /// Find the path to a SPACK package under the ROCm candidate installation
+ /// directory if the candidate is a SPACK ROCm candidate. \returns empty
+ /// string if the candidate is not SPACK ROCm candidate or the requested
+ /// package is not found.
+ llvm::SmallString<0> findSPACKPackage(const Candidate &Cand,
+ StringRef PackageName);
public:
RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
@@ -112,12 +136,13 @@
bool DetectHIPRuntime = true,
bool DetectDeviceLib = false);
- /// Add arguments needed to link default bitcode libraries.
- void addCommonBitcodeLibCC1Args(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- StringRef LibDeviceFile, bool Wave64,
- bool DAZ, bool FiniteOnly, bool UnsafeMathOpt,
- bool FastRelaxedMath, bool CorrectSqrt) const;
+ /// Get file paths of default bitcode libraries common to AMDGPU based
+ /// toolchains.
+ llvm::SmallVector<std::string, 12>
+ getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs,
+ StringRef LibDeviceFile, bool Wave64, bool DAZ,
+ bool FiniteOnly, bool UnsafeMathOpt,
+ bool FastRelaxedMath, bool CorrectSqrt) const;
/// Check whether we detected a valid HIP runtime.
bool hasHIPRuntime() const { return HasHIPRuntime; }
@@ -166,6 +191,9 @@
return HIP;
}
+ /// Returns empty string of Asan runtime library is not available.
+ StringRef getAsanRTLPath() const { return AsanRTL; }
+
StringRef getWavefrontSize64Path(bool Enabled) const {
return WavefrontSize64.get(Enabled);
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp
index 4ed4d83..4d1af09 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -283,9 +283,7 @@
const GCCVersion &Version = GCCInstallation.getVersion();
// The primary search for libstdc++ supports multiarch variants.
- addLibStdCXXIncludePaths(LibDir.str() + "/../include", "/c++/" + Version.Text,
- TripleStr,
- /*GCCMultiarchTriple*/ "",
- /*TargetMultiarchTriple*/ "",
- Multilib.includeSuffix(), DriverArgs, CC1Args);
+ addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
+ TripleStr, Multilib.includeSuffix(), DriverArgs,
+ CC1Args);
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp b/src/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 6b65488..19f3571 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -26,9 +26,9 @@
/// Following the conventions in https://wiki.debian.org/Multiarch/Tuples,
/// we remove the vendor field to form the multiarch triple.
-static std::string getMultiarchTriple(const Driver &D,
- const llvm::Triple &TargetTriple,
- StringRef SysRoot) {
+std::string WebAssembly::getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const {
return (TargetTriple.getArchName() + "-" +
TargetTriple.getOSAndEnvironmentName()).str();
}
@@ -77,6 +77,16 @@
const char *Crt1 = "crt1.o";
const char *Entry = NULL;
+
+ // If crt1-command.o exists, it supports new-style commands, so use it.
+ // Otherwise, use the old crt1.o. This is a temporary transition measure.
+ // Once WASI libc no longer needs to support LLVM versions which lack
+ // support for new-style command, it can make crt1.o the same as
+ // crt1-command.o. And once LLVM no longer needs to support WASI libc
+ // versions before that, it can switch to using crt1-command.o.
+ if (ToolChain.GetFilePath("crt1-command.o") != "crt1-command.o")
+ Crt1 = "crt1-command.o";
+
if (const Arg *A = Args.getLastArg(options::OPT_mexec_model_EQ)) {
StringRef CM = A->getValue();
if (CM == "command") {
@@ -272,12 +282,6 @@
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
<< "-fwasm-exceptions"
<< "-mno-exception-handling";
- // '-fwasm-exceptions' is not compatible with '-mno-reference-types'
- if (DriverArgs.hasFlag(options::OPT_mno_reference_types,
- options::OPT_mexception_handing, false))
- getDriver().Diag(diag::err_drv_argument_not_allowed_with)
- << "-fwasm-exceptions"
- << "-mno-reference-types";
// '-fwasm-exceptions' is not compatible with
// '-mllvm -enable-emscripten-cxx-exceptions'
for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
@@ -286,11 +290,39 @@
<< "-fwasm-exceptions"
<< "-mllvm -enable-emscripten-cxx-exceptions";
}
- // '-fwasm-exceptions' implies exception-handling and reference-types
+ // '-fwasm-exceptions' implies exception-handling feature
CC1Args.push_back("-target-feature");
CC1Args.push_back("+exception-handling");
- CC1Args.push_back("-target-feature");
- CC1Args.push_back("+reference-types");
+ }
+
+ for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
+ StringRef Opt = A->getValue(0);
+ if (Opt.startswith("-emscripten-cxx-exceptions-allowed")) {
+ // '-mllvm -emscripten-cxx-exceptions-allowed' should be used with
+ // '-mllvm -enable-emscripten-cxx-exceptions'
+ bool EmExceptionArgExists = false;
+ for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
+ if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions") {
+ EmExceptionArgExists = true;
+ break;
+ }
+ }
+ if (!EmExceptionArgExists)
+ getDriver().Diag(diag::err_drv_argument_only_allowed_with)
+ << "-mllvm -emscripten-cxx-exceptions-allowed"
+ << "-mllvm -enable-emscripten-cxx-exceptions";
+
+ // Prevent functions specified in -emscripten-cxx-exceptions-allowed list
+ // from being inlined before reaching the wasm backend.
+ StringRef FuncNamesStr = Opt.split('=').second;
+ SmallVector<StringRef, 4> FuncNames;
+ FuncNamesStr.split(FuncNames, ',');
+ for (auto Name : FuncNames) {
+ CC1Args.push_back("-mllvm");
+ CC1Args.push_back(DriverArgs.MakeArgString("--force-attribute=" + Name +
+ ":noinline"));
+ }
+ }
}
}
diff --git a/src/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h b/src/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h
index 616bfb5..8a3f82d 100644
--- a/src/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h
+++ b/src/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h
@@ -70,6 +70,10 @@
const char *getDefaultLinker() const override { return "wasm-ld"; }
Tool *buildLinker() const override;
+
+ std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const override;
};
} // end namespace toolchains
diff --git a/src/llvm-project/clang/lib/Driver/Types.cpp b/src/llvm-project/clang/lib/Driver/Types.cpp
index e898334..b7ccdf2 100644
--- a/src/llvm-project/clang/lib/Driver/Types.cpp
+++ b/src/llvm-project/clang/lib/Driver/Types.cpp
@@ -126,7 +126,7 @@
case TY_Asm:
case TY_C: case TY_PP_C:
- case TY_CL:
+ case TY_CL: case TY_CLCXX:
case TY_CUDA: case TY_PP_CUDA:
case TY_CUDA_DEVICE:
case TY_HIP:
@@ -160,6 +160,8 @@
}
}
+bool types::isOpenCL(ID Id) { return Id == TY_CL || Id == TY_CLCXX; }
+
bool types::isCXX(ID Id) {
switch (Id) {
default:
@@ -247,6 +249,7 @@
.Case("cc", TY_CXX)
.Case("CC", TY_CXX)
.Case("cl", TY_CL)
+ .Case("clcpp", TY_CLCXX)
.Case("cp", TY_CXX)
.Case("cu", TY_CUDA)
.Case("hh", TY_CXXHeader)
@@ -325,12 +328,10 @@
// Filter to compiler mode. When the compiler is run as a preprocessor then
// compilation is not an option.
// -S runs the compiler in Assembly listing mode.
- // -test-io is used by Flang to run InputOutputTest action
if (Driver.CCCIsCPP() || DAL.getLastArg(options::OPT_E) ||
DAL.getLastArg(options::OPT__SLASH_EP) ||
DAL.getLastArg(options::OPT_M, options::OPT_MM) ||
- DAL.getLastArg(options::OPT__SLASH_P) ||
- DAL.getLastArg(options::OPT_test_io))
+ DAL.getLastArg(options::OPT__SLASH_P))
LastPhase = phases::Preprocess;
// --precompile only runs up to precompilation.
@@ -396,6 +397,7 @@
case types::TY_ObjCXX:
return types::TY_ObjCXXHeader;
case types::TY_CL:
+ case types::TY_CLCXX:
return types::TY_CLHeader;
}
}
diff --git a/src/llvm-project/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/src/llvm-project/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
index 7565626..a3d388a 100644
--- a/src/llvm-project/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ b/src/llvm-project/clang/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -1080,6 +1080,7 @@
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLOpaqueType:
case CK_IntToOCLSampler:
+ case CK_MatrixCast:
return false;
case CK_BooleanToSignedIntegral:
diff --git a/src/llvm-project/clang/lib/Format/BreakableToken.cpp b/src/llvm-project/clang/lib/Format/BreakableToken.cpp
index f179ac6..4559048 100644
--- a/src/llvm-project/clang/lib/Format/BreakableToken.cpp
+++ b/src/llvm-project/clang/lib/Format/BreakableToken.cpp
@@ -757,6 +757,9 @@
assert(Tok.is(TT_LineComment) &&
"line comment section must start with a line comment");
FormatToken *LineTok = nullptr;
+ // How many spaces we changed in the first line of the section, this will be
+ // applied in all following lines
+ int FirstLineSpaceChange = 0;
for (const FormatToken *CurrentTok = &Tok;
CurrentTok && CurrentTok->is(TT_LineComment);
CurrentTok = CurrentTok->Next) {
@@ -768,44 +771,72 @@
TokenText.split(Lines, "\n");
Content.resize(Lines.size());
ContentColumn.resize(Lines.size());
- OriginalContentColumn.resize(Lines.size());
+ PrefixSpaceChange.resize(Lines.size());
Tokens.resize(Lines.size());
Prefix.resize(Lines.size());
OriginalPrefix.resize(Lines.size());
for (size_t i = FirstLineIndex, e = Lines.size(); i < e; ++i) {
Lines[i] = Lines[i].ltrim(Blanks);
StringRef IndentPrefix = getLineCommentIndentPrefix(Lines[i], Style);
- assert((TokenText.startswith("//") || TokenText.startswith("#")) &&
- "unsupported line comment prefix, '//' and '#' are supported");
- OriginalPrefix[i] = Prefix[i] = IndentPrefix;
- if (Lines[i].size() > Prefix[i].size() &&
- isAlphanumeric(Lines[i][Prefix[i].size()])) {
- if (Prefix[i] == "//")
- Prefix[i] = "// ";
- else if (Prefix[i] == "///")
- Prefix[i] = "/// ";
- else if (Prefix[i] == "//!")
- Prefix[i] = "//! ";
- else if (Prefix[i] == "///<")
- Prefix[i] = "///< ";
- else if (Prefix[i] == "//!<")
- Prefix[i] = "//!< ";
- else if (Prefix[i] == "#")
- Prefix[i] = "# ";
- else if (Prefix[i] == "##")
- Prefix[i] = "## ";
- else if (Prefix[i] == "###")
- Prefix[i] = "### ";
- else if (Prefix[i] == "####")
- Prefix[i] = "#### ";
+ OriginalPrefix[i] = IndentPrefix;
+ const unsigned SpacesInPrefix =
+ std::count(IndentPrefix.begin(), IndentPrefix.end(), ' ');
+
+ // On the first line of the comment section we calculate how many spaces
+ // are to be added or removed, all lines after that just get only the
+ // change and we will not look at the maximum anymore. Additionally to the
+ // actual first line, we calculate that when the non space Prefix changes,
+ // e.g. from "///" to "//".
+ if (i == 0 || OriginalPrefix[i].rtrim(Blanks) !=
+ OriginalPrefix[i - 1].rtrim(Blanks)) {
+ if (SpacesInPrefix < Style.SpacesInLineCommentPrefix.Minimum &&
+ Lines[i].size() > IndentPrefix.size() &&
+ isAlphanumeric(Lines[i][IndentPrefix.size()])) {
+ FirstLineSpaceChange =
+ Style.SpacesInLineCommentPrefix.Minimum - SpacesInPrefix;
+ } else if (SpacesInPrefix > Style.SpacesInLineCommentPrefix.Maximum) {
+ FirstLineSpaceChange =
+ Style.SpacesInLineCommentPrefix.Maximum - SpacesInPrefix;
+ } else {
+ FirstLineSpaceChange = 0;
+ }
+ }
+
+ if (Lines[i].size() != IndentPrefix.size()) {
+ PrefixSpaceChange[i] = FirstLineSpaceChange;
+
+ if (SpacesInPrefix + PrefixSpaceChange[i] <
+ Style.SpacesInLineCommentPrefix.Minimum) {
+ PrefixSpaceChange[i] += Style.SpacesInLineCommentPrefix.Minimum -
+ (SpacesInPrefix + PrefixSpaceChange[i]);
+ }
+
+ assert(Lines[i].size() > IndentPrefix.size());
+ const auto FirstNonSpace = Lines[i][IndentPrefix.size()];
+ const auto AllowsSpaceChange =
+ SpacesInPrefix != 0 ||
+ (isAlphanumeric(FirstNonSpace) ||
+ (FirstNonSpace == '}' && FirstLineSpaceChange != 0));
+
+ if (PrefixSpaceChange[i] > 0 && AllowsSpaceChange) {
+ Prefix[i] = IndentPrefix.str();
+ Prefix[i].append(PrefixSpaceChange[i], ' ');
+ } else if (PrefixSpaceChange[i] < 0 && AllowsSpaceChange) {
+ Prefix[i] = IndentPrefix
+ .drop_back(std::min<std::size_t>(
+ -PrefixSpaceChange[i], SpacesInPrefix))
+ .str();
+ } else {
+ Prefix[i] = IndentPrefix.str();
+ }
+ } else {
+ // If the IndentPrefix is the whole line, there is no content and we
+ // drop just all space
+ Prefix[i] = IndentPrefix.drop_back(SpacesInPrefix).str();
}
Tokens[i] = LineTok;
Content[i] = Lines[i].substr(IndentPrefix.size());
- OriginalContentColumn[i] =
- StartColumn + encoding::columnWidthWithTabs(OriginalPrefix[i],
- StartColumn,
- Style.TabWidth, Encoding);
ContentColumn[i] =
StartColumn + encoding::columnWidthWithTabs(Prefix[i], StartColumn,
Style.TabWidth, Encoding);
@@ -848,10 +879,9 @@
Encoding);
}
-unsigned BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
- bool Break) const {
- if (Break)
- return OriginalContentColumn[LineIndex];
+unsigned
+BreakableLineCommentSection::getContentStartColumn(unsigned LineIndex,
+ bool /*Break*/) const {
return ContentColumn[LineIndex];
}
@@ -864,16 +894,10 @@
unsigned BreakOffsetInToken =
Text.data() - tokenAt(LineIndex).TokenText.data() + Split.first;
unsigned CharsToRemove = Split.second;
- // Compute the size of the new indent, including the size of the new prefix of
- // the newly broken line.
- unsigned IndentAtLineBreak = OriginalContentColumn[LineIndex] +
- Prefix[LineIndex].size() -
- OriginalPrefix[LineIndex].size();
- assert(IndentAtLineBreak >= Prefix[LineIndex].size());
Whitespaces.replaceWhitespaceInToken(
tokenAt(LineIndex), BreakOffsetInToken, CharsToRemove, "",
Prefix[LineIndex], InPPDirective, /*Newlines=*/1,
- /*Spaces=*/IndentAtLineBreak - Prefix[LineIndex].size());
+ /*Spaces=*/ContentColumn[LineIndex] - Prefix[LineIndex].size());
}
BreakableComment::Split BreakableLineCommentSection::getReflowSplit(
@@ -971,14 +995,12 @@
}
if (OriginalPrefix[LineIndex] != Prefix[LineIndex]) {
// Adjust the prefix if necessary.
-
- // Take care of the space possibly introduced after a decoration.
- assert(Prefix[LineIndex] == (OriginalPrefix[LineIndex] + " ").str() &&
- "Expecting a line comment prefix to differ from original by at most "
- "a space");
+ const auto SpacesToRemove = -std::min(PrefixSpaceChange[LineIndex], 0);
+ const auto SpacesToAdd = std::max(PrefixSpaceChange[LineIndex], 0);
Whitespaces.replaceWhitespaceInToken(
- tokenAt(LineIndex), OriginalPrefix[LineIndex].size(), 0, "", "",
- /*InPPDirective=*/false, /*Newlines=*/0, /*Spaces=*/1);
+ tokenAt(LineIndex), OriginalPrefix[LineIndex].size() - SpacesToRemove,
+ /*ReplaceChars=*/SpacesToRemove, "", "", /*InPPDirective=*/false,
+ /*Newlines=*/0, /*Spaces=*/SpacesToAdd);
}
}
diff --git a/src/llvm-project/clang/lib/Format/BreakableToken.h b/src/llvm-project/clang/lib/Format/BreakableToken.h
index 41b19f8..190144a 100644
--- a/src/llvm-project/clang/lib/Format/BreakableToken.h
+++ b/src/llvm-project/clang/lib/Format/BreakableToken.h
@@ -465,15 +465,23 @@
// then the original prefix is "// ".
SmallVector<StringRef, 16> OriginalPrefix;
- // Prefix[i] contains the intended leading "//" with trailing spaces to
- // account for the indentation of content within the comment at line i after
- // formatting. It can be different than the original prefix when the original
- // line starts like this:
- // //content
- // Then the original prefix is "//", but the prefix is "// ".
- SmallVector<StringRef, 16> Prefix;
+ /// Prefix[i] + SpacesToAdd[i] contains the intended leading "//" with
+ /// trailing spaces to account for the indentation of content within the
+ /// comment at line i after formatting. It can be different than the original
+ /// prefix.
+ /// When the original line starts like this:
+ /// //content
+ /// Then the OriginalPrefix[i] is "//", but the Prefix[i] is "// " in the LLVM
+ /// style.
+ /// When the line starts like:
+ /// // content
+ /// And we want to remove the spaces the OriginalPrefix[i] is "// " and
+ /// Prefix[i] is "//".
+ SmallVector<std::string, 16> Prefix;
- SmallVector<unsigned, 16> OriginalContentColumn;
+ /// How many spaces are added or removed from the OriginalPrefix to form
+ /// Prefix.
+ SmallVector<int, 16> PrefixSpaceChange;
/// The token to which the last line of this breakable token belongs
/// to; nullptr if that token is the initial token.
diff --git a/src/llvm-project/clang/lib/Format/ContinuationIndenter.cpp b/src/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
index 7198671..8fbc15f 100644
--- a/src/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
+++ b/src/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
@@ -1651,7 +1651,7 @@
StringRef OldDelimiter = *getRawStringDelimiter(Current.TokenText);
StringRef NewDelimiter =
getCanonicalRawStringDelimiter(Style, RawStringStyle.Language);
- if (NewDelimiter.empty() || OldDelimiter.empty())
+ if (NewDelimiter.empty())
NewDelimiter = OldDelimiter;
// The text of a raw string is between the leading 'R"delimiter(' and the
// trailing 'delimiter)"'.
@@ -1906,12 +1906,12 @@
LineState &State, bool AllowBreak) {
unsigned StartColumn = State.Column - Current.ColumnWidth;
if (Current.isStringLiteral()) {
- // FIXME: String literal breaking is currently disabled for C#, Java and
- // JavaScript, as it requires strings to be merged using "+" which we
+ // FIXME: String literal breaking is currently disabled for C#, Java, Json
+ // and JavaScript, as it requires strings to be merged using "+" which we
// don't support.
if (Style.Language == FormatStyle::LK_Java ||
Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp() ||
- !Style.BreakStringLiterals || !AllowBreak)
+ Style.isJson() || !Style.BreakStringLiterals || !AllowBreak)
return nullptr;
// Don't break string literals inside preprocessor directives (except for
@@ -1993,6 +1993,11 @@
// We don't insert backslashes when breaking line comments.
ColumnLimit = Style.ColumnLimit;
}
+ if (ColumnLimit == 0) {
+ // To make the rest of the function easier set the column limit to the
+ // maximum, if there should be no limit.
+ ColumnLimit = std::numeric_limits<decltype(ColumnLimit)>::max();
+ }
if (Current.UnbreakableTailLength >= ColumnLimit)
return {0, false};
// ColumnWidth was already accounted into State.Column before calling
diff --git a/src/llvm-project/clang/lib/Format/Format.cpp b/src/llvm-project/clang/lib/Format/Format.cpp
index 5f5bb85..2b860d2 100644
--- a/src/llvm-project/clang/lib/Format/Format.cpp
+++ b/src/llvm-project/clang/lib/Format/Format.cpp
@@ -63,6 +63,7 @@
IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
IO.enumCase(Value, "CSharp", FormatStyle::LK_CSharp);
+ IO.enumCase(Value, "Json", FormatStyle::LK_Json);
}
};
@@ -85,6 +86,15 @@
}
};
+template <>
+struct ScalarEnumerationTraits<FormatStyle::LambdaBodyIndentationKind> {
+ static void enumeration(IO &IO,
+ FormatStyle::LambdaBodyIndentationKind &Value) {
+ IO.enumCase(Value, "Signature", FormatStyle::LBI_Signature);
+ IO.enumCase(Value, "OuterScope", FormatStyle::LBI_OuterScope);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
IO.enumCase(Value, "Never", FormatStyle::UT_Never);
@@ -143,13 +153,25 @@
}
};
+template <>
+struct ScalarEnumerationTraits<FormatStyle::ArrayInitializerAlignmentStyle> {
+ static void enumeration(IO &IO,
+ FormatStyle::ArrayInitializerAlignmentStyle &Value) {
+ IO.enumCase(Value, "None", FormatStyle::AIAS_None);
+ IO.enumCase(Value, "Left", FormatStyle::AIAS_Left);
+ IO.enumCase(Value, "Right", FormatStyle::AIAS_Right);
+ }
+};
+
template <> struct ScalarEnumerationTraits<FormatStyle::ShortIfStyle> {
static void enumeration(IO &IO, FormatStyle::ShortIfStyle &Value) {
IO.enumCase(Value, "Never", FormatStyle::SIS_Never);
- IO.enumCase(Value, "Always", FormatStyle::SIS_Always);
IO.enumCase(Value, "WithoutElse", FormatStyle::SIS_WithoutElse);
+ IO.enumCase(Value, "OnlyFirstIf", FormatStyle::SIS_OnlyFirstIf);
+ IO.enumCase(Value, "AllIfsAndElse", FormatStyle::SIS_AllIfsAndElse);
// For backward compatibility.
+ IO.enumCase(Value, "Always", FormatStyle::SIS_OnlyFirstIf);
IO.enumCase(Value, "false", FormatStyle::SIS_Never);
IO.enumCase(Value, "true", FormatStyle::SIS_WithoutElse);
}
@@ -238,6 +260,17 @@
IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
+ IO.enumCase(Value, "AfterComma", FormatStyle::BILS_AfterComma);
+ }
+};
+
+template <>
+struct ScalarEnumerationTraits<FormatStyle::EmptyLineAfterAccessModifierStyle> {
+ static void
+ enumeration(IO &IO, FormatStyle::EmptyLineAfterAccessModifierStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::ELAAMS_Never);
+ IO.enumCase(Value, "Leave", FormatStyle::ELAAMS_Leave);
+ IO.enumCase(Value, "Always", FormatStyle::ELAAMS_Always);
}
};
@@ -386,14 +419,24 @@
};
template <>
+struct ScalarEnumerationTraits<FormatStyle::ReferenceAlignmentStyle> {
+ static void enumeration(IO &IO, FormatStyle::ReferenceAlignmentStyle &Value) {
+ IO.enumCase(Value, "Pointer", FormatStyle::RAS_Pointer);
+ IO.enumCase(Value, "Middle", FormatStyle::RAS_Middle);
+ IO.enumCase(Value, "Left", FormatStyle::RAS_Left);
+ IO.enumCase(Value, "Right", FormatStyle::RAS_Right);
+ }
+};
+
+template <>
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
static void enumeration(IO &IO,
FormatStyle::SpaceBeforeParensOptions &Value) {
IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
IO.enumCase(Value, "ControlStatements",
FormatStyle::SBPO_ControlStatements);
- IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
- FormatStyle::SBPO_ControlStatementsExceptForEachMacros);
+ IO.enumCase(Value, "ControlStatementsExceptControlMacros",
+ FormatStyle::SBPO_ControlStatementsExceptControlMacros);
IO.enumCase(Value, "NonEmptyParentheses",
FormatStyle::SBPO_NonEmptyParentheses);
IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
@@ -401,6 +444,8 @@
// For backward compatibility.
IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
+ IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
+ FormatStyle::SBPO_ControlStatementsExceptControlMacros);
}
};
@@ -415,6 +460,18 @@
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::SortIncludesOptions> {
+ static void enumeration(IO &IO, FormatStyle::SortIncludesOptions &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::SI_Never);
+ IO.enumCase(Value, "CaseInsensitive", FormatStyle::SI_CaseInsensitive);
+ IO.enumCase(Value, "CaseSensitive", FormatStyle::SI_CaseSensitive);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::SI_Never);
+ IO.enumCase(Value, "true", FormatStyle::SI_CaseSensitive);
+ }
+};
+
template <>
struct ScalarEnumerationTraits<FormatStyle::SortJavaStaticImportOptions> {
static void enumeration(IO &IO,
@@ -424,6 +481,18 @@
}
};
+template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> {
+ static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) {
+ IO.enumCase(Value, "Never", FormatStyle::SIAS_Never);
+ IO.enumCase(Value, "Always", FormatStyle::SIAS_Always);
+ IO.enumCase(Value, "Leave", FormatStyle::SIAS_Leave);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::SIAS_Never);
+ IO.enumCase(Value, "true", FormatStyle::SIAS_Always);
+ }
+};
+
template <> struct MappingTraits<FormatStyle> {
static void mapping(IO &IO, FormatStyle &Style) {
// When reading, read the language first, we need it for getPredefinedStyle.
@@ -470,6 +539,7 @@
IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
+ IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros);
IO.mapOptional("AlignConsecutiveAssignments",
Style.AlignConsecutiveAssignments);
@@ -572,19 +642,22 @@
IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding);
IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
IO.mapOptional("DisableFormat", Style.DisableFormat);
+ IO.mapOptional("EmptyLineAfterAccessModifier",
+ Style.EmptyLineAfterAccessModifier);
IO.mapOptional("EmptyLineBeforeAccessModifier",
Style.EmptyLineBeforeAccessModifier);
IO.mapOptional("ExperimentalAutoDetectBinPacking",
Style.ExperimentalAutoDetectBinPacking);
IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
IO.mapOptional("ForEachMacros", Style.ForEachMacros);
- IO.mapOptional("StatementAttributeLikeMacros",
- Style.StatementAttributeLikeMacros);
+ IO.mapOptional("IfMacros", Style.IfMacros);
+
IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
IO.mapOptional("IncludeIsMainSourceRegex",
Style.IncludeStyle.IncludeIsMainSourceRegex);
+ IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
@@ -600,6 +673,7 @@
IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
Style.KeepEmptyLinesAtTheStartOfBlocks);
+ IO.mapOptional("LambdaBodyIndentation", Style.LambdaBodyIndentation);
IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
@@ -627,8 +701,11 @@
IO.mapOptional("PenaltyIndentedWhitespace",
Style.PenaltyIndentedWhitespace);
IO.mapOptional("PointerAlignment", Style.PointerAlignment);
+ IO.mapOptional("PPIndentWidth", Style.PPIndentWidth);
IO.mapOptional("RawStringFormats", Style.RawStringFormats);
+ IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
IO.mapOptional("ReflowComments", Style.ReflowComments);
+ IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
IO.mapOptional("SortIncludes", Style.SortIncludes);
IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
@@ -661,12 +738,16 @@
Style.SpacesInContainerLiterals);
IO.mapOptional("SpacesInCStyleCastParentheses",
Style.SpacesInCStyleCastParentheses);
+ IO.mapOptional("SpacesInLineCommentPrefix",
+ Style.SpacesInLineCommentPrefix);
IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
IO.mapOptional("SpaceBeforeSquareBrackets",
Style.SpaceBeforeSquareBrackets);
IO.mapOptional("BitFieldColonSpacing", Style.BitFieldColonSpacing);
IO.mapOptional("Standard", Style.Standard);
+ IO.mapOptional("StatementAttributeLikeMacros",
+ Style.StatementAttributeLikeMacros);
IO.mapOptional("StatementMacros", Style.StatementMacros);
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
@@ -710,6 +791,20 @@
}
};
+template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
+ static void mapping(IO &IO, FormatStyle::SpacesInLineComment &Space) {
+ // Transform the maximum to signed, to parse "-1" correctly
+ int signedMaximum = static_cast<int>(Space.Maximum);
+ IO.mapOptional("Minimum", Space.Minimum);
+ IO.mapOptional("Maximum", signedMaximum);
+ Space.Maximum = static_cast<unsigned>(signedMaximum);
+
+ if (Space.Maximum != -1u) {
+ Space.Minimum = std::min(Space.Minimum, Space.Maximum);
+ }
+ }
+};
+
// Allows to read vector<FormatStyle> while keeping default values.
// IO.getContext() should contain a pointer to the FormatStyle structure, that
// will be used to get default values for missing keys.
@@ -880,10 +975,12 @@
FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
FormatStyle LLVMStyle;
+ LLVMStyle.InheritsParentConfig = false;
LLVMStyle.Language = Language;
LLVMStyle.AccessModifierOffset = -2;
LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
+ LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
LLVMStyle.AlignTrailingComments = true;
LLVMStyle.AlignConsecutiveAssignments = FormatStyle::ACS_None;
@@ -943,18 +1040,21 @@
LLVMStyle.Cpp11BracedListStyle = true;
LLVMStyle.DeriveLineEnding = true;
LLVMStyle.DerivePointerAlignment = false;
+ LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never;
LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock;
LLVMStyle.ExperimentalAutoDetectBinPacking = false;
LLVMStyle.FixNamespaceComments = true;
LLVMStyle.ForEachMacros.push_back("foreach");
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
+ LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
LLVMStyle.IncludeStyle.IncludeCategories = {
{"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
{"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
{".*", 1, 0, false}};
LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
+ LLVMStyle.IndentAccessModifiers = false;
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentCaseBlocks = false;
LLVMStyle.IndentGotoLabels = true;
@@ -962,10 +1062,12 @@
LLVMStyle.IndentRequires = false;
LLVMStyle.IndentWrappedFunctionNames = false;
LLVMStyle.IndentWidth = 2;
+ LLVMStyle.PPIndentWidth = -1;
LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true;
LLVMStyle.TabWidth = 8;
+ LLVMStyle.LambdaBodyIndentation = FormatStyle::LBI_Signature;
LLVMStyle.MaxEmptyLinesToKeep = 1;
LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
@@ -975,6 +1077,8 @@
LLVMStyle.ObjCSpaceAfterProperty = false;
LLVMStyle.ObjCSpaceBeforeProtocolList = true;
LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
+ LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
+ LLVMStyle.ShortNamespaceLines = 1;
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.Standard = FormatStyle::LS_Latest;
LLVMStyle.UseCRLF = false;
@@ -986,6 +1090,7 @@
LLVMStyle.SpaceInEmptyParentheses = false;
LLVMStyle.SpacesInContainerLiterals = true;
LLVMStyle.SpacesInCStyleCastParentheses = false;
+ LLVMStyle.SpacesInLineCommentPrefix = {/*Minimum=*/1, /*Maximum=*/-1u};
LLVMStyle.SpaceAfterCStyleCast = false;
LLVMStyle.SpaceAfterLogicalNot = false;
LLVMStyle.SpaceAfterTemplateKeyword = true;
@@ -999,7 +1104,7 @@
LLVMStyle.SpaceBeforeCpp11BracedList = false;
LLVMStyle.SpaceBeforeSquareBrackets = false;
LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
- LLVMStyle.SpacesInAngles = false;
+ LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
LLVMStyle.SpacesInConditionalStatement = false;
LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
@@ -1013,7 +1118,7 @@
LLVMStyle.PenaltyIndentedWhitespace = 0;
LLVMStyle.DisableFormat = false;
- LLVMStyle.SortIncludes = true;
+ LLVMStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
LLVMStyle.SortUsingDeclarations = true;
LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT");
@@ -1029,6 +1134,9 @@
if (Language == FormatStyle::LK_TableGen) {
LLVMStyle.SpacesInContainerLiterals = false;
}
+ if (LLVMStyle.isJson()) {
+ LLVMStyle.ColumnLimit = 0;
+ }
return LLVMStyle;
}
@@ -1103,7 +1211,7 @@
"ParseTestProto",
"ParsePartialTestProto",
},
- /*CanonicalDelimiter=*/"",
+ /*CanonicalDelimiter=*/"pb",
/*BasedOnStyle=*/"google",
},
};
@@ -1216,7 +1324,7 @@
"java",
"javax",
};
- ChromiumStyle.SortIncludes = true;
+ ChromiumStyle.SortIncludes = FormatStyle::SI_CaseSensitive;
} else if (Language == FormatStyle::LK_JavaScript) {
ChromiumStyle.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Never;
ChromiumStyle.AllowShortLoopsOnASingleLine = false;
@@ -1330,29 +1438,31 @@
FormatStyle getNoStyle() {
FormatStyle NoStyle = getLLVMStyle();
NoStyle.DisableFormat = true;
- NoStyle.SortIncludes = false;
+ NoStyle.SortIncludes = FormatStyle::SI_Never;
NoStyle.SortUsingDeclarations = false;
return NoStyle;
}
bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
FormatStyle *Style) {
- if (Name.equals_lower("llvm")) {
+ if (Name.equals_insensitive("llvm")) {
*Style = getLLVMStyle(Language);
- } else if (Name.equals_lower("chromium")) {
+ } else if (Name.equals_insensitive("chromium")) {
*Style = getChromiumStyle(Language);
- } else if (Name.equals_lower("mozilla")) {
+ } else if (Name.equals_insensitive("mozilla")) {
*Style = getMozillaStyle();
- } else if (Name.equals_lower("google")) {
+ } else if (Name.equals_insensitive("google")) {
*Style = getGoogleStyle(Language);
- } else if (Name.equals_lower("webkit")) {
+ } else if (Name.equals_insensitive("webkit")) {
*Style = getWebKitStyle();
- } else if (Name.equals_lower("gnu")) {
+ } else if (Name.equals_insensitive("gnu")) {
*Style = getGNUStyle();
- } else if (Name.equals_lower("microsoft")) {
+ } else if (Name.equals_insensitive("microsoft")) {
*Style = getMicrosoftStyle(Language);
- } else if (Name.equals_lower("none")) {
+ } else if (Name.equals_insensitive("none")) {
*Style = getNoStyle();
+ } else if (Name.equals_insensitive("inheritparentconfig")) {
+ Style->InheritsParentConfig = true;
} else {
return false;
}
@@ -1362,8 +1472,9 @@
}
std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
- FormatStyle *Style,
- bool AllowUnknownOptions) {
+ FormatStyle *Style, bool AllowUnknownOptions,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler,
+ void *DiagHandlerCtxt) {
assert(Style);
FormatStyle::LanguageKind Language = Style->Language;
assert(Language != FormatStyle::LK_None);
@@ -1371,7 +1482,8 @@
return make_error_code(ParseError::Error);
Style->StyleSet.Clear();
std::vector<FormatStyle> Styles;
- llvm::yaml::Input Input(Config);
+ llvm::yaml::Input Input(Config, /*Ctxt=*/nullptr, DiagHandler,
+ DiagHandlerCtxt);
// DocumentListTraits<vector<FormatStyle>> uses the context to get default
// values for the fields, keys for which are missing from the configuration.
// Mapping also uses the context to get the language to find the correct
@@ -1659,10 +1771,12 @@
Tok = Tok->Next;
}
}
- if (Style.DerivePointerAlignment)
+ if (Style.DerivePointerAlignment) {
Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
? FormatStyle::PAS_Left
: FormatStyle::PAS_Right;
+ Style.ReferenceAlignment = FormatStyle::RAS_Pointer;
+ }
if (Style.Standard == FormatStyle::LS_Auto)
Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
? FormatStyle::LS_Latest
@@ -2209,10 +2323,23 @@
for (unsigned i = 0, e = Includes.size(); i != e; ++i) {
Indices.push_back(i);
}
- llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
- return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
- });
+
+ if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
+ llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
+ const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
+ const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
+ return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
+ Includes[LHSI].Filename) <
+ std::tie(Includes[RHSI].Priority, RHSFilenameLower,
+ Includes[RHSI].Filename);
+ });
+ } else {
+ llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
+ return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
+ std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
+ });
+ }
+
// The index of the include on which the cursor will be put after
// sorting/deduplicating.
unsigned CursorIndex;
@@ -2527,7 +2654,7 @@
ArrayRef<tooling::Range> Ranges,
StringRef FileName, unsigned *Cursor) {
tooling::Replacements Replaces;
- if (!Style.SortIncludes)
+ if (!Style.SortIncludes || Style.DisableFormat)
return Replaces;
if (isLikelyXml(Code))
return Replaces;
@@ -2702,6 +2829,25 @@
if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
return {tooling::Replacements(), 0};
+ // JSON only needs the formatting passing.
+ if (Style.isJson()) {
+ std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
+ auto Env =
+ std::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
+ NextStartColumn, LastStartColumn);
+ // Perform the actual formatting pass.
+ tooling::Replacements Replaces =
+ Formatter(*Env, Style, Status).process().first;
+ // add a replacement to remove the "x = " from the result.
+ if (!Replaces.add(tooling::Replacement(FileName, 0, 4, ""))) {
+ // apply the reformatting changes and the removal of "x = ".
+ if (applyAllReplacements(Code, Replaces)) {
+ return {Replaces, 0};
+ }
+ }
+ return {tooling::Replacements(), 0};
+ }
+
typedef std::function<std::pair<tooling::Replacements, unsigned>(
const Environment &)>
AnalyzerPass;
@@ -2850,23 +2996,26 @@
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
if (FileName.endswith(".java"))
return FormatStyle::LK_Java;
- if (FileName.endswith_lower(".js") || FileName.endswith_lower(".mjs") ||
- FileName.endswith_lower(".ts"))
+ if (FileName.endswith_insensitive(".js") ||
+ FileName.endswith_insensitive(".mjs") ||
+ FileName.endswith_insensitive(".ts"))
return FormatStyle::LK_JavaScript; // (module) JavaScript or TypeScript.
if (FileName.endswith(".m") || FileName.endswith(".mm"))
return FormatStyle::LK_ObjC;
- if (FileName.endswith_lower(".proto") ||
- FileName.endswith_lower(".protodevel"))
+ if (FileName.endswith_insensitive(".proto") ||
+ FileName.endswith_insensitive(".protodevel"))
return FormatStyle::LK_Proto;
- if (FileName.endswith_lower(".textpb") ||
- FileName.endswith_lower(".pb.txt") ||
- FileName.endswith_lower(".textproto") ||
- FileName.endswith_lower(".asciipb"))
+ if (FileName.endswith_insensitive(".textpb") ||
+ FileName.endswith_insensitive(".pb.txt") ||
+ FileName.endswith_insensitive(".textproto") ||
+ FileName.endswith_insensitive(".asciipb"))
return FormatStyle::LK_TextProto;
- if (FileName.endswith_lower(".td"))
+ if (FileName.endswith_insensitive(".td"))
return FormatStyle::LK_TableGen;
- if (FileName.endswith_lower(".cs"))
+ if (FileName.endswith_insensitive(".cs"))
return FormatStyle::LK_CSharp;
+ if (FileName.endswith_insensitive(".json"))
+ return FormatStyle::LK_Json;
return FormatStyle::LK_Cpp;
}
@@ -2905,21 +3054,36 @@
if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
return make_string_error("Invalid fallback style \"" + FallbackStyleName);
+ llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1>
+ ChildFormatTextToApply;
+
if (StyleName.startswith("{")) {
// Parse YAML/JSON style from the command line.
- if (std::error_code ec = parseConfiguration(
- llvm::MemoryBufferRef(StyleName, "<command-line>"), &Style,
- AllowUnknownOptions))
+ StringRef Source = "<command-line>";
+ if (std::error_code ec =
+ parseConfiguration(llvm::MemoryBufferRef(StyleName, Source), &Style,
+ AllowUnknownOptions))
return make_string_error("Error parsing -style: " + ec.message());
- return Style;
+ if (Style.InheritsParentConfig)
+ ChildFormatTextToApply.emplace_back(
+ llvm::MemoryBuffer::getMemBuffer(StyleName, Source, false));
+ else
+ return Style;
}
- if (!StyleName.equals_lower("file")) {
+ // If the style inherits the parent configuration it is a command line
+ // configuration, which wants to inherit, so we have to skip the check of the
+ // StyleName.
+ if (!Style.InheritsParentConfig && !StyleName.equals_insensitive("file")) {
if (!getPredefinedStyle(StyleName, Style.Language, &Style))
return make_string_error("Invalid value for -style");
- return Style;
+ if (!Style.InheritsParentConfig)
+ return Style;
}
+ // Reset possible inheritance
+ Style.InheritsParentConfig = false;
+
// Look for .clang-format/_clang-format file in the file's parent directories.
SmallString<128> UnsuitableConfigFiles;
SmallString<128> Path(FileName);
@@ -2930,6 +3094,8 @@
FilesToLookFor.push_back(".clang-format");
FilesToLookFor.push_back("_clang-format");
+ auto dropDiagnosticHandler = [](const llvm::SMDiagnostic &, void *) {};
+
for (StringRef Directory = Path; !Directory.empty();
Directory = llvm::sys::path::parent_path(Directory)) {
@@ -2966,7 +3132,36 @@
}
LLVM_DEBUG(llvm::dbgs()
<< "Using configuration file " << ConfigFile << "\n");
- return Style;
+
+ if (!Style.InheritsParentConfig) {
+ if (ChildFormatTextToApply.empty())
+ return Style;
+
+ LLVM_DEBUG(llvm::dbgs() << "Applying child configurations\n");
+
+ for (const auto &MemBuf : llvm::reverse(ChildFormatTextToApply)) {
+ auto Ec = parseConfiguration(*MemBuf, &Style, AllowUnknownOptions,
+ dropDiagnosticHandler);
+ // It was already correctly parsed.
+ assert(!Ec);
+ static_cast<void>(Ec);
+ }
+
+ return Style;
+ }
+
+ LLVM_DEBUG(llvm::dbgs() << "Inherits parent configuration\n");
+
+ // Reset inheritance of style
+ Style.InheritsParentConfig = false;
+
+ ChildFormatTextToApply.emplace_back(std::move(*Text));
+
+ // Breaking out of the inner loop, since we don't want to parse
+ // .clang-format AND _clang-format, if both exist. Then we continue the
+ // inner loop (parent directories) in search for the parent
+ // configuration.
+ break;
}
}
}
@@ -2974,6 +3169,21 @@
return make_string_error("Configuration file(s) do(es) not support " +
getLanguageName(Style.Language) + ": " +
UnsuitableConfigFiles);
+
+ if (!ChildFormatTextToApply.empty()) {
+ assert(ChildFormatTextToApply.size() == 1);
+
+ LLVM_DEBUG(llvm::dbgs()
+ << "Applying child configuration on fallback style\n");
+
+ auto Ec =
+ parseConfiguration(*ChildFormatTextToApply.front(), &FallbackStyle,
+ AllowUnknownOptions, dropDiagnosticHandler);
+ // It was already correctly parsed.
+ assert(!Ec);
+ static_cast<void>(Ec);
+ }
+
return FallbackStyle;
}
diff --git a/src/llvm-project/clang/lib/Format/FormatToken.h b/src/llvm-project/clang/lib/Format/FormatToken.h
index 2f53b33..0506cd5 100644
--- a/src/llvm-project/clang/lib/Format/FormatToken.h
+++ b/src/llvm-project/clang/lib/Format/FormatToken.h
@@ -46,11 +46,13 @@
TYPE(DesignatedInitializerLSquare) \
TYPE(DesignatedInitializerPeriod) \
TYPE(DictLiteral) \
+ TYPE(FatArrow) \
TYPE(ForEachMacro) \
TYPE(FunctionAnnotationRParen) \
TYPE(FunctionDeclarationName) \
TYPE(FunctionLBrace) \
TYPE(FunctionTypeLParen) \
+ TYPE(IfMacro) \
TYPE(ImplicitStringLiteral) \
TYPE(InheritanceColon) \
TYPE(InheritanceComma) \
@@ -61,17 +63,12 @@
TYPE(JsComputedPropertyName) \
TYPE(JsExponentiation) \
TYPE(JsExponentiationEqual) \
- TYPE(JsFatArrow) \
- TYPE(JsNonNullAssertion) \
- TYPE(JsNullishCoalescingOperator) \
- TYPE(JsNullPropagatingOperator) \
+ TYPE(JsPipePipeEqual) \
TYPE(JsPrivateIdentifier) \
TYPE(JsTypeColon) \
TYPE(JsTypeOperator) \
TYPE(JsTypeOptionalQuestion) \
TYPE(JsAndAndEqual) \
- TYPE(JsPipePipeEqual) \
- TYPE(JsNullishCoalescingEqual) \
TYPE(LambdaArrow) \
TYPE(LambdaLBrace) \
TYPE(LambdaLSquare) \
@@ -80,6 +77,10 @@
TYPE(MacroBlockBegin) \
TYPE(MacroBlockEnd) \
TYPE(NamespaceMacro) \
+ TYPE(NonNullAssertion) \
+ TYPE(NullCoalescingEqual) \
+ TYPE(NullCoalescingOperator) \
+ TYPE(NullPropagatingOperator) \
TYPE(ObjCBlockLBrace) \
TYPE(ObjCBlockLParen) \
TYPE(ObjCDecl) \
@@ -113,8 +114,6 @@
TYPE(CSharpStringLiteral) \
TYPE(CSharpNamedArgumentColon) \
TYPE(CSharpNullable) \
- TYPE(CSharpNullCoalescing) \
- TYPE(CSharpNullConditional) \
TYPE(CSharpNullConditionalLSquare) \
TYPE(CSharpGenericTypeConstraint) \
TYPE(CSharpGenericTypeConstraintColon) \
@@ -433,6 +432,15 @@
/// The next token in the unwrapped line.
FormatToken *Next = nullptr;
+ /// The first token in set of column elements.
+ bool StartsColumn = false;
+
+ /// This notes the start of the line of an array initializer.
+ bool ArrayInitializerLineStart = false;
+
+ /// This starts an array initializer.
+ bool IsArrayInitializer = false;
+
/// If this token starts a block, this contains all the unwrapped lines
/// in it.
SmallVector<AnnotatedLine *, 1> Children;
diff --git a/src/llvm-project/clang/lib/Format/FormatTokenLexer.cpp b/src/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
index e9b0963..a9cfb4a 100644
--- a/src/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
+++ b/src/llvm-project/clang/lib/Format/FormatTokenLexer.cpp
@@ -39,6 +39,8 @@
for (const std::string &ForEachMacro : Style.ForEachMacros)
Macros.insert({&IdentTable.get(ForEachMacro), TT_ForEachMacro});
+ for (const std::string &IfMacro : Style.IfMacros)
+ Macros.insert({&IdentTable.get(IfMacro), TT_IfMacro});
for (const std::string &AttributeMacro : Style.AttributeMacros)
Macros.insert({&IdentTable.get(AttributeMacro), TT_AttributeMacro});
for (const std::string &StatementMacro : Style.StatementMacros)
@@ -92,20 +94,46 @@
if (Style.isCpp() && tryTransformTryUsageForC())
return;
+ if (Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) {
+ static const tok::TokenKind NullishCoalescingOperator[] = {tok::question,
+ tok::question};
+ static const tok::TokenKind NullPropagatingOperator[] = {tok::question,
+ tok::period};
+ static const tok::TokenKind FatArrow[] = {tok::equal, tok::greater};
+
+ if (tryMergeTokens(FatArrow, TT_FatArrow))
+ return;
+ if (tryMergeTokens(NullishCoalescingOperator, TT_NullCoalescingOperator)) {
+ // Treat like the "||" operator (as opposed to the ternary ?).
+ Tokens.back()->Tok.setKind(tok::pipepipe);
+ return;
+ }
+ if (tryMergeTokens(NullPropagatingOperator, TT_NullPropagatingOperator)) {
+ // Treat like a regular "." access.
+ Tokens.back()->Tok.setKind(tok::period);
+ return;
+ }
+ if (tryMergeNullishCoalescingEqual()) {
+ return;
+ }
+ }
+
if (Style.isCSharp()) {
+ static const tok::TokenKind CSharpNullConditionalLSquare[] = {
+ tok::question, tok::l_square};
+
if (tryMergeCSharpKeywordVariables())
return;
if (tryMergeCSharpStringLiteral())
return;
- if (tryMergeCSharpDoubleQuestion())
- return;
- if (tryMergeCSharpNullConditional())
- return;
if (tryTransformCSharpForEach())
return;
- static const tok::TokenKind JSRightArrow[] = {tok::equal, tok::greater};
- if (tryMergeTokens(JSRightArrow, TT_JsFatArrow))
+ if (tryMergeTokens(CSharpNullConditionalLSquare,
+ TT_CSharpNullConditionalLSquare)) {
+ // Treat like a regular "[" operator.
+ Tokens.back()->Tok.setKind(tok::l_square);
return;
+ }
}
if (tryMergeNSStringLiteral())
@@ -117,16 +145,9 @@
tok::equal};
static const tok::TokenKind JSShiftEqual[] = {tok::greater, tok::greater,
tok::greaterequal};
- static const tok::TokenKind JSRightArrow[] = {tok::equal, tok::greater};
static const tok::TokenKind JSExponentiation[] = {tok::star, tok::star};
static const tok::TokenKind JSExponentiationEqual[] = {tok::star,
tok::starequal};
- static const tok::TokenKind JSNullPropagatingOperator[] = {tok::question,
- tok::period};
- static const tok::TokenKind JSNullishOperator[] = {tok::question,
- tok::question};
- static const tok::TokenKind JSNullishEqual[] = {tok::question,
- tok::question, tok::equal};
static const tok::TokenKind JSPipePipeEqual[] = {tok::pipepipe, tok::equal};
static const tok::TokenKind JSAndAndEqual[] = {tok::ampamp, tok::equal};
@@ -137,28 +158,14 @@
return;
if (tryMergeTokens(JSShiftEqual, TT_BinaryOperator))
return;
- if (tryMergeTokens(JSRightArrow, TT_JsFatArrow))
- return;
if (tryMergeTokens(JSExponentiation, TT_JsExponentiation))
return;
if (tryMergeTokens(JSExponentiationEqual, TT_JsExponentiationEqual)) {
Tokens.back()->Tok.setKind(tok::starequal);
return;
}
- if (tryMergeTokens(JSNullishOperator, TT_JsNullishCoalescingOperator)) {
- // Treat like the "||" operator (as opposed to the ternary ?).
- Tokens.back()->Tok.setKind(tok::pipepipe);
- return;
- }
- if (tryMergeTokens(JSNullPropagatingOperator,
- TT_JsNullPropagatingOperator)) {
- // Treat like a regular "." access.
- Tokens.back()->Tok.setKind(tok::period);
- return;
- }
if (tryMergeTokens(JSAndAndEqual, TT_JsAndAndEqual) ||
- tryMergeTokens(JSPipePipeEqual, TT_JsPipePipeEqual) ||
- tryMergeTokens(JSNullishEqual, TT_JsNullishCoalescingEqual)) {
+ tryMergeTokens(JSPipePipeEqual, TT_JsPipePipeEqual)) {
// Treat like the "=" assignment operator.
Tokens.back()->Tok.setKind(tok::equal);
return;
@@ -310,45 +317,20 @@
"param", "property", "return", "type",
};
-bool FormatTokenLexer::tryMergeCSharpDoubleQuestion() {
+bool FormatTokenLexer::tryMergeNullishCoalescingEqual() {
if (Tokens.size() < 2)
return false;
- auto &FirstQuestion = *(Tokens.end() - 2);
- auto &SecondQuestion = *(Tokens.end() - 1);
- if (!FirstQuestion->is(tok::question) || !SecondQuestion->is(tok::question))
+ auto &NullishCoalescing = *(Tokens.end() - 2);
+ auto &Equal = *(Tokens.end() - 1);
+ if (NullishCoalescing->getType() != TT_NullCoalescingOperator ||
+ !Equal->is(tok::equal))
return false;
- FirstQuestion->Tok.setKind(tok::question); // no '??' in clang tokens.
- FirstQuestion->TokenText = StringRef(FirstQuestion->TokenText.begin(),
- SecondQuestion->TokenText.end() -
- FirstQuestion->TokenText.begin());
- FirstQuestion->ColumnWidth += SecondQuestion->ColumnWidth;
- FirstQuestion->setType(TT_CSharpNullCoalescing);
- Tokens.erase(Tokens.end() - 1);
- return true;
-}
-
-// Merge '?[' and '?.' pairs into single tokens.
-bool FormatTokenLexer::tryMergeCSharpNullConditional() {
- if (Tokens.size() < 2)
- return false;
- auto &Question = *(Tokens.end() - 2);
- auto &PeriodOrLSquare = *(Tokens.end() - 1);
- if (!Question->is(tok::question) ||
- !PeriodOrLSquare->isOneOf(tok::l_square, tok::period))
- return false;
- Question->TokenText =
- StringRef(Question->TokenText.begin(),
- PeriodOrLSquare->TokenText.end() - Question->TokenText.begin());
- Question->ColumnWidth += PeriodOrLSquare->ColumnWidth;
-
- if (PeriodOrLSquare->is(tok::l_square)) {
- Question->Tok.setKind(tok::question); // no '?[' in clang tokens.
- Question->setType(TT_CSharpNullConditionalLSquare);
- } else {
- Question->Tok.setKind(tok::question); // no '?.' in clang tokens.
- Question->setType(TT_CSharpNullConditional);
- }
-
+ NullishCoalescing->Tok.setKind(tok::equal); // no '??=' in clang tokens.
+ NullishCoalescing->TokenText =
+ StringRef(NullishCoalescing->TokenText.begin(),
+ Equal->TokenText.end() - NullishCoalescing->TokenText.begin());
+ NullishCoalescing->ColumnWidth += Equal->ColumnWidth;
+ NullishCoalescing->setType(TT_NullCoalescingEqual);
Tokens.erase(Tokens.end() - 1);
return true;
}
@@ -1034,6 +1016,13 @@
tok::pp_define) &&
it != Macros.end()) {
FormatTok->setType(it->second);
+ if (it->second == TT_IfMacro) {
+ // The lexer token currently has type tok::kw_unknown. However, for this
+ // substitution to be treated correctly in the TokenAnnotator, faking
+ // the tok value seems to be needed. Not sure if there's a more elegant
+ // way.
+ FormatTok->Tok.setKind(tok::kw_if);
+ }
} else if (FormatTok->is(tok::identifier)) {
if (MacroBlockBeginRegex.match(Text)) {
FormatTok->setType(TT_MacroBlockBegin);
diff --git a/src/llvm-project/clang/lib/Format/FormatTokenLexer.h b/src/llvm-project/clang/lib/Format/FormatTokenLexer.h
index 6b08677..a9e3b2f 100644
--- a/src/llvm-project/clang/lib/Format/FormatTokenLexer.h
+++ b/src/llvm-project/clang/lib/Format/FormatTokenLexer.h
@@ -54,8 +54,7 @@
bool tryMergeJSPrivateIdentifier();
bool tryMergeCSharpStringLiteral();
bool tryMergeCSharpKeywordVariables();
- bool tryMergeCSharpDoubleQuestion();
- bool tryMergeCSharpNullConditional();
+ bool tryMergeNullishCoalescingEqual();
bool tryTransformCSharpForEach();
bool tryMergeForEach();
bool tryTransformTryUsageForC();
diff --git a/src/llvm-project/clang/lib/Format/NamespaceEndCommentsFixer.cpp b/src/llvm-project/clang/lib/Format/NamespaceEndCommentsFixer.cpp
index 97de45b..def551f 100644
--- a/src/llvm-project/clang/lib/Format/NamespaceEndCommentsFixer.cpp
+++ b/src/llvm-project/clang/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -22,10 +22,6 @@
namespace format {
namespace {
-// The maximal number of unwrapped lines that a short namespace spans.
-// Short namespaces don't need an end comment.
-static const int kShortNamespaceMaxLines = 1;
-
// Computes the name of a namespace given the namespace token.
// Returns "" for anonymous namespace.
std::string computeName(const FormatToken *NamespaceTok) {
@@ -66,8 +62,10 @@
}
std::string computeEndCommentText(StringRef NamespaceName, bool AddNewline,
- const FormatToken *NamespaceTok) {
- std::string text = "// ";
+ const FormatToken *NamespaceTok,
+ unsigned SpacesToAdd) {
+ std::string text = "//";
+ text.append(SpacesToAdd, ' ');
text += NamespaceTok->TokenText;
if (NamespaceTok->is(TT_NamespaceMacro))
text += "(";
@@ -278,9 +276,10 @@
EndCommentNextTok->NewlinesBefore == 0 &&
EndCommentNextTok->isNot(tok::eof);
const std::string EndCommentText =
- computeEndCommentText(NamespaceName, AddNewline, NamespaceTok);
+ computeEndCommentText(NamespaceName, AddNewline, NamespaceTok,
+ Style.SpacesInLineCommentPrefix.Minimum);
if (!hasEndComment(EndCommentPrevTok)) {
- bool isShort = I - StartLineIndex <= kShortNamespaceMaxLines + 1;
+ bool isShort = I - StartLineIndex <= Style.ShortNamespaceLines + 1;
if (!isShort)
addEndComment(EndCommentPrevTok, EndCommentText, SourceMgr, &Fixes);
} else if (!validEndComment(EndCommentPrevTok, NamespaceName,
diff --git a/src/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp b/src/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp
index db2b65b..a5e3ce6 100644
--- a/src/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp
+++ b/src/llvm-project/clang/lib/Format/SortJavaScriptImports.cpp
@@ -19,6 +19,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Format/Format.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -69,6 +70,7 @@
// This struct represents both exports and imports to build up the information
// required for sorting module references.
struct JsModuleReference {
+ bool FormattingOff = false;
bool IsExport = false;
// Module references are sorted into these categories, in order.
enum ReferenceCategory {
@@ -83,8 +85,16 @@
// Prefix from "import * as prefix". Empty for symbol imports and `export *`.
// Implies an empty names list.
StringRef Prefix;
+ // Default import from "import DefaultName from '...';".
+ StringRef DefaultImport;
// Symbols from `import {SymbolA, SymbolB, ...} from ...;`.
SmallVector<JsImportedSymbol, 1> Symbols;
+ // Whether some symbols were merged into this one. Controls if the module
+ // reference needs re-formatting.
+ bool SymbolsMerged = false;
+ // The source location just after { and just before } in the import.
+ // Extracted eagerly to allow modification of Symbols later on.
+ SourceLocation SymbolsStart, SymbolsEnd;
// Textual position of the import/export, including preceding and trailing
// comments.
SourceRange Range;
@@ -103,7 +113,7 @@
// Empty URLs sort *last* (for export {...};).
if (LHS.URL.empty() != RHS.URL.empty())
return LHS.URL.empty() < RHS.URL.empty();
- if (int Res = LHS.URL.compare_lower(RHS.URL))
+ if (int Res = LHS.URL.compare_insensitive(RHS.URL))
return Res < 0;
// '*' imports (with prefix) sort before {a, b, ...} imports.
if (LHS.Prefix.empty() != RHS.Prefix.empty())
@@ -138,38 +148,31 @@
if (References.empty())
return {Result, 0};
- SmallVector<unsigned, 16> Indices;
- for (unsigned i = 0, e = References.size(); i != e; ++i)
- Indices.push_back(i);
- llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
- return References[LHSI] < References[RHSI];
- });
- bool ReferencesInOrder = llvm::is_sorted(Indices);
+ // The text range of all parsed imports, to be replaced later.
+ SourceRange InsertionPoint = References[0].Range;
+ InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd());
+
+ References = sortModuleReferences(References);
std::string ReferencesText;
- bool SymbolsInOrder = true;
- for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
- JsModuleReference Reference = References[Indices[i]];
- if (appendReference(ReferencesText, Reference))
- SymbolsInOrder = false;
- if (i + 1 < e) {
+ for (unsigned I = 0, E = References.size(); I != E; ++I) {
+ JsModuleReference Reference = References[I];
+ appendReference(ReferencesText, Reference);
+ if (I + 1 < E) {
// Insert breaks between imports and exports.
ReferencesText += "\n";
// Separate imports groups with two line breaks, but keep all exports
// in a single group.
if (!Reference.IsExport &&
- (Reference.IsExport != References[Indices[i + 1]].IsExport ||
- Reference.Category != References[Indices[i + 1]].Category))
+ (Reference.IsExport != References[I + 1].IsExport ||
+ Reference.Category != References[I + 1].Category))
ReferencesText += "\n";
}
}
-
- if (ReferencesInOrder && SymbolsInOrder)
+ llvm::StringRef PreviousText = getSourceText(InsertionPoint);
+ if (ReferencesText == PreviousText)
return {Result, 0};
- SourceRange InsertionPoint = References[0].Range;
- InsertionPoint.setEnd(References[References.size() - 1].Range.getEnd());
-
// The loop above might collapse previously existing line breaks between
// import blocks, and thus shrink the file. SortIncludes must not shrink
// overall source length as there is currently no re-calculation of ranges
@@ -177,17 +180,19 @@
// This loop just backfills trailing spaces after the imports, which are
// harmless and will be stripped by the subsequent formatting pass.
// FIXME: A better long term fix is to re-calculate Ranges after sorting.
- unsigned PreviousSize = getSourceText(InsertionPoint).size();
+ unsigned PreviousSize = PreviousText.size();
while (ReferencesText.size() < PreviousSize) {
ReferencesText += " ";
}
// Separate references from the main code body of the file.
- if (FirstNonImportLine && FirstNonImportLine->First->NewlinesBefore < 2)
+ if (FirstNonImportLine && FirstNonImportLine->First->NewlinesBefore < 2 &&
+ !(FirstNonImportLine->First->is(tok::comment) &&
+ FirstNonImportLine->First->TokenText.trim() == "// clang-format on"))
ReferencesText += "\n";
LLVM_DEBUG(llvm::dbgs() << "Replacing imports:\n"
- << getSourceText(InsertionPoint) << "\nwith:\n"
+ << PreviousText << "\nwith:\n"
<< ReferencesText << "\n");
auto Err = Result.add(tooling::Replacement(
Env.getSourceManager(), CharSourceRange::getCharRange(InsertionPoint),
@@ -239,26 +244,99 @@
SM.getFileOffset(End) - SM.getFileOffset(Begin));
}
- // Appends ``Reference`` to ``Buffer``, returning true if text within the
- // ``Reference`` changed (e.g. symbol order).
- bool appendReference(std::string &Buffer, JsModuleReference &Reference) {
+ // Sorts the given module references.
+ // Imports can have formatting disabled (FormattingOff), so the code below
+ // skips runs of "no-formatting" module references, and sorts/merges the
+ // references that have formatting enabled in individual chunks.
+ SmallVector<JsModuleReference, 16>
+ sortModuleReferences(const SmallVector<JsModuleReference, 16> &References) {
+ // Sort module references.
+ // Imports can have formatting disabled (FormattingOff), so the code below
+ // skips runs of "no-formatting" module references, and sorts other
+ // references per group.
+ const auto *Start = References.begin();
+ SmallVector<JsModuleReference, 16> ReferencesSorted;
+ while (Start != References.end()) {
+ while (Start != References.end() && Start->FormattingOff) {
+ // Skip over all imports w/ disabled formatting.
+ ReferencesSorted.push_back(*Start);
+ Start++;
+ }
+ SmallVector<JsModuleReference, 16> SortChunk;
+ while (Start != References.end() && !Start->FormattingOff) {
+ // Skip over all imports w/ disabled formatting.
+ SortChunk.push_back(*Start);
+ Start++;
+ }
+ llvm::stable_sort(SortChunk);
+ mergeModuleReferences(SortChunk);
+ ReferencesSorted.insert(ReferencesSorted.end(), SortChunk.begin(),
+ SortChunk.end());
+ }
+ return ReferencesSorted;
+ }
+
+ // Merge module references.
+ // After sorting, find all references that import named symbols from the
+ // same URL and merge their names. E.g.
+ // import {X} from 'a';
+ // import {Y} from 'a';
+ // should be rewritten to:
+ // import {X, Y} from 'a';
+ // Note: this modifies the passed in ``References`` vector (by removing no
+ // longer needed references).
+ void mergeModuleReferences(SmallVector<JsModuleReference, 16> &References) {
+ if (References.empty())
+ return;
+ JsModuleReference *PreviousReference = References.begin();
+ auto *Reference = std::next(References.begin());
+ while (Reference != References.end()) {
+ // Skip:
+ // import 'foo';
+ // import * as foo from 'foo'; on either previous or this.
+ // import Default from 'foo'; on either previous or this.
+ // mismatching
+ if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+ PreviousReference->Category == JsModuleReference::SIDE_EFFECT ||
+ Reference->IsExport != PreviousReference->IsExport ||
+ !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
+ !PreviousReference->DefaultImport.empty() ||
+ !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
+ PreviousReference->URL != Reference->URL) {
+ PreviousReference = Reference;
+ ++Reference;
+ continue;
+ }
+ // Merge symbols from identical imports.
+ PreviousReference->Symbols.append(Reference->Symbols);
+ PreviousReference->SymbolsMerged = true;
+ // Remove the merged import.
+ Reference = References.erase(Reference);
+ }
+ }
+
+ // Appends ``Reference`` to ``Buffer``.
+ void appendReference(std::string &Buffer, JsModuleReference &Reference) {
+ if (Reference.FormattingOff) {
+ Buffer +=
+ getSourceText(Reference.Range.getBegin(), Reference.Range.getEnd());
+ return;
+ }
// Sort the individual symbols within the import.
// E.g. `import {b, a} from 'x';` -> `import {a, b} from 'x';`
SmallVector<JsImportedSymbol, 1> Symbols = Reference.Symbols;
llvm::stable_sort(
Symbols, [&](const JsImportedSymbol &LHS, const JsImportedSymbol &RHS) {
- return LHS.Symbol.compare_lower(RHS.Symbol) < 0;
+ return LHS.Symbol.compare_insensitive(RHS.Symbol) < 0;
});
- if (Symbols == Reference.Symbols) {
- // No change in symbol order.
+ if (!Reference.SymbolsMerged && Symbols == Reference.Symbols) {
+ // Symbols didn't change, just emit the entire module reference.
StringRef ReferenceStmt = getSourceText(Reference.Range);
Buffer += ReferenceStmt;
- return false;
+ return;
}
// Stitch together the module reference start...
- SourceLocation SymbolsStart = Reference.Symbols.front().Range.getBegin();
- SourceLocation SymbolsEnd = Reference.Symbols.back().Range.getEnd();
- Buffer += getSourceText(Reference.Range.getBegin(), SymbolsStart);
+ Buffer += getSourceText(Reference.Range.getBegin(), Reference.SymbolsStart);
// ... then the references in order ...
for (auto I = Symbols.begin(), E = Symbols.end(); I != E; ++I) {
if (I != Symbols.begin())
@@ -266,8 +344,7 @@
Buffer += getSourceText(I->Range);
}
// ... followed by the module reference end.
- Buffer += getSourceText(SymbolsEnd, Reference.Range.getEnd());
- return true;
+ Buffer += getSourceText(Reference.SymbolsEnd, Reference.Range.getEnd());
}
// Parses module references in the given lines. Returns the module references,
@@ -280,9 +357,30 @@
SourceLocation Start;
AnnotatedLine *FirstNonImportLine = nullptr;
bool AnyImportAffected = false;
- for (auto Line : AnnotatedLines) {
+ bool FormattingOff = false;
+ for (auto *Line : AnnotatedLines) {
Current = Line->First;
LineEnd = Line->Last;
+ // clang-format comments toggle formatting on/off.
+ // This is tracked in FormattingOff here and on JsModuleReference.
+ while (Current && Current->is(tok::comment)) {
+ StringRef CommentText = Current->TokenText.trim();
+ if (CommentText == "// clang-format off") {
+ FormattingOff = true;
+ } else if (CommentText == "// clang-format on") {
+ FormattingOff = false;
+ // Special case: consider a trailing "clang-format on" line to be part
+ // of the module reference, so that it gets moved around together with
+ // it (as opposed to the next module reference, which might get sorted
+ // around).
+ if (!References.empty()) {
+ References.back().Range.setEnd(Current->Tok.getEndLoc());
+ Start = Current->Tok.getEndLoc().getLocWithOffset(1);
+ }
+ }
+ // Handle all clang-format comments on a line, e.g. for an empty block.
+ Current = Current->Next;
+ }
skipComments();
if (Start.isInvalid() || References.empty())
// After the first file level comment, consider line comments to be part
@@ -295,6 +393,7 @@
continue;
}
JsModuleReference Reference;
+ Reference.FormattingOff = FormattingOff;
Reference.Range.setBegin(Start);
if (!parseModuleReference(Keywords, Reference)) {
if (!FirstNonImportLine)
@@ -306,13 +405,14 @@
Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
LLVM_DEBUG({
llvm::dbgs() << "JsModuleReference: {"
- << "is_export: " << Reference.IsExport
+ << "formatting_off: " << Reference.FormattingOff
+ << ", is_export: " << Reference.IsExport
<< ", cat: " << Reference.Category
<< ", url: " << Reference.URL
<< ", prefix: " << Reference.Prefix;
- for (size_t i = 0; i < Reference.Symbols.size(); ++i)
- llvm::dbgs() << ", " << Reference.Symbols[i].Symbol << " as "
- << Reference.Symbols[i].Alias;
+ for (size_t I = 0; I < Reference.Symbols.size(); ++I)
+ llvm::dbgs() << ", " << Reference.Symbols[I].Symbol << " as "
+ << Reference.Symbols[I].Alias;
llvm::dbgs() << ", text: " << getSourceText(Reference.Range);
llvm::dbgs() << "}\n";
});
@@ -393,7 +493,9 @@
bool parseNamedBindings(const AdditionalKeywords &Keywords,
JsModuleReference &Reference) {
+ // eat a potential "import X, " prefix.
if (Current->is(tok::identifier)) {
+ Reference.DefaultImport = Current->TokenText;
nextToken();
if (Current->is(Keywords.kw_from))
return true;
@@ -405,6 +507,7 @@
return false;
// {sym as alias, sym2 as ...} from '...';
+ Reference.SymbolsStart = Current->Tok.getEndLoc();
while (Current->isNot(tok::r_brace)) {
nextToken();
if (Current->is(tok::r_brace))
@@ -432,6 +535,11 @@
if (!Current->isOneOf(tok::r_brace, tok::comma))
return false;
}
+ Reference.SymbolsEnd = Current->Tok.getLocation();
+ // For named imports with a trailing comma ("import {X,}"), consider the
+ // comma to be the end of the import list, so that it doesn't get removed.
+ if (Current->Previous->is(tok::comma))
+ Reference.SymbolsEnd = Current->Previous->Tok.getLocation();
nextToken(); // consume r_brace
return true;
}
diff --git a/src/llvm-project/clang/lib/Format/TokenAnnotator.cpp b/src/llvm-project/clang/lib/Format/TokenAnnotator.cpp
old mode 100755
new mode 100644
index 82d6cfe..54e6c7d
--- a/src/llvm-project/clang/lib/Format/TokenAnnotator.cpp
+++ b/src/llvm-project/clang/lib/Format/TokenAnnotator.cpp
@@ -116,10 +116,17 @@
while (CurrentToken) {
if (CurrentToken->is(tok::greater)) {
// Try to do a better job at looking for ">>" within the condition of
- // a statement.
+ // a statement. Conservatively insert spaces between consecutive ">"
+ // tokens to prevent splitting right bitshift operators and potentially
+ // altering program semantics. This check is overly conservative and
+ // will prevent spaces from being inserted in select nested template
+ // parameter cases, but should not alter program semantics.
if (CurrentToken->Next && CurrentToken->Next->is(tok::greater) &&
Left->ParentBracket != tok::less &&
- isKeywordWithCondition(*Line.First))
+ (isKeywordWithCondition(*Line.First) ||
+ CurrentToken->getStartOfNonWhitespace() ==
+ CurrentToken->Next->getStartOfNonWhitespace().getLocWithOffset(
+ -1)))
return false;
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
@@ -222,7 +229,19 @@
}
if (Left->is(TT_OverloadedOperatorLParen)) {
- Contexts.back().IsExpression = false;
+ // Find the previous kw_operator token.
+ FormatToken *Prev = Left;
+ while (!Prev->is(tok::kw_operator)) {
+ Prev = Prev->Previous;
+ assert(Prev && "Expect a kw_operator prior to the OperatorLParen!");
+ }
+
+ // If faced with "a.operator*(argument)" or "a->operator*(argument)",
+ // i.e. the operator is called as a member function,
+ // then the argument must be an expression.
+ bool OperatorCalledAsMemberFunction =
+ Prev->Previous && Prev->Previous->isOneOf(tok::period, tok::arrow);
+ Contexts.back().IsExpression = OperatorCalledAsMemberFunction;
} else if (Style.Language == FormatStyle::LK_JavaScript &&
(Line.startsWith(Keywords.kw_type, tok::identifier) ||
Line.startsWith(tok::kw_export, Keywords.kw_type,
@@ -344,7 +363,7 @@
Left->Previous && Left->Previous->is(tok::l_paren)) {
// Detect the case where macros are used to generate lambdas or
// function bodies, e.g.:
- // auto my_lambda = MARCO((Type *type, int i) { .. body .. });
+ // auto my_lambda = MACRO((Type *type, int i) { .. body .. });
for (FormatToken *Tok = Left; Tok != CurrentToken; Tok = Tok->Next) {
if (Tok->is(TT_BinaryOperator) &&
Tok->isOneOf(tok::star, tok::amp, tok::ampamp))
@@ -390,9 +409,13 @@
!CurrentToken->Next->HasUnescapedNewline &&
!CurrentToken->Next->isTrailingComment())
HasMultipleParametersOnALine = true;
+ bool ProbablyFunctionTypeLParen =
+ (CurrentToken->is(tok::l_paren) && CurrentToken->Next &&
+ CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret));
if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) ||
CurrentToken->Previous->isSimpleTypeSpecifier()) &&
- !CurrentToken->is(tok::l_brace))
+ !(CurrentToken->is(tok::l_brace) ||
+ (CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen)))
Contexts.back().IsExpression = false;
if (CurrentToken->isOneOf(tok::semi, tok::colon)) {
MightBeObjCForRangeLoop = false;
@@ -722,6 +745,21 @@
return false;
}
+ bool couldBeInStructArrayInitializer() const {
+ if (Contexts.size() < 2)
+ return false;
+ // We want to back up no more then 2 context levels i.e.
+ // . { { <-
+ const auto End = std::next(Contexts.rbegin(), 2);
+ auto Last = Contexts.rbegin();
+ unsigned Depth = 0;
+ for (; Last != End; ++Last) {
+ if (Last->ContextKind == tok::l_brace)
+ ++Depth;
+ }
+ return Depth == 2 && Last->ContextKind != tok::l_brace;
+ }
+
bool parseBrace() {
if (CurrentToken) {
FormatToken *Left = CurrentToken->Previous;
@@ -739,10 +777,17 @@
Left->Previous->is(TT_JsTypeColon))
Contexts.back().IsExpression = false;
+ unsigned CommaCount = 0;
while (CurrentToken) {
if (CurrentToken->is(tok::r_brace)) {
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
+ if (Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
+ if (Left->ParentBracket == tok::l_brace &&
+ couldBeInStructArrayInitializer() && CommaCount > 0) {
+ Contexts.back().InStructArrayInitializer = true;
+ }
+ }
next();
return true;
}
@@ -766,9 +811,11 @@
Style.Language == FormatStyle::LK_JavaScript)
Left->setType(TT_DictLiteral);
}
- if (CurrentToken->is(tok::comma) &&
- Style.Language == FormatStyle::LK_JavaScript)
- Left->setType(TT_DictLiteral);
+ if (CurrentToken->is(tok::comma)) {
+ if (Style.Language == FormatStyle::LK_JavaScript)
+ Left->setType(TT_DictLiteral);
+ ++CommaCount;
+ }
if (!consumeToken())
return false;
}
@@ -1048,13 +1095,6 @@
CurrentToken->Previous->setType(TT_OverloadedOperator);
break;
case tok::question:
- if (Tok->is(TT_CSharpNullConditionalLSquare)) {
- if (!parseSquare())
- return false;
- break;
- }
- if (Tok->isOneOf(TT_CSharpNullConditional, TT_CSharpNullCoalescing))
- break;
if (Style.Language == FormatStyle::LK_JavaScript && Tok->Next &&
Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren,
tok::r_brace)) {
@@ -1339,6 +1379,12 @@
return LT_ObjCMethodDecl;
}
+ for (const auto &ctx : Contexts) {
+ if (ctx.InStructArrayInitializer) {
+ return LT_ArrayOfStructInitializer;
+ }
+ }
+
return LT_Other;
}
@@ -1363,9 +1409,9 @@
// Reset token type in case we have already looked at it and then
// recovered from an error (e.g. failure to find the matching >).
if (!CurrentToken->isOneOf(
- TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro,
+ TT_LambdaLSquare, TT_LambdaLBrace, TT_AttributeMacro, TT_IfMacro,
TT_ForEachMacro, TT_TypenameMacro, TT_FunctionLBrace,
- TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_JsFatArrow,
+ TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow,
TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,
TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,
TT_UntouchableMacroFunc, TT_ConstraintJunctions,
@@ -1414,6 +1460,7 @@
bool IsForEachMacro = false;
bool InCpp11AttributeSpecifier = false;
bool InCSharpAttributeSpecifier = false;
+ bool InStructArrayInitializer = false;
};
/// Puts a new \c Context onto the stack \c Contexts for the lifetime
@@ -1429,7 +1476,16 @@
P.Contexts.back().IsExpression));
}
- ~ScopedContextCreator() { P.Contexts.pop_back(); }
+ ~ScopedContextCreator() {
+ if (P.Style.AlignArrayOfStructures != FormatStyle::AIAS_None) {
+ if (P.Contexts.back().InStructArrayInitializer) {
+ P.Contexts.pop_back();
+ P.Contexts.back().InStructArrayInitializer = true;
+ return;
+ }
+ }
+ P.Contexts.pop_back();
+ }
};
void modifyContext(const FormatToken &Current) {
@@ -1564,38 +1620,28 @@
// The token type is already known.
return;
- if (Style.isCSharp() && CurrentToken->is(tok::question)) {
- if (CurrentToken->TokenText == "??") {
- Current.setType(TT_CSharpNullCoalescing);
- return;
- }
- if (CurrentToken->TokenText == "?.") {
- Current.setType(TT_CSharpNullConditional);
- return;
- }
- if (CurrentToken->TokenText == "?[") {
- Current.setType(TT_CSharpNullConditionalLSquare);
- return;
- }
- }
-
- if (Style.Language == FormatStyle::LK_JavaScript) {
- if (Current.is(tok::exclaim)) {
- if (Current.Previous &&
- (Keywords.IsJavaScriptIdentifier(
- *Current.Previous, /* AcceptIdentifierName= */ true) ||
- Current.Previous->isOneOf(
- tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace,
- Keywords.kw_type, Keywords.kw_get, Keywords.kw_set) ||
- Current.Previous->Tok.isLiteral())) {
- Current.setType(TT_JsNonNullAssertion);
+ if ((Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) &&
+ Current.is(tok::exclaim)) {
+ if (Current.Previous) {
+ bool IsIdentifier =
+ Style.Language == FormatStyle::LK_JavaScript
+ ? Keywords.IsJavaScriptIdentifier(
+ *Current.Previous, /* AcceptIdentifierName= */ true)
+ : Current.Previous->is(tok::identifier);
+ if (IsIdentifier ||
+ Current.Previous->isOneOf(
+ tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace,
+ tok::kw_false, tok::kw_true, Keywords.kw_type, Keywords.kw_get,
+ Keywords.kw_set) ||
+ Current.Previous->Tok.isLiteral()) {
+ Current.setType(TT_NonNullAssertion);
return;
}
- if (Current.Next &&
- Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) {
- Current.setType(TT_JsNonNullAssertion);
- return;
- }
+ }
+ if (Current.Next &&
+ Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) {
+ Current.setType(TT_NonNullAssertion);
+ return;
}
}
@@ -2184,7 +2230,7 @@
return prec::Assignment;
if (Current->is(TT_LambdaArrow))
return prec::Comma;
- if (Current->is(TT_JsFatArrow))
+ if (Current->is(TT_FatArrow))
return prec::Assignment;
if (Current->isOneOf(tok::semi, TT_InlineASMColon, TT_SelectorName) ||
(Current->is(tok::comment) && NextNonComment &&
@@ -2430,6 +2476,14 @@
if (Next->MatchingParen->Next &&
Next->MatchingParen->Next->is(TT_PointerOrReference))
return true;
+ // Check for K&R C function definitions, e.g.:
+ // int f(i)
+ // {
+ // return i + 1;
+ // }
+ if (Next->Next && Next->Next->is(tok::identifier) &&
+ !(Next->MatchingParen->Next && Next->MatchingParen->Next->is(tok::semi)))
+ return true;
for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen;
Tok = Tok->Next) {
if (Tok->is(TT_TypeDeclarationParen))
@@ -2483,6 +2537,12 @@
: Line.FirstStartColumn + Line.First->ColumnWidth;
FormatToken *Current = Line.First->Next;
bool InFunctionDecl = Line.MightBeFunctionDecl;
+ bool AlignArrayOfStructures =
+ (Style.AlignArrayOfStructures != FormatStyle::AIAS_None &&
+ Line.Type == LT_ArrayOfStructInitializer);
+ if (AlignArrayOfStructures)
+ calculateArrayInitializerColumnList(Line);
+
while (Current) {
if (isFunctionDeclarationName(*Current, Line))
Current->setType(TT_FunctionDeclarationName);
@@ -2602,6 +2662,45 @@
}
}
+void TokenAnnotator::calculateArrayInitializerColumnList(AnnotatedLine &Line) {
+ if (Line.First == Line.Last) {
+ return;
+ }
+ auto *CurrentToken = Line.First;
+ CurrentToken->ArrayInitializerLineStart = true;
+ unsigned Depth = 0;
+ while (CurrentToken != nullptr && CurrentToken != Line.Last) {
+ if (CurrentToken->is(tok::l_brace)) {
+ CurrentToken->IsArrayInitializer = true;
+ if (CurrentToken->Next != nullptr)
+ CurrentToken->Next->MustBreakBefore = true;
+ CurrentToken =
+ calculateInitializerColumnList(Line, CurrentToken->Next, Depth + 1);
+ } else {
+ CurrentToken = CurrentToken->Next;
+ }
+ }
+}
+
+FormatToken *TokenAnnotator::calculateInitializerColumnList(
+ AnnotatedLine &Line, FormatToken *CurrentToken, unsigned Depth) {
+ while (CurrentToken != nullptr && CurrentToken != Line.Last) {
+ if (CurrentToken->is(tok::l_brace))
+ ++Depth;
+ else if (CurrentToken->is(tok::r_brace))
+ --Depth;
+ if (Depth == 2 && CurrentToken->isOneOf(tok::l_brace, tok::comma)) {
+ CurrentToken = CurrentToken->Next;
+ if (CurrentToken == nullptr)
+ break;
+ CurrentToken->StartsColumn = true;
+ CurrentToken = CurrentToken->Previous;
+ }
+ CurrentToken = CurrentToken->Next;
+ }
+ return CurrentToken;
+}
+
unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
const FormatToken &Tok,
bool InFunctionDecl) {
@@ -2809,6 +2908,8 @@
const FormatToken &Right) {
if (Left.is(tok::kw_return) && Right.isNot(tok::semi))
return true;
+ if (Style.isJson() && Left.is(tok::string_literal) && Right.is(tok::colon))
+ return false;
if (Left.is(Keywords.kw_assert) && Style.Language == FormatStyle::LK_Java)
return true;
if (Style.ObjCSpaceAfterProperty && Line.Type == LT_ObjCProperty &&
@@ -2897,16 +2998,17 @@
Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both) &&
(Left.is(TT_AttributeParen) || Left.canBePointerOrReferenceQualifier()))
return true;
- return (Left.Tok.isLiteral() ||
- (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
- (Style.PointerAlignment != FormatStyle::PAS_Left ||
- (Line.IsMultiVariableDeclStmt &&
- (Left.NestingLevel == 0 ||
- (Left.NestingLevel == 1 && Line.First->is(tok::kw_for)))))));
+ return (
+ Left.Tok.isLiteral() ||
+ (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
+ (getTokenPointerOrReferenceAlignment(Right) != FormatStyle::PAS_Left ||
+ (Line.IsMultiVariableDeclStmt &&
+ (Left.NestingLevel == 0 ||
+ (Left.NestingLevel == 1 && Line.First->is(tok::kw_for)))))));
}
if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
(!Left.is(TT_PointerOrReference) ||
- (Style.PointerAlignment != FormatStyle::PAS_Right &&
+ (getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right &&
!Line.IsMultiVariableDeclStmt)))
return true;
if (Left.is(TT_PointerOrReference)) {
@@ -2922,7 +3024,8 @@
(Right.is(tok::l_brace) && Right.is(BK_Block)) ||
(!Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,
tok::l_paren) &&
- (Style.PointerAlignment != FormatStyle::PAS_Right &&
+ (getTokenPointerOrReferenceAlignment(Left) !=
+ FormatStyle::PAS_Right &&
!Line.IsMultiVariableDeclStmt) &&
Left.Previous &&
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon,
@@ -2957,6 +3060,8 @@
// Space between the type and the * in:
// operator void*()
// operator char*()
+ // operator void const*()
+ // operator void volatile*()
// operator /*comment*/ const char*()
// operator volatile /*comment*/ char*()
// operator Foo*()
@@ -2964,11 +3069,15 @@
// operator std::Foo*()
// operator C<T>::D<U>*()
// dependent on PointerAlignment style.
- if (Previous &&
- (Previous->endsSequence(tok::kw_operator) ||
- Previous->endsSequence(tok::kw_const, tok::kw_operator) ||
- Previous->endsSequence(tok::kw_volatile, tok::kw_operator)))
- return (Style.PointerAlignment != FormatStyle::PAS_Left);
+ if (Previous) {
+ if (Previous->endsSequence(tok::kw_operator))
+ return (Style.PointerAlignment != FormatStyle::PAS_Left);
+ if (Previous->is(tok::kw_const) || Previous->is(tok::kw_volatile))
+ return (Style.PointerAlignment != FormatStyle::PAS_Left) ||
+ (Style.SpaceAroundPointerQualifiers ==
+ FormatStyle::SAPQ_After) ||
+ (Style.SpaceAroundPointerQualifiers == FormatStyle::SAPQ_Both);
+ }
}
const auto SpaceRequiredForArrayInitializerLSquare =
[](const FormatToken &LSquareTok, const FormatStyle &Style) {
@@ -3023,9 +3132,13 @@
(Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
return true;
if (Style.SpaceBeforeParens ==
- FormatStyle::SBPO_ControlStatementsExceptForEachMacros &&
+ FormatStyle::SBPO_ControlStatementsExceptControlMacros &&
Left.is(TT_ForEachMacro))
return false;
+ if (Style.SpaceBeforeParens ==
+ FormatStyle::SBPO_ControlStatementsExceptControlMacros &&
+ Left.is(TT_IfMacro))
+ return false;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
(Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while,
@@ -3081,13 +3194,16 @@
// Match const and volatile ref-qualifiers without any additional
// qualifiers such as
// void Fn() const &;
- return Style.PointerAlignment != FormatStyle::PAS_Left;
+ return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
return true;
}
bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
const FormatToken &Right) {
const FormatToken &Left = *Right.Previous;
+ auto HasExistingWhitespace = [&Right]() {
+ return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
+ };
if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
return true; // Never ever merge two identifiers.
if (Style.isCpp()) {
@@ -3120,7 +3236,10 @@
// Preserve the existence of a space before a percent for cases like 0x%04x
// and "%d %d"
if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
- return Right.WhitespaceRange.getEnd() != Right.WhitespaceRange.getBegin();
+ return HasExistingWhitespace();
+ } else if (Style.isJson()) {
+ if (Right.is(tok::colon))
+ return false;
} else if (Style.isCSharp()) {
// Require spaces around '{' and before '}' unless they appear in
// interpolated strings. Interpolated strings are merged into a single token
@@ -3146,7 +3265,7 @@
return true;
// Spaces around '=>'.
- if (Left.is(TT_JsFatArrow) || Right.is(TT_JsFatArrow))
+ if (Left.is(TT_FatArrow) || Right.is(TT_FatArrow))
return true;
// No spaces around attribute target colons
@@ -3165,30 +3284,14 @@
if (Right.is(TT_CSharpNullable))
return false;
- // Require space after ? in nullable types except in generics and casts.
- if (Left.is(TT_CSharpNullable))
- return !Right.isOneOf(TT_TemplateCloser, tok::r_paren);
-
- // No space before or after '?.'.
- if (Left.is(TT_CSharpNullConditional) || Right.is(TT_CSharpNullConditional))
- return false;
-
- // Space before and after '??'.
- if (Left.is(TT_CSharpNullCoalescing) || Right.is(TT_CSharpNullCoalescing))
- return true;
-
- // No space before '?['.
- if (Right.is(TT_CSharpNullConditionalLSquare))
+ // No space before null forgiving '!'.
+ if (Right.is(TT_NonNullAssertion))
return false;
// No space between consecutive commas '[,,]'.
if (Left.is(tok::comma) && Right.is(tok::comma))
return false;
- // Possible space inside `?[ 0 ]`.
- if (Left.is(TT_CSharpNullConditionalLSquare))
- return Style.SpacesInSquareBrackets;
-
// space after var in `var (key, value)`
if (Left.is(Keywords.kw_var) && Right.is(tok::l_paren))
return true;
@@ -3210,7 +3313,7 @@
Right.is(tok::l_paren))
return true;
} else if (Style.Language == FormatStyle::LK_JavaScript) {
- if (Left.is(TT_JsFatArrow))
+ if (Left.is(TT_FatArrow))
return true;
// for await ( ...
if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&
@@ -3221,7 +3324,7 @@
const FormatToken *Next = Right.MatchingParen->getNextNonComment();
// An async arrow function, for example: `x = async () => foo();`,
// as opposed to calling a function called async: `x = async();`
- if (Next && Next->is(TT_JsFatArrow))
+ if (Next && Next->is(TT_FatArrow))
return true;
}
if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
@@ -3295,9 +3398,9 @@
// locations that should have whitespace following are identified by the
// above set of follower tokens.
return false;
- if (Right.is(TT_JsNonNullAssertion))
+ if (Right.is(TT_NonNullAssertion))
return false;
- if (Left.is(TT_JsNonNullAssertion) &&
+ if (Left.is(TT_NonNullAssertion) &&
Right.isOneOf(Keywords.kw_as, Keywords.kw_in))
return true; // "x! as string", "x! in y"
} else if (Style.Language == FormatStyle::LK_Java) {
@@ -3313,7 +3416,7 @@
return true;
}
if (Left.is(TT_ImplicitStringLiteral))
- return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
+ return HasExistingWhitespace();
if (Line.Type == LT_ObjCMethodDecl) {
if (Left.is(TT_ObjCMethodSpecifier))
return true;
@@ -3370,6 +3473,12 @@
Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
return true;
}
+ // Do not merge "- -" into "--".
+ if ((Left.isOneOf(tok::minus, tok::minusminus) &&
+ Right.isOneOf(tok::minus, tok::minusminus)) ||
+ (Left.isOneOf(tok::plus, tok::plusplus) &&
+ Right.isOneOf(tok::plus, tok::plusplus)))
+ return true;
if (Left.is(TT_UnaryOperator)) {
if (!Right.is(tok::l_paren)) {
// The alternative operators for ~ and ! are "compl" and "not".
@@ -3394,12 +3503,21 @@
return Style.SpaceAfterCStyleCast ||
Right.isOneOf(TT_BinaryOperator, TT_SelectorName);
+ auto ShouldAddSpacesInAngles = [this, &HasExistingWhitespace]() {
+ if (this->Style.SpacesInAngles == FormatStyle::SIAS_Always)
+ return true;
+ if (this->Style.SpacesInAngles == FormatStyle::SIAS_Leave)
+ return HasExistingWhitespace();
+ return false;
+ };
+
if (Left.is(tok::greater) && Right.is(tok::greater)) {
if (Style.Language == FormatStyle::LK_TextProto ||
(Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral)))
return !Style.Cpp11BracedListStyle;
return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
- (Style.Standard < FormatStyle::LS_Cpp11 || Style.SpacesInAngles);
+ ((Style.Standard < FormatStyle::LS_Cpp11) ||
+ ShouldAddSpacesInAngles());
}
if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
@@ -3415,26 +3533,27 @@
// Generally don't remove existing spaces between an identifier and "::".
// The identifier might actually be a macro name such as ALWAYS_INLINE. If
// this turns out to be too lenient, add analysis of the identifier itself.
- return Right.WhitespaceRange.getBegin() != Right.WhitespaceRange.getEnd();
+ return HasExistingWhitespace();
if (Right.is(tok::coloncolon) &&
!Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren))
// Put a space between < and :: in vector< ::std::string >
return (Left.is(TT_TemplateOpener) &&
- (Style.Standard < FormatStyle::LS_Cpp11 || Style.SpacesInAngles)) ||
+ ((Style.Standard < FormatStyle::LS_Cpp11) ||
+ ShouldAddSpacesInAngles())) ||
!(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
tok::kw___super, TT_TemplateOpener,
TT_TemplateCloser)) ||
(Left.is(tok::l_paren) && Style.SpacesInParentheses);
if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
- return Style.SpacesInAngles;
+ return ShouldAddSpacesInAngles();
// Space before TT_StructuredBindingLSquare.
if (Right.is(TT_StructuredBindingLSquare))
return !Left.isOneOf(tok::amp, tok::ampamp) ||
- Style.PointerAlignment != FormatStyle::PAS_Right;
+ getTokenReferenceAlignment(Left) != FormatStyle::PAS_Right;
// Space before & or && following a TT_StructuredBindingLSquare.
if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) &&
Right.isOneOf(tok::amp, tok::ampamp))
- return Style.PointerAlignment != FormatStyle::PAS_Left;
+ return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
(Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
!Right.is(tok::r_paren)))
@@ -3473,42 +3592,11 @@
return Tok.Children.empty() && ShortLambdaOption != FormatStyle::SLS_None;
}
-static bool
-isItAInlineLambdaAllowed(const FormatToken &Tok,
- FormatStyle::ShortLambdaStyle ShortLambdaOption) {
- return (ShortLambdaOption == FormatStyle::SLS_Inline &&
- IsFunctionArgument(Tok)) ||
- (ShortLambdaOption == FormatStyle::SLS_All);
-}
-
-static bool isOneChildWithoutMustBreakBefore(const FormatToken &Tok) {
- if (Tok.Children.size() != 1)
- return false;
- FormatToken *curElt = Tok.Children[0]->First;
- while (curElt) {
- if (curElt->MustBreakBefore)
- return false;
- curElt = curElt->Next;
- }
- return true;
-}
static bool isAllmanLambdaBrace(const FormatToken &Tok) {
return (Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
!Tok.isOneOf(TT_ObjCBlockLBrace, TT_DictLiteral));
}
-static bool isAllmanBraceIncludedBreakableLambda(
- const FormatToken &Tok, FormatStyle::ShortLambdaStyle ShortLambdaOption) {
- if (!isAllmanLambdaBrace(Tok))
- return false;
-
- if (isItAnEmptyLambdaAllowed(Tok, ShortLambdaOption))
- return false;
-
- return !isItAInlineLambdaAllowed(Tok, ShortLambdaOption) ||
- !isOneChildWithoutMustBreakBefore(Tok);
-}
-
bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
const FormatToken &Right) {
const FormatToken &Left = *Right.Previous;
@@ -3521,6 +3609,17 @@
return false;
if (Right.is(TT_CSharpGenericTypeConstraint))
return true;
+
+ // Break after C# [...] and before public/protected/private/internal.
+ if (Left.is(TT_AttributeSquare) && Left.is(tok::r_square) &&
+ (Right.isAccessSpecifier(/*ColonRequired=*/false) ||
+ Right.is(Keywords.kw_internal)))
+ return true;
+ // Break between ] and [ but only when there are really 2 attributes.
+ if (Left.is(TT_AttributeSquare) && Right.is(TT_AttributeSquare) &&
+ Left.is(tok::r_square) && Right.is(tok::l_square))
+ return true;
+
} else if (Style.Language == FormatStyle::LK_JavaScript) {
// FIXME: This might apply to other languages and token kinds.
if (Right.is(tok::string_literal) && Left.is(tok::plus) && Left.Previous &&
@@ -3545,7 +3644,7 @@
// instead of bin-packing.
return true;
if (Right.is(tok::r_brace) && Left.is(tok::l_brace) && Left.Previous &&
- Left.Previous->is(TT_JsFatArrow)) {
+ Left.Previous->is(TT_FatArrow)) {
// JS arrow function (=> {...}).
switch (Style.AllowShortLambdasOnASingleLine) {
case FormatStyle::SLS_All:
@@ -3584,6 +3683,26 @@
return true;
}
+ // Basic JSON newline processing.
+ if (Style.isJson()) {
+ // Always break after a JSON record opener.
+ // {
+ // }
+ if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace))
+ return true;
+ // Always break after a JSON array opener.
+ // [
+ // ]
+ if (Left.is(TT_ArrayInitializerLSquare) && Left.is(tok::l_square) &&
+ !Right.is(tok::r_square))
+ return true;
+ // Always break afer successive entries.
+ // 1,
+ // 2
+ if (Left.is(tok::comma))
+ return true;
+ }
+
// If the last token before a '}', ']', or ')' is a comma or a trailing
// comment, the intention is to insert a line break after it in order to make
// shuffling around entries easier. Import statements, especially in
@@ -3640,6 +3759,9 @@
if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma &&
Right.is(TT_InheritanceComma))
return true;
+ if (Style.BreakInheritanceList == FormatStyle::BILS_AfterComma &&
+ Left.is(TT_InheritanceComma))
+ return true;
if (Right.is(tok::string_literal) && Right.TokenText.startswith("R\""))
// Multiline raw string literals are special wrt. line breaks. The author
// has made a deliberate choice and might have aligned the contents of the
@@ -3656,13 +3778,6 @@
if (Right.is(TT_InlineASMBrace))
return Right.HasUnescapedNewline;
- auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
- if (Style.BraceWrapping.BeforeLambdaBody &&
- (isAllmanBraceIncludedBreakableLambda(Left, ShortLambdaOption) ||
- isAllmanBraceIncludedBreakableLambda(Right, ShortLambdaOption))) {
- return true;
- }
-
if (isAllmanBrace(Left) || isAllmanBrace(Right))
return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) ||
(Line.startsWith(tok::kw_typedef, tok::kw_enum) &&
@@ -3685,6 +3800,11 @@
return true;
}
+ if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&
+ Left.isOneOf(tok::star, tok::amp, tok::ampamp, TT_TemplateCloser)) {
+ return true;
+ }
+
// Put multiple Java annotation on a new line.
if ((Style.Language == FormatStyle::LK_Java ||
Style.Language == FormatStyle::LK_JavaScript) &&
@@ -3819,6 +3939,10 @@
// Only break after commas for generic type constraints.
if (Line.First->is(TT_CSharpGenericTypeConstraint))
return Left.is(TT_CSharpGenericTypeConstraintComma);
+ // Keep nullable operators attached to their identifiers.
+ if (Right.is(TT_CSharpNullable)) {
+ return false;
+ }
} else if (Style.Language == FormatStyle::LK_Java) {
if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
Keywords.kw_implements))
@@ -3841,7 +3965,10 @@
Left.isOneOf(tok::r_square, tok::r_paren)) &&
Right.isOneOf(tok::l_square, tok::l_paren))
return false; // Otherwise automatic semicolon insertion would trigger.
- if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
+ if (NonComment && NonComment->is(tok::identifier) &&
+ NonComment->TokenText == "asserts")
+ return false;
+ if (Left.is(TT_FatArrow) && Right.is(tok::l_brace))
return false;
if (Left.is(TT_JsTypeColon))
return true;
@@ -3877,7 +4004,7 @@
}
if (Left.is(Keywords.kw_as))
return true;
- if (Left.is(TT_JsNonNullAssertion))
+ if (Left.is(TT_NonNullAssertion))
return true;
if (Left.is(Keywords.kw_declare) &&
Right.isOneOf(Keywords.kw_module, tok::kw_namespace,
@@ -3909,7 +4036,8 @@
return !Right.is(tok::l_paren);
if (Right.is(TT_PointerOrReference))
return Line.IsMultiVariableDeclStmt ||
- (Style.PointerAlignment == FormatStyle::PAS_Right &&
+ (getTokenPointerOrReferenceAlignment(Right) ==
+ FormatStyle::PAS_Right &&
(!Right.Next || Right.Next->isNot(TT_FunctionDeclarationName)));
if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
Right.is(tok::kw_operator))
@@ -4081,7 +4209,7 @@
return false;
auto ShortLambdaOption = Style.AllowShortLambdasOnASingleLine;
- if (Style.BraceWrapping.BeforeLambdaBody) {
+ if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) {
if (isAllmanLambdaBrace(Left))
return !isItAnEmptyLambdaAllowed(Left, ShortLambdaOption);
if (isAllmanLambdaBrace(Right))
@@ -4093,7 +4221,6 @@
Right.isMemberAccess() ||
Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless,
tok::colon, tok::l_square, tok::at) ||
- (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace)) ||
(Left.is(tok::r_paren) &&
Right.isOneOf(tok::identifier, tok::kw_const)) ||
(Left.is(tok::l_paren) && !Right.is(tok::r_paren)) ||
@@ -4124,5 +4251,41 @@
llvm::errs() << "----\n";
}
+FormatStyle::PointerAlignmentStyle
+TokenAnnotator::getTokenReferenceAlignment(const FormatToken &Reference) {
+ assert(Reference.isOneOf(tok::amp, tok::ampamp));
+ switch (Style.ReferenceAlignment) {
+ case FormatStyle::RAS_Pointer:
+ return Style.PointerAlignment;
+ case FormatStyle::RAS_Left:
+ return FormatStyle::PAS_Left;
+ case FormatStyle::RAS_Right:
+ return FormatStyle::PAS_Right;
+ case FormatStyle::RAS_Middle:
+ return FormatStyle::PAS_Middle;
+ }
+ assert(0); //"Unhandled value of ReferenceAlignment"
+ return Style.PointerAlignment;
+}
+
+FormatStyle::PointerAlignmentStyle
+TokenAnnotator::getTokenPointerOrReferenceAlignment(
+ const FormatToken &PointerOrReference) {
+ if (PointerOrReference.isOneOf(tok::amp, tok::ampamp)) {
+ switch (Style.ReferenceAlignment) {
+ case FormatStyle::RAS_Pointer:
+ return Style.PointerAlignment;
+ case FormatStyle::RAS_Left:
+ return FormatStyle::PAS_Left;
+ case FormatStyle::RAS_Right:
+ return FormatStyle::PAS_Right;
+ case FormatStyle::RAS_Middle:
+ return FormatStyle::PAS_Middle;
+ }
+ }
+ assert(PointerOrReference.is(tok::star));
+ return Style.PointerAlignment;
+}
+
} // namespace format
} // namespace clang
diff --git a/src/llvm-project/clang/lib/Format/TokenAnnotator.h b/src/llvm-project/clang/lib/Format/TokenAnnotator.h
index 5377100..0f9c02d 100644
--- a/src/llvm-project/clang/lib/Format/TokenAnnotator.h
+++ b/src/llvm-project/clang/lib/Format/TokenAnnotator.h
@@ -31,7 +31,8 @@
LT_ObjCProperty, // An @property line.
LT_Other,
LT_PreprocessorDirective,
- LT_VirtualFunctionDecl
+ LT_VirtualFunctionDecl,
+ LT_ArrayOfStructInitializer,
};
class AnnotatedLine {
@@ -189,6 +190,17 @@
void calculateUnbreakableTailLengths(AnnotatedLine &Line);
+ void calculateArrayInitializerColumnList(AnnotatedLine &Line);
+
+ FormatToken *calculateInitializerColumnList(AnnotatedLine &Line,
+ FormatToken *CurrentToken,
+ unsigned Depth);
+ FormatStyle::PointerAlignmentStyle
+ getTokenReferenceAlignment(const FormatToken &PointerOrReference);
+
+ FormatStyle::PointerAlignmentStyle
+ getTokenPointerOrReferenceAlignment(const FormatToken &PointerOrReference);
+
const FormatStyle &Style;
const AdditionalKeywords &Keywords;
diff --git a/src/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp b/src/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
index 7d19731..cca85c1 100644
--- a/src/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/src/llvm-project/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -57,7 +57,9 @@
while (IndentForLevel.size() <= Line.Level)
IndentForLevel.push_back(-1);
if (Line.InPPDirective) {
- Indent = Line.Level * Style.IndentWidth + AdditionalIndent;
+ unsigned IndentWidth =
+ (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
+ Indent = Line.Level * IndentWidth + AdditionalIndent;
} else {
IndentForLevel.resize(Line.Level + 1);
Indent = getIndent(IndentForLevel, Line.Level);
@@ -101,8 +103,13 @@
if (RootToken.isAccessSpecifier(false) ||
RootToken.isObjCAccessSpecifier() ||
(RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
- RootToken.Next && RootToken.Next->is(tok::colon)))
- return Style.AccessModifierOffset;
+ RootToken.Next && RootToken.Next->is(tok::colon))) {
+ // The AccessModifierOffset may be overriden by IndentAccessModifiers,
+ // in which case we take a negative value of the IndentWidth to simulate
+ // the upper indent level.
+ return Style.IndentAccessModifiers ? -Style.IndentWidth
+ : Style.AccessModifierOffset;
+ }
return 0;
}
@@ -416,7 +423,17 @@
}
return MergedLines;
}
- if (TheLine->First->is(tok::kw_if)) {
+ auto IsElseLine = [&TheLine]() -> bool {
+ const FormatToken *First = TheLine->First;
+ if (First->is(tok::kw_else))
+ return true;
+
+ return First->is(tok::r_brace) && First->Next &&
+ First->Next->is(tok::kw_else);
+ };
+ if (TheLine->First->is(tok::kw_if) ||
+ (IsElseLine() && (Style.AllowShortIfStatementsOnASingleLine ==
+ FormatStyle::SIS_AllIfsAndElse))) {
return Style.AllowShortIfStatementsOnASingleLine
? tryMergeSimpleControlStatement(I, E, Limit)
: 0;
@@ -466,7 +483,8 @@
return 0;
Limit = limitConsideringMacros(I + 1, E, Limit);
AnnotatedLine &Line = **I;
- if (!Line.First->is(tok::kw_do) && Line.Last->isNot(tok::r_paren))
+ if (!Line.First->is(tok::kw_do) && !Line.First->is(tok::kw_else) &&
+ !Line.Last->is(tok::kw_else) && Line.Last->isNot(tok::r_paren))
return 0;
// Only merge do while if do is the only statement on the line.
if (Line.First->is(tok::kw_do) && !Line.Last->is(tok::kw_do))
@@ -477,7 +495,8 @@
TT_LineComment))
return 0;
// Only inline simple if's (no nested if or else), unless specified
- if (Style.AllowShortIfStatementsOnASingleLine != FormatStyle::SIS_Always) {
+ if (Style.AllowShortIfStatementsOnASingleLine ==
+ FormatStyle::SIS_WithoutElse) {
if (I + 2 != E && Line.startsWith(tok::kw_if) &&
I[2]->First->is(tok::kw_else))
return 0;
@@ -804,8 +823,20 @@
return true;
if (NewLine) {
- int AdditionalIndent = State.Stack.back().Indent -
- Previous.Children[0]->Level * Style.IndentWidth;
+ const ParenState &P = State.Stack.back();
+
+ int AdditionalIndent =
+ P.Indent - Previous.Children[0]->Level * Style.IndentWidth;
+
+ if (Style.LambdaBodyIndentation == FormatStyle::LBI_OuterScope &&
+ P.NestedBlockIndent == P.LastSpace) {
+ if (State.NextToken->MatchingParen &&
+ State.NextToken->MatchingParen->is(TT_LambdaLBrace)) {
+ State.Stack.pop_back();
+ }
+ if (LBrace->is(TT_LambdaLBrace))
+ AdditionalIndent = 0;
+ }
Penalty +=
BlockFormatter->format(Previous.Children, DryRun, AdditionalIndent,
@@ -1103,6 +1134,7 @@
unsigned Penalty = 0;
LevelIndentTracker IndentTracker(Style, Keywords, Lines[0]->Level,
AdditionalIndent);
+ const AnnotatedLine *PrevPrevLine = nullptr;
const AnnotatedLine *PreviousLine = nullptr;
const AnnotatedLine *NextLine = nullptr;
@@ -1141,7 +1173,7 @@
if (ShouldFormat && TheLine.Type != LT_Invalid) {
if (!DryRun) {
bool LastLine = Line->First->is(tok::eof);
- formatFirstToken(TheLine, PreviousLine, Lines, Indent,
+ formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines, Indent,
LastLine ? LastStartColumn : NextStartColumn + Indent);
}
@@ -1187,7 +1219,7 @@
TheLine.LeadingEmptyLinesAffected);
// Format the first token.
if (ReformatLeadingWhitespace)
- formatFirstToken(TheLine, PreviousLine, Lines,
+ formatFirstToken(TheLine, PreviousLine, PrevPrevLine, Lines,
TheLine.First->OriginalColumn,
TheLine.First->OriginalColumn);
else
@@ -1203,6 +1235,7 @@
}
if (!DryRun)
markFinalized(TheLine.First);
+ PrevPrevLine = PreviousLine;
PreviousLine = &TheLine;
}
PenaltyCache[CacheKey] = Penalty;
@@ -1211,6 +1244,7 @@
void UnwrappedLineFormatter::formatFirstToken(
const AnnotatedLine &Line, const AnnotatedLine *PreviousLine,
+ const AnnotatedLine *PrevPrevLine,
const SmallVectorImpl<AnnotatedLine *> &Lines, unsigned Indent,
unsigned NewlineIndent) {
FormatToken &RootToken = *Line.First;
@@ -1242,6 +1276,8 @@
if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
PreviousLine->Last->is(tok::l_brace) &&
!PreviousLine->startsWithNamespace() &&
+ !(PrevPrevLine && PrevPrevLine->startsWithNamespace() &&
+ PreviousLine->startsWith(tok::l_brace)) &&
!startsExternCBlock(*PreviousLine))
Newlines = 1;
@@ -1249,16 +1285,17 @@
if (PreviousLine && RootToken.isAccessSpecifier()) {
switch (Style.EmptyLineBeforeAccessModifier) {
case FormatStyle::ELBAMS_Never:
- if (RootToken.NewlinesBefore > 1)
+ if (Newlines > 1)
Newlines = 1;
break;
case FormatStyle::ELBAMS_Leave:
Newlines = std::max(RootToken.NewlinesBefore, 1u);
break;
case FormatStyle::ELBAMS_LogicalBlock:
- if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&
- RootToken.NewlinesBefore <= 1)
+ if (PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) && Newlines <= 1)
Newlines = 2;
+ if (PreviousLine->First->isAccessSpecifier())
+ Newlines = 1; // Previous is an access modifier remove all new lines.
break;
case FormatStyle::ELBAMS_Always: {
const FormatToken *previousToken;
@@ -1266,17 +1303,34 @@
previousToken = PreviousLine->Last->getPreviousNonComment();
else
previousToken = PreviousLine->Last;
- if ((!previousToken || !previousToken->is(tok::l_brace)) &&
- RootToken.NewlinesBefore <= 1)
+ if ((!previousToken || !previousToken->is(tok::l_brace)) && Newlines <= 1)
Newlines = 2;
} break;
}
}
- // Remove empty lines after access specifiers.
+ // Insert or remove empty line after access specifiers.
if (PreviousLine && PreviousLine->First->isAccessSpecifier() &&
- (!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline))
- Newlines = std::min(1u, Newlines);
+ (!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline)) {
+ // EmptyLineBeforeAccessModifier is handling the case when two access
+ // modifiers follow each other.
+ if (!RootToken.isAccessSpecifier()) {
+ switch (Style.EmptyLineAfterAccessModifier) {
+ case FormatStyle::ELAAMS_Never:
+ Newlines = 1;
+ break;
+ case FormatStyle::ELAAMS_Leave:
+ Newlines = std::max(Newlines, 1u);
+ break;
+ case FormatStyle::ELAAMS_Always:
+ if (RootToken.is(tok::r_brace)) // Do not add at end of class.
+ Newlines = 1u;
+ else
+ Newlines = std::max(Newlines, 2u);
+ break;
+ }
+ }
+ }
if (Newlines)
Indent = NewlineIndent;
diff --git a/src/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h b/src/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h
index a1ff169..3e33de0 100644
--- a/src/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h
+++ b/src/llvm-project/clang/lib/Format/UnwrappedLineFormatter.h
@@ -47,6 +47,7 @@
/// of the \c UnwrappedLine if there was no structural parsing error.
void formatFirstToken(const AnnotatedLine &Line,
const AnnotatedLine *PreviousLine,
+ const AnnotatedLine *PrevPrevLine,
const SmallVectorImpl<AnnotatedLine *> &Lines,
unsigned Indent, unsigned NewlineIndent);
diff --git a/src/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp b/src/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
index bec18bd..103e355 100644
--- a/src/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/src/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
@@ -431,7 +431,7 @@
}
LLVM_FALLTHROUGH;
default:
- parseStructuralElement();
+ parseStructuralElement(/*IsTopLevel=*/true);
break;
}
} while (!eof());
@@ -649,7 +649,6 @@
nextToken();
Line->Level = InitialLevel;
- FormatTok->setBlockKind(BK_Block);
if (PPStartHash == PPEndHash) {
Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
@@ -752,6 +751,8 @@
case tok::pp_else:
parsePPElse();
break;
+ case tok::pp_elifdef:
+ case tok::pp_elifndef:
case tok::pp_elif:
parsePPElIf();
break;
@@ -993,6 +994,33 @@
Keywords.kw_import, tok::kw_export);
}
+// This function checks whether a token starts the first parameter declaration
+// in a K&R C (aka C78) function definition, e.g.:
+// int f(a, b)
+// short a, b;
+// {
+// return a + b;
+// }
+static bool isC78ParameterDecl(const FormatToken *Tok) {
+ if (!Tok)
+ return false;
+
+ if (!Tok->isOneOf(tok::kw_int, tok::kw_char, tok::kw_float, tok::kw_double,
+ tok::kw_struct, tok::kw_union, tok::kw_long, tok::kw_short,
+ tok::kw_unsigned, tok::kw_register, tok::identifier))
+ return false;
+
+ Tok = Tok->Previous;
+ if (!Tok || Tok->isNot(tok::r_paren))
+ return false;
+
+ Tok = Tok->Previous;
+ if (!Tok || Tok->isNot(tok::identifier))
+ return false;
+
+ return Tok->Previous && Tok->Previous->isOneOf(tok::l_paren, tok::comma);
+}
+
// readTokenWithJavaScriptASI reads the next token and terminates the current
// line if JavaScript Automatic Semicolon Insertion must
// happen between the current token and the next token.
@@ -1040,7 +1068,7 @@
return addUnwrappedLine();
}
-void UnwrappedLineParser::parseStructuralElement() {
+void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
assert(!FormatTok->is(tok::l_brace));
if (Style.Language == FormatStyle::LK_TableGen &&
FormatTok->is(tok::pp_include)) {
@@ -1138,12 +1166,12 @@
if (Style.BraceWrapping.AfterExternBlock) {
addUnwrappedLine();
}
- parseBlock(/*MustBeDeclaration=*/true,
- /*AddLevel=*/Style.BraceWrapping.AfterExternBlock);
+ unsigned AddLevels = Style.BraceWrapping.AfterExternBlock ? 1u : 0u;
+ parseBlock(/*MustBeDeclaration=*/true, AddLevels);
} else {
- parseBlock(/*MustBeDeclaration=*/true,
- /*AddLevel=*/Style.IndentExternBlock ==
- FormatStyle::IEBS_Indent);
+ unsigned AddLevels =
+ Style.IndentExternBlock == FormatStyle::IEBS_Indent ? 1u : 0u;
+ parseBlock(/*MustBeDeclaration=*/true, AddLevels);
}
addUnwrappedLine();
return;
@@ -1172,7 +1200,7 @@
return;
}
if (FormatTok->is(TT_MacroBlockBegin)) {
- parseBlock(/*MustBeDeclaration=*/false, /*AddLevel=*/true,
+ parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
/*MunchSemi=*/false);
return;
}
@@ -1317,15 +1345,7 @@
case tok::kw_struct:
case tok::kw_union:
case tok::kw_class:
- // parseRecord falls through and does not yet add an unwrapped line as a
- // record declaration or definition can start a structural element.
- parseRecord();
- // This does not apply for Java, JavaScript and C#.
- if (Style.Language == FormatStyle::LK_Java ||
- Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) {
- if (FormatTok->is(tok::semi))
- nextToken();
- addUnwrappedLine();
+ if (parseStructLike()) {
return;
}
break;
@@ -1350,6 +1370,18 @@
return;
case tok::l_paren:
parseParens();
+ // Break the unwrapped line if a K&R C function definition has a parameter
+ // declaration.
+ if (!IsTopLevel || !Style.isCpp())
+ break;
+ if (!Previous || Previous->isNot(tok::identifier))
+ break;
+ if (Previous->Previous && Previous->Previous->is(tok::at))
+ break;
+ if (isC78ParameterDecl(FormatTok)) {
+ addUnwrappedLine();
+ return;
+ }
break;
case tok::kw_operator:
nextToken();
@@ -1439,6 +1471,13 @@
return;
}
+ if (FormatTok->is(Keywords.kw_interface)) {
+ if (parseStructLike()) {
+ return;
+ }
+ break;
+ }
+
if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
parseStatementMacro();
return;
@@ -1482,9 +1521,9 @@
}
case tok::equal:
// Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
- // TT_JsFatArrow. The always start an expression or a child block if
- // followed by a curly.
- if (FormatTok->is(TT_JsFatArrow)) {
+ // TT_FatArrow. They always start an expression or a child block if
+ // followed by a curly brace.
+ if (FormatTok->is(TT_FatArrow)) {
nextToken();
if (FormatTok->is(tok::l_brace)) {
// C# may break after => if the next character is a newline.
@@ -1590,7 +1629,7 @@
--Line->Level;
break;
case tok::equal:
- if (FormatTok->is(TT_JsFatArrow)) {
+ if (FormatTok->is(TT_FatArrow)) {
++Line->Level;
do {
nextToken();
@@ -1790,14 +1829,20 @@
bool HasError = false;
// FIXME: Once we have an expression parser in the UnwrappedLineParser,
- // replace this by using parseAssigmentExpression() inside.
+ // replace this by using parseAssignmentExpression() inside.
do {
if (Style.isCSharp()) {
- if (FormatTok->is(TT_JsFatArrow)) {
+ // Fat arrows (=>) have tok::TokenKind tok::equal but TokenType
+ // TT_FatArrow. They always start an expression or a child block if
+ // followed by a curly brace.
+ if (FormatTok->is(TT_FatArrow)) {
nextToken();
- // Fat arrows can be followed by simple expressions or by child blocks
- // in curly braces.
if (FormatTok->is(tok::l_brace)) {
+ // C# may break after => if the next character is a newline.
+ if (Style.isCSharp() && Style.BraceWrapping.AfterFunction == true) {
+ // calling `addUnwrappedLine()` here causes odd parsing errors.
+ FormatTok->MustBreakBefore = true;
+ }
parseChildBlock();
continue;
}
@@ -1809,7 +1854,7 @@
tryToParseJSFunction();
continue;
}
- if (FormatTok->is(TT_JsFatArrow)) {
+ if (FormatTok->is(TT_FatArrow)) {
nextToken();
// Fat arrows can be followed by simple expressions or by child blocks
// in curly braces.
@@ -1927,6 +1972,12 @@
parseBracedList();
}
break;
+ case tok::equal:
+ if (Style.isCSharp() && FormatTok->is(TT_FatArrow))
+ parseStructuralElement();
+ else
+ nextToken();
+ break;
case tok::kw_class:
if (Style.Language == FormatStyle::LK_JavaScript)
parseRecord(/*ParseAsExpr=*/true);
@@ -2021,7 +2072,15 @@
parseBlock(/*MustBeDeclaration=*/false);
addUnwrappedLine();
} else if (FormatTok->Tok.is(tok::kw_if)) {
+ FormatToken *Previous = AllTokens[Tokens->getPosition() - 1];
+ bool PrecededByComment = Previous->is(tok::comment);
+ if (PrecededByComment) {
+ addUnwrappedLine();
+ ++Line->Level;
+ }
parseIfThenElse();
+ if (PrecededByComment)
+ --Line->Level;
} else {
addUnwrappedLine();
++Line->Level;
@@ -2526,6 +2585,21 @@
// "} n, m;" will end up in one unwrapped line.
}
+bool UnwrappedLineParser::parseStructLike() {
+ // parseRecord falls through and does not yet add an unwrapped line as a
+ // record declaration or definition can start a structural element.
+ parseRecord();
+ // This does not apply to Java, JavaScript and C#.
+ if (Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) {
+ if (FormatTok->is(tok::semi))
+ nextToken();
+ addUnwrappedLine();
+ return true;
+ }
+ return false;
+}
+
namespace {
// A class used to set and restore the Token position when peeking
// ahead in the token source.
@@ -2608,7 +2682,7 @@
while (FormatTok) {
if (FormatTok->is(tok::l_brace)) {
// Parse the constant's class body.
- parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
+ parseBlock(/*MustBeDeclaration=*/true, /*AddLevels=*/1u,
/*MunchSemi=*/false);
} else if (FormatTok->is(tok::l_paren)) {
parseParens();
@@ -2710,8 +2784,8 @@
if (ShouldBreakBeforeBrace(Style, InitialToken))
addUnwrappedLine();
- parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
- /*MunchSemi=*/false);
+ unsigned AddLevels = Style.IndentAccessModifiers ? 2u : 1u;
+ parseBlock(/*MustBeDeclaration=*/true, AddLevels, /*MunchSemi=*/false);
}
}
// There is no addUnwrappedLine() here so that we fall through to parsing a
diff --git a/src/llvm-project/clang/lib/Format/UnwrappedLineParser.h b/src/llvm-project/clang/lib/Format/UnwrappedLineParser.h
index ce135fa..f22bb63 100644
--- a/src/llvm-project/clang/lib/Format/UnwrappedLineParser.h
+++ b/src/llvm-project/clang/lib/Format/UnwrappedLineParser.h
@@ -97,7 +97,7 @@
void parsePPEndIf();
void parsePPUnknown();
void readTokenWithJavaScriptASI();
- void parseStructuralElement();
+ void parseStructuralElement(bool IsTopLevel = false);
bool tryToParseBracedList();
bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false,
tok::TokenKind ClosingBraceKind = tok::r_brace);
@@ -114,6 +114,7 @@
void parseNew();
void parseAccessSpecifier();
bool parseEnum();
+ bool parseStructLike();
void parseConcept();
void parseRequires();
void parseRequiresExpression(unsigned int OriginalLevel);
diff --git a/src/llvm-project/clang/lib/Format/UsingDeclarationsSorter.cpp b/src/llvm-project/clang/lib/Format/UsingDeclarationsSorter.cpp
index b6559db..5608a5a 100644
--- a/src/llvm-project/clang/lib/Format/UsingDeclarationsSorter.cpp
+++ b/src/llvm-project/clang/lib/Format/UsingDeclarationsSorter.cpp
@@ -48,7 +48,7 @@
return -1;
// Two names within a group compare case-insensitively.
- return NamesA[I].compare_lower(NamesB[I]);
+ return NamesA[I].compare_insensitive(NamesB[I]);
}
// I is the last index of NamesB and NamesB[I] is a non-namespace name.
@@ -57,7 +57,7 @@
return 1;
// Two namespaces names within a group compare case-insensitively.
- int C = NamesA[I].compare_lower(NamesB[I]);
+ int C = NamesA[I].compare_insensitive(NamesB[I]);
if (C != 0)
return C;
}
diff --git a/src/llvm-project/clang/lib/Format/WhitespaceManager.cpp b/src/llvm-project/clang/lib/Format/WhitespaceManager.cpp
index 7d6964b..a822e0a 100644
--- a/src/llvm-project/clang/lib/Format/WhitespaceManager.cpp
+++ b/src/llvm-project/clang/lib/Format/WhitespaceManager.cpp
@@ -13,6 +13,8 @@
#include "WhitespaceManager.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
namespace clang {
namespace format {
@@ -100,6 +102,7 @@
alignChainedConditionals();
alignTrailingComments();
alignEscapedNewlines();
+ alignArrayInitializers();
generateChanges();
return Replaces;
@@ -262,7 +265,8 @@
// Align a single sequence of tokens, see AlignTokens below.
template <typename F>
static void
-AlignTokenSequence(unsigned Start, unsigned End, unsigned Column, F &&Matches,
+AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
+ unsigned Column, F &&Matches,
SmallVector<WhitespaceManager::Change, 16> &Changes) {
bool FoundMatchOnLine = false;
int Shift = 0;
@@ -278,6 +282,14 @@
// double z);
// In the above example, we need to take special care to ensure that
// 'double z' is indented along with it's owning function 'b'.
+ // The same holds for calling a function:
+ // double a = foo(x);
+ // int b = bar(foo(y),
+ // foor(z));
+ // Similar for broken string literals:
+ // double x = 3.14;
+ // auto s = "Hello"
+ // "World";
// Special handling is required for 'nested' ternary operators.
SmallVector<unsigned, 16> ScopeStack;
@@ -298,8 +310,12 @@
ScopeStack.push_back(i);
bool InsideNestedScope = ScopeStack.size() != 0;
+ bool ContinuedStringLiteral = i > Start &&
+ Changes[i].Tok->is(tok::string_literal) &&
+ Changes[i - 1].Tok->is(tok::string_literal);
+ bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral;
- if (Changes[i].NewlinesBefore > 0 && !InsideNestedScope) {
+ if (Changes[i].NewlinesBefore > 0 && !SkipMatchCheck) {
Shift = 0;
FoundMatchOnLine = false;
}
@@ -307,7 +323,7 @@
// If this is the first matching token to be aligned, remember by how many
// spaces it has to be shifted, so the rest of the changes on the line are
// shifted by the same amount
- if (!FoundMatchOnLine && !InsideNestedScope && Matches(Changes[i])) {
+ if (!FoundMatchOnLine && !SkipMatchCheck && Matches(Changes[i])) {
FoundMatchOnLine = true;
Shift = Column - Changes[i].StartOfTokenColumn;
Changes[i].Spaces += Shift;
@@ -317,19 +333,62 @@
// as mentioned in the ScopeStack comment.
if (InsideNestedScope && Changes[i].NewlinesBefore > 0) {
unsigned ScopeStart = ScopeStack.back();
- if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName) ||
- (ScopeStart > Start + 1 &&
- Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)) ||
- Changes[i].Tok->is(TT_ConditionalExpr) ||
- (Changes[i].Tok->Previous &&
- Changes[i].Tok->Previous->is(TT_ConditionalExpr)))
+ auto ShouldShiftBeAdded = [&] {
+ // Function declaration
+ if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
+ return true;
+
+ // Continued function declaration
+ if (ScopeStart > Start + 1 &&
+ Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
+ return true;
+
+ // Continued function call
+ if (ScopeStart > Start + 1 &&
+ Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
+ Changes[ScopeStart - 1].Tok->is(tok::l_paren))
+ return Style.BinPackArguments;
+
+ // Ternary operator
+ if (Changes[i].Tok->is(TT_ConditionalExpr))
+ return true;
+
+ // Period Initializer .XXX = 1.
+ if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
+ return true;
+
+ // Continued ternary operator
+ if (Changes[i].Tok->Previous &&
+ Changes[i].Tok->Previous->is(TT_ConditionalExpr))
+ return true;
+
+ return false;
+ };
+
+ if (ShouldShiftBeAdded())
Changes[i].Spaces += Shift;
}
+ if (ContinuedStringLiteral)
+ Changes[i].Spaces += Shift;
+
assert(Shift >= 0);
+
Changes[i].StartOfTokenColumn += Shift;
if (i + 1 != Changes.size())
Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+
+ // If PointerAlignment is PAS_Right, keep *s or &s next to the token
+ if (Style.PointerAlignment == FormatStyle::PAS_Right &&
+ Changes[i].Spaces != 0) {
+ for (int Previous = i - 1;
+ Previous >= 0 &&
+ Changes[Previous].Tok->getType() == TT_PointerOrReference;
+ --Previous) {
+ Changes[Previous + 1].Spaces -= Shift;
+ Changes[Previous].Spaces += Shift;
+ }
+ }
}
}
@@ -399,8 +458,8 @@
// containing any matching token to be aligned and located after such token.
auto AlignCurrentSequence = [&] {
if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
- AlignTokenSequence(StartOfSequence, EndOfSequence, MinColumn, Matches,
- Changes);
+ AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
+ Matches, Changes);
MinColumn = 0;
MaxColumn = UINT_MAX;
StartOfSequence = 0;
@@ -434,7 +493,10 @@
AlignCurrentSequence();
// A new line starts, re-initialize line status tracking bools.
- FoundMatchOnLine = false;
+ // Keep the match state if a string literal is continued on this line.
+ if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
+ !Changes[i - 1].Tok->is(tok::string_literal))
+ FoundMatchOnLine = false;
LineIsComment = true;
}
@@ -687,12 +749,6 @@
if (Style.AlignConsecutiveDeclarations == FormatStyle::ACS_None)
return;
- // FIXME: Currently we don't handle properly the PointerAlignment: Right
- // The * and & are not aligned and are left dangling. Something has to be done
- // about it, but it raises the question of alignment of code like:
- // const char* const* v1;
- // float const* v2;
- // SomeVeryLongType const& v3;
AlignTokens(
Style,
[](Change const &C) {
@@ -709,6 +765,8 @@
for (FormatToken *Next = C.Tok->Next; Next; Next = Next->Next) {
if (Next->is(tok::comment))
continue;
+ if (Next->is(TT_PointerOrReference))
+ return false;
if (!Next->Tok.getIdentifierInfo())
break;
if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
@@ -735,12 +793,11 @@
Changes, /*StartAt=*/0);
} else {
static auto AlignWrappedOperand = [](Change const &C) {
- auto Previous = C.Tok->getPreviousNonComment(); // Previous;
+ FormatToken *Previous = C.Tok->getPreviousNonComment();
return C.NewlinesBefore && Previous && Previous->is(TT_ConditionalExpr) &&
- (Previous->is(tok::question) ||
- (Previous->is(tok::colon) &&
- (C.Tok->FakeLParens.size() == 0 ||
- C.Tok->FakeLParens.back() != prec::Conditional)));
+ (Previous->is(tok::colon) &&
+ (C.Tok->FakeLParens.size() == 0 ||
+ C.Tok->FakeLParens.back() != prec::Conditional));
};
// Ensure we keep alignment of wrapped operands with non-wrapped operands
// Since we actually align the operators, the wrapped operands need the
@@ -902,6 +959,302 @@
}
}
+void WhitespaceManager::alignArrayInitializers() {
+ if (Style.AlignArrayOfStructures == FormatStyle::AIAS_None)
+ return;
+
+ for (unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
+ ChangeIndex < ChangeEnd; ++ChangeIndex) {
+ auto &C = Changes[ChangeIndex];
+ if (C.Tok->IsArrayInitializer) {
+ bool FoundComplete = false;
+ for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
+ ++InsideIndex) {
+ if (Changes[InsideIndex].Tok == C.Tok->MatchingParen) {
+ alignArrayInitializers(ChangeIndex, InsideIndex + 1);
+ ChangeIndex = InsideIndex + 1;
+ FoundComplete = true;
+ break;
+ }
+ }
+ if (!FoundComplete)
+ ChangeIndex = ChangeEnd;
+ }
+ }
+}
+
+void WhitespaceManager::alignArrayInitializers(unsigned Start, unsigned End) {
+
+ if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Right)
+ alignArrayInitializersRightJustified(getCells(Start, End));
+ else if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Left)
+ alignArrayInitializersLeftJustified(getCells(Start, End));
+}
+
+void WhitespaceManager::alignArrayInitializersRightJustified(
+ CellDescriptions &&CellDescs) {
+ auto &Cells = CellDescs.Cells;
+
+ // Now go through and fixup the spaces.
+ auto *CellIter = Cells.begin();
+ for (auto i = 0U; i < CellDescs.CellCount; i++, ++CellIter) {
+ unsigned NetWidth = 0U;
+ if (isSplitCell(*CellIter))
+ NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
+ auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
+
+ if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
+ // So in here we want to see if there is a brace that falls
+ // on a line that was split. If so on that line we make sure that
+ // the spaces in front of the brace are enough.
+ Changes[CellIter->Index].NewlinesBefore = 0;
+ Changes[CellIter->Index].Spaces = 0;
+ for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
+ Next = Next->NextColumnElement) {
+ Changes[Next->Index].Spaces = 0;
+ Changes[Next->Index].NewlinesBefore = 0;
+ }
+ // Unless the array is empty, we need the position of all the
+ // immediately adjacent cells
+ if (CellIter != Cells.begin()) {
+ auto ThisNetWidth =
+ getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
+ auto MaxNetWidth =
+ getMaximumNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces,
+ CellDescs.CellCount);
+ if (ThisNetWidth < MaxNetWidth)
+ Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
+ auto RowCount = 1U;
+ auto Offset = std::distance(Cells.begin(), CellIter);
+ for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
+ Next = Next->NextColumnElement) {
+ auto *Start = (Cells.begin() + RowCount * CellDescs.CellCount);
+ auto *End = Start + Offset;
+ ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
+ if (ThisNetWidth < MaxNetWidth)
+ Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
+ ++RowCount;
+ }
+ }
+ } else {
+ auto ThisWidth =
+ calculateCellWidth(CellIter->Index, CellIter->EndIndex, true) +
+ NetWidth;
+ if (Changes[CellIter->Index].NewlinesBefore == 0) {
+ Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
+ Changes[CellIter->Index].Spaces += (i > 0) ? 1 : 0;
+ }
+ alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
+ for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
+ Next = Next->NextColumnElement) {
+ ThisWidth =
+ calculateCellWidth(Next->Index, Next->EndIndex, true) + NetWidth;
+ if (Changes[Next->Index].NewlinesBefore == 0) {
+ Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
+ Changes[Next->Index].Spaces += (i > 0) ? 1 : 0;
+ }
+ alignToStartOfCell(Next->Index, Next->EndIndex);
+ }
+ }
+ }
+}
+
+void WhitespaceManager::alignArrayInitializersLeftJustified(
+ CellDescriptions &&CellDescs) {
+ auto &Cells = CellDescs.Cells;
+
+ // Now go through and fixup the spaces.
+ auto *CellIter = Cells.begin();
+ // The first cell needs to be against the left brace.
+ if (Changes[CellIter->Index].NewlinesBefore == 0)
+ Changes[CellIter->Index].Spaces = 0;
+ else
+ Changes[CellIter->Index].Spaces = CellDescs.InitialSpaces;
+ ++CellIter;
+ for (auto i = 1U; i < CellDescs.CellCount; i++, ++CellIter) {
+ auto MaxNetWidth = getMaximumNetWidth(
+ Cells.begin(), CellIter, CellDescs.InitialSpaces, CellDescs.CellCount);
+ auto ThisNetWidth =
+ getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
+ if (Changes[CellIter->Index].NewlinesBefore == 0) {
+ Changes[CellIter->Index].Spaces =
+ MaxNetWidth - ThisNetWidth +
+ (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1 : 0);
+ }
+ auto RowCount = 1U;
+ auto Offset = std::distance(Cells.begin(), CellIter);
+ for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
+ Next = Next->NextColumnElement) {
+ auto *Start = (Cells.begin() + RowCount * CellDescs.CellCount);
+ auto *End = Start + Offset;
+ auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
+ if (Changes[Next->Index].NewlinesBefore == 0) {
+ Changes[Next->Index].Spaces =
+ MaxNetWidth - ThisNetWidth +
+ (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : 0);
+ }
+ ++RowCount;
+ }
+ }
+}
+
+bool WhitespaceManager::isSplitCell(const CellDescription &Cell) {
+ if (Cell.HasSplit)
+ return true;
+ for (const auto *Next = Cell.NextColumnElement; Next != nullptr;
+ Next = Next->NextColumnElement) {
+ if (Next->HasSplit)
+ return true;
+ }
+ return false;
+}
+
+WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
+ unsigned End) {
+
+ unsigned Depth = 0;
+ unsigned Cell = 0;
+ unsigned CellCount = 0;
+ unsigned InitialSpaces = 0;
+ unsigned InitialTokenLength = 0;
+ unsigned EndSpaces = 0;
+ SmallVector<CellDescription> Cells;
+ const FormatToken *MatchingParen = nullptr;
+ for (unsigned i = Start; i < End; ++i) {
+ auto &C = Changes[i];
+ if (C.Tok->is(tok::l_brace))
+ ++Depth;
+ else if (C.Tok->is(tok::r_brace))
+ --Depth;
+ if (Depth == 2) {
+ if (C.Tok->is(tok::l_brace)) {
+ Cell = 0;
+ MatchingParen = C.Tok->MatchingParen;
+ if (InitialSpaces == 0) {
+ InitialSpaces = C.Spaces + C.TokenLength;
+ InitialTokenLength = C.TokenLength;
+ auto j = i - 1;
+ for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
+ InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
+ InitialTokenLength += Changes[j].TokenLength;
+ }
+ if (C.NewlinesBefore == 0) {
+ InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
+ InitialTokenLength += Changes[j].TokenLength;
+ }
+ }
+ } else if (C.Tok->is(tok::comma)) {
+ if (!Cells.empty())
+ Cells.back().EndIndex = i;
+ Cell++;
+ }
+ } else if (Depth == 1) {
+ if (C.Tok == MatchingParen) {
+ if (!Cells.empty())
+ Cells.back().EndIndex = i;
+ Cells.push_back(CellDescription{i, ++Cell, i + 1, false, nullptr});
+ CellCount = Cell + 1;
+ // Go to the next non-comment and ensure there is a break in front
+ const auto *NextNonComment = C.Tok->getNextNonComment();
+ while (NextNonComment->is(tok::comma))
+ NextNonComment = NextNonComment->getNextNonComment();
+ auto j = i;
+ while (Changes[j].Tok != NextNonComment && j < End)
+ j++;
+ if (j < End && Changes[j].NewlinesBefore == 0 &&
+ Changes[j].Tok->isNot(tok::r_brace)) {
+ Changes[j].NewlinesBefore = 1;
+ // Account for the added token lengths
+ Changes[j].Spaces = InitialSpaces - InitialTokenLength;
+ }
+ } else if (C.Tok->is(tok::comment)) {
+ // Trailing comments stay at a space past the last token
+ C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
+ } else if (C.Tok->is(tok::l_brace)) {
+ // We need to make sure that the ending braces is aligned to the
+ // start of our initializer
+ auto j = i - 1;
+ for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
+ ; // Nothing the loop does the work
+ EndSpaces = Changes[j].Spaces;
+ }
+ } else if (Depth == 0 && C.Tok->is(tok::r_brace)) {
+ C.NewlinesBefore = 1;
+ C.Spaces = EndSpaces;
+ }
+ if (C.Tok->StartsColumn) {
+ // This gets us past tokens that have been split over multiple
+ // lines
+ bool HasSplit = false;
+ if (Changes[i].NewlinesBefore > 0) {
+ // So if we split a line previously and the tail line + this token is
+ // less then the column limit we remove the split here and just put
+ // the column start at a space past the comma
+ auto j = i - 1;
+ if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
+ Changes[j - 1].NewlinesBefore > 0) {
+ --j;
+ auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
+ if (LineLimit < Style.ColumnLimit) {
+ Changes[i].NewlinesBefore = 0;
+ Changes[i].Spaces = 1;
+ }
+ }
+ }
+ while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok == C.Tok) {
+ Changes[i].Spaces = InitialSpaces;
+ ++i;
+ HasSplit = true;
+ }
+ if (Changes[i].Tok != C.Tok)
+ --i;
+ Cells.push_back(CellDescription{i, Cell, i, HasSplit, nullptr});
+ }
+ }
+
+ return linkCells({Cells, CellCount, InitialSpaces});
+}
+
+unsigned WhitespaceManager::calculateCellWidth(unsigned Start, unsigned End,
+ bool WithSpaces) const {
+ unsigned CellWidth = 0;
+ for (auto i = Start; i < End; i++) {
+ if (Changes[i].NewlinesBefore > 0)
+ CellWidth = 0;
+ CellWidth += Changes[i].TokenLength;
+ CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
+ }
+ return CellWidth;
+}
+
+void WhitespaceManager::alignToStartOfCell(unsigned Start, unsigned End) {
+ if ((End - Start) <= 1)
+ return;
+ // If the line is broken anywhere in there make sure everything
+ // is aligned to the parent
+ for (auto i = Start + 1; i < End; i++) {
+ if (Changes[i].NewlinesBefore > 0)
+ Changes[i].Spaces = Changes[Start].Spaces;
+ }
+}
+
+WhitespaceManager::CellDescriptions
+WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
+ auto &Cells = CellDesc.Cells;
+ for (auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
+ if (CellIter->NextColumnElement == nullptr &&
+ ((CellIter + 1) != Cells.end())) {
+ for (auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
+ if (NextIter->Cell == CellIter->Cell) {
+ CellIter->NextColumnElement = &(*NextIter);
+ break;
+ }
+ }
+ }
+ }
+ return std::move(CellDesc);
+}
+
void WhitespaceManager::generateChanges() {
for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
const Change &C = Changes[i];
diff --git a/src/llvm-project/clang/lib/Format/WhitespaceManager.h b/src/llvm-project/clang/lib/Format/WhitespaceManager.h
index 1398a3a..4f8f950 100644
--- a/src/llvm-project/clang/lib/Format/WhitespaceManager.h
+++ b/src/llvm-project/clang/lib/Format/WhitespaceManager.h
@@ -18,6 +18,8 @@
#include "TokenAnnotator.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
#include <string>
#include <tuple>
@@ -173,6 +175,28 @@
};
private:
+ struct CellDescription {
+ unsigned Index = 0;
+ unsigned Cell = 0;
+ unsigned EndIndex = 0;
+ bool HasSplit = false;
+ CellDescription *NextColumnElement = nullptr;
+
+ constexpr bool operator==(const CellDescription &Other) const {
+ return Index == Other.Index && Cell == Other.Cell &&
+ EndIndex == Other.EndIndex;
+ }
+ constexpr bool operator!=(const CellDescription &Other) const {
+ return !(*this == Other);
+ }
+ };
+
+ struct CellDescriptions {
+ SmallVector<CellDescription> Cells;
+ unsigned CellCount = 0;
+ unsigned InitialSpaces = 0;
+ };
+
/// Calculate \c IsTrailingComment, \c TokenLength for the last tokens
/// or token parts in a line and \c PreviousEndOfTokenColumn and
/// \c EscapedNewlineColumn for the first tokens or token parts in a line.
@@ -207,6 +231,89 @@
/// the specified \p Column.
void alignEscapedNewlines(unsigned Start, unsigned End, unsigned Column);
+ /// Align Array Initializers over all \c Changes.
+ void alignArrayInitializers();
+
+ /// Align Array Initializers from change \p Start to change \p End at
+ /// the specified \p Column.
+ void alignArrayInitializers(unsigned Start, unsigned End);
+
+ /// Align Array Initializers being careful to right justify the columns
+ /// as described by \p CellDescs.
+ void alignArrayInitializersRightJustified(CellDescriptions &&CellDescs);
+
+ /// Align Array Initializers being careful to leftt justify the columns
+ /// as described by \p CellDescs.
+ void alignArrayInitializersLeftJustified(CellDescriptions &&CellDescs);
+
+ /// Calculate the cell width between two indexes.
+ unsigned calculateCellWidth(unsigned Start, unsigned End,
+ bool WithSpaces = false) const;
+
+ /// Get a set of fully specified CellDescriptions between \p Start and
+ /// \p End of the change list.
+ CellDescriptions getCells(unsigned Start, unsigned End);
+
+ /// Does this \p Cell contain a split element?
+ static bool isSplitCell(const CellDescription &Cell);
+
+ /// Get the width of the preceeding cells from \p Start to \p End.
+ template <typename I>
+ auto getNetWidth(const I &Start, const I &End, unsigned InitialSpaces) const {
+ auto NetWidth = InitialSpaces;
+ for (auto PrevIter = Start; PrevIter != End; ++PrevIter) {
+ // If we broke the line the initial spaces are already
+ // accounted for.
+ if (Changes[PrevIter->Index].NewlinesBefore > 0)
+ NetWidth = 0;
+ NetWidth +=
+ calculateCellWidth(PrevIter->Index, PrevIter->EndIndex, true) + 1;
+ }
+ return NetWidth;
+ }
+
+ /// Get the maximum width of a cell in a sequence of columns.
+ template <typename I>
+ unsigned getMaximumCellWidth(I CellIter, unsigned NetWidth) const {
+ unsigned CellWidth =
+ calculateCellWidth(CellIter->Index, CellIter->EndIndex, true);
+ if (Changes[CellIter->Index].NewlinesBefore == 0)
+ CellWidth += NetWidth;
+ for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
+ Next = Next->NextColumnElement) {
+ auto ThisWidth = calculateCellWidth(Next->Index, Next->EndIndex, true);
+ if (Changes[Next->Index].NewlinesBefore == 0)
+ ThisWidth += NetWidth;
+ CellWidth = std::max(CellWidth, ThisWidth);
+ }
+ return CellWidth;
+ }
+
+ /// Get The maximum width of all columns to a given cell.
+ template <typename I>
+ unsigned getMaximumNetWidth(const I &CellStart, const I &CellStop,
+ unsigned InitialSpaces,
+ unsigned CellCount) const {
+ auto MaxNetWidth = getNetWidth(CellStart, CellStop, InitialSpaces);
+ auto RowCount = 1U;
+ auto Offset = std::distance(CellStart, CellStop);
+ for (const auto *Next = CellStop->NextColumnElement; Next != nullptr;
+ Next = Next->NextColumnElement) {
+ auto Start = (CellStart + RowCount * CellCount);
+ auto End = Start + Offset;
+ MaxNetWidth =
+ std::max(MaxNetWidth, getNetWidth(Start, End, InitialSpaces));
+ ++RowCount;
+ }
+ return MaxNetWidth;
+ }
+
+ /// Align a split cell with a newline to the first element in the cell.
+ void alignToStartOfCell(unsigned Start, unsigned End);
+
+ /// Link the Cell pointers in the list of Cells.
+ static CellDescriptions linkCells(CellDescriptions &&CellDesc);
+
/// Fill \c Replaces with the replacements for all effective changes.
void generateChanges();
diff --git a/src/llvm-project/clang/lib/Frontend/ASTUnit.cpp b/src/llvm-project/clang/lib/Frontend/ASTUnit.cpp
index e7a87dc..996783a 100644
--- a/src/llvm-project/clang/lib/Frontend/ASTUnit.cpp
+++ b/src/llvm-project/clang/lib/Frontend/ASTUnit.cpp
@@ -588,7 +588,7 @@
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- Target->adjust(LangOpt);
+ Target->adjust(PP.getDiagnostics(), LangOpt);
// Initialize the preprocessor.
PP.Initialize(*Target);
@@ -807,7 +807,8 @@
if (ToLoad >= LoadASTOnly)
AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),
PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
+ PP.getBuiltinInfo(),
+ AST->getTranslationUnitKind());
DisableValidationForModuleKind disableValid =
DisableValidationForModuleKind::None;
@@ -1150,17 +1151,9 @@
Clang->setDiagnostics(&getDiagnostics());
// Create the target instance.
- Clang->setTarget(TargetInfo::CreateTargetInfo(
- Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
- if (!Clang->hasTarget())
+ if (!Clang->createTarget())
return true;
- // Inform the target of the language options.
- //
- // FIXME: We shouldn't need to do this, the target should be immutable once
- // created. This complexity should be lifted elsewhere.
- Clang->getTarget().adjust(Clang->getLangOpts());
-
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
@@ -1568,17 +1561,9 @@
Clang->setDiagnostics(&AST->getDiagnostics());
// Create the target instance.
- Clang->setTarget(TargetInfo::CreateTargetInfo(
- Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
- if (!Clang->hasTarget())
+ if (!Clang->createTarget())
return nullptr;
- // Inform the target of the language options.
- //
- // FIXME: We shouldn't need to do this, the target should be immutable once
- // created. This complexity should be lifted elsewhere.
- Clang->getTarget().adjust(Clang->getLangOpts());
-
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
@@ -2194,19 +2179,11 @@
ProcessWarningOptions(Diag, Inv.getDiagnosticOpts());
// Create the target instance.
- Clang->setTarget(TargetInfo::CreateTargetInfo(
- Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
- if (!Clang->hasTarget()) {
+ if (!Clang->createTarget()) {
Clang->setInvocation(nullptr);
return;
}
- // Inform the target of the language options.
- //
- // FIXME: We shouldn't need to do this, the target should be immutable once
- // created. This complexity should be lifted elsewhere.
- Clang->getTarget().adjust(Clang->getLangOpts());
-
assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
diff --git a/src/llvm-project/clang/lib/Frontend/CompilerInstance.cpp b/src/llvm-project/clang/lib/Frontend/CompilerInstance.cpp
index 956877d..c642af1 100644
--- a/src/llvm-project/clang/lib/Frontend/CompilerInstance.cpp
+++ b/src/llvm-project/clang/lib/Frontend/CompilerInstance.cpp
@@ -77,7 +77,7 @@
return (BuildGlobalModuleIndex ||
(TheASTReader && TheASTReader->isGlobalIndexUnavailable() &&
getFrontendOpts().GenerateGlobalModuleIndex)) &&
- !ModuleBuildFailed;
+ !DisableGeneratingGlobalModuleIndex;
}
void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
@@ -97,6 +97,62 @@
void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }
+bool CompilerInstance::createTarget() {
+ // Create the target instance.
+ setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
+ getInvocation().TargetOpts));
+ if (!hasTarget())
+ return false;
+
+ // Check whether AuxTarget exists, if not, then create TargetInfo for the
+ // other side of CUDA/OpenMP/SYCL compilation.
+ if (!getAuxTarget() &&
+ (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
+ getLangOpts().SYCLIsDevice) &&
+ !getFrontendOpts().AuxTriple.empty()) {
+ auto TO = std::make_shared<TargetOptions>();
+ TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple);
+ if (getFrontendOpts().AuxTargetCPU)
+ TO->CPU = getFrontendOpts().AuxTargetCPU.getValue();
+ if (getFrontendOpts().AuxTargetFeatures)
+ TO->FeaturesAsWritten = getFrontendOpts().AuxTargetFeatures.getValue();
+ TO->HostTriple = getTarget().getTriple().str();
+ setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
+ }
+
+ if (!getTarget().hasStrictFP() && !getLangOpts().ExpStrictFP) {
+ if (getLangOpts().getFPRoundingMode() !=
+ llvm::RoundingMode::NearestTiesToEven) {
+ getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_rounding);
+ getLangOpts().setFPRoundingMode(llvm::RoundingMode::NearestTiesToEven);
+ }
+ if (getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore) {
+ getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_exceptions);
+ getLangOpts().setFPExceptionMode(LangOptions::FPE_Ignore);
+ }
+ // FIXME: can we disable FEnvAccess?
+ }
+
+ // We should do it here because target knows nothing about
+ // language options when it's being created.
+ if (getLangOpts().OpenCL &&
+ !getTarget().validateOpenCLTarget(getLangOpts(), getDiagnostics()))
+ return false;
+
+ // Inform the target of the language options.
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ getTarget().adjust(getDiagnostics(), getLangOpts());
+
+ // Adjust target options based on codegen options.
+ getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
+
+ if (auto *Aux = getAuxTarget())
+ getTarget().setAuxTarget(Aux);
+
+ return true;
+}
+
llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const {
return getFileManager().getVirtualFileSystem();
}
@@ -229,7 +285,7 @@
// Create the output stream.
auto FileOS = std::make_unique<llvm::raw_fd_ostream>(
DiagOpts->DiagnosticLogFile, EC,
- llvm::sys::fs::OF_Append | llvm::sys::fs::OF_Text);
+ llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
<< DiagOpts->DiagnosticLogFile << EC.message();
@@ -401,7 +457,7 @@
getSourceManager(), *HeaderInfo, *this,
/*IdentifierInfoLookup=*/nullptr,
/*OwnsHeaderSearch=*/true, TUKind);
- getTarget().adjust(getLangOpts());
+ getTarget().adjust(getDiagnostics(), getLangOpts());
PP->Initialize(getTarget(), getAuxTarget());
if (PPOpts.DetailedRecord)
@@ -495,7 +551,7 @@
Preprocessor &PP = getPreprocessor();
auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
PP.getIdentifierTable(), PP.getSelectorTable(),
- PP.getBuiltinInfo());
+ PP.getBuiltinInfo(), PP.TUKind);
Context->InitBuiltinTypes(getTarget(), getAuxTarget());
setASTContext(Context);
}
@@ -647,31 +703,37 @@
// Output Files
void CompilerInstance::clearOutputFiles(bool EraseFiles) {
+ // Ignore errors that occur when trying to discard the temp file.
for (OutputFile &OF : OutputFiles) {
if (EraseFiles) {
- if (!OF.TempFilename.empty()) {
- llvm::sys::fs::remove(OF.TempFilename);
- continue;
- }
+ if (OF.File)
+ consumeError(OF.File->discard());
if (!OF.Filename.empty())
llvm::sys::fs::remove(OF.Filename);
continue;
}
- if (OF.TempFilename.empty())
+ if (!OF.File)
continue;
+ if (OF.File->TmpName.empty()) {
+ consumeError(OF.File->discard());
+ continue;
+ }
+
// If '-working-directory' was passed, the output filename should be
// relative to that.
SmallString<128> NewOutFile(OF.Filename);
FileMgr->FixupRelativePath(NewOutFile);
- std::error_code EC = llvm::sys::fs::rename(OF.TempFilename, NewOutFile);
- if (!EC)
- continue;
- getDiagnostics().Report(diag::err_unable_to_rename_temp)
- << OF.TempFilename << OF.Filename << EC.message();
- llvm::sys::fs::remove(OF.TempFilename);
+ llvm::Error E = OF.File->keep(NewOutFile);
+ if (!E)
+ continue;
+
+ getDiagnostics().Report(diag::err_unable_to_rename_temp)
+ << OF.File->TmpName << OF.Filename << std::move(E);
+
+ llvm::sys::fs::remove(OF.File->TmpName);
}
OutputFiles.clear();
if (DeleteBuiltModules) {
@@ -681,11 +743,9 @@
}
}
-std::unique_ptr<raw_pwrite_stream>
-CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile,
- StringRef Extension,
- bool RemoveFileOnSignal,
- bool CreateMissingDirectories) {
+std::unique_ptr<raw_pwrite_stream> CompilerInstance::createDefaultOutputFile(
+ bool Binary, StringRef InFile, StringRef Extension, bool RemoveFileOnSignal,
+ bool CreateMissingDirectories, bool ForceUseTemporary) {
StringRef OutputPath = getFrontendOpts().OutputFile;
Optional<SmallString<128>> PathStorage;
if (OutputPath.empty()) {
@@ -698,9 +758,8 @@
}
}
- // Force a temporary file if RemoveFileOnSignal was disabled.
return createOutputFile(OutputPath, Binary, RemoveFileOnSignal,
- getFrontendOpts().UseTemporary || !RemoveFileOnSignal,
+ getFrontendOpts().UseTemporary || ForceUseTemporary,
CreateMissingDirectories);
}
@@ -753,7 +812,7 @@
}
}
- std::string TempFile;
+ Optional<llvm::sys::fs::TempFile> Temp;
if (UseTemporary) {
// Create a temporary file.
// Insert -%%%%%%%% before the extension (if any), and because some tools
@@ -765,22 +824,34 @@
TempPath += "-%%%%%%%%";
TempPath += OutputExtension;
TempPath += ".tmp";
- int fd;
- std::error_code EC =
- llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);
+ Expected<llvm::sys::fs::TempFile> ExpectedFile =
+ llvm::sys::fs::TempFile::create(
+ TempPath, llvm::sys::fs::all_read | llvm::sys::fs::all_write,
+ Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text);
- if (CreateMissingDirectories &&
- EC == llvm::errc::no_such_file_or_directory) {
- StringRef Parent = llvm::sys::path::parent_path(OutputPath);
- EC = llvm::sys::fs::create_directories(Parent);
- if (!EC) {
- EC = llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);
- }
- }
+ llvm::Error E = handleErrors(
+ ExpectedFile.takeError(), [&](const llvm::ECError &E) -> llvm::Error {
+ std::error_code EC = E.convertToErrorCode();
+ if (CreateMissingDirectories &&
+ EC == llvm::errc::no_such_file_or_directory) {
+ StringRef Parent = llvm::sys::path::parent_path(OutputPath);
+ EC = llvm::sys::fs::create_directories(Parent);
+ if (!EC) {
+ ExpectedFile = llvm::sys::fs::TempFile::create(TempPath);
+ if (!ExpectedFile)
+ return llvm::errorCodeToError(
+ llvm::errc::no_such_file_or_directory);
+ }
+ }
+ return llvm::errorCodeToError(EC);
+ });
- if (!EC) {
- OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
- OSFile = TempFile = std::string(TempPath.str());
+ if (E) {
+ consumeError(std::move(E));
+ } else {
+ Temp = std::move(ExpectedFile.get());
+ OS.reset(new llvm::raw_fd_ostream(Temp->FD, /*shouldClose=*/false));
+ OSFile = Temp->TmpName;
}
// If we failed to create the temporary, fallback to writing to the file
// directly. This handles the corner case where we cannot write to the
@@ -792,19 +863,15 @@
std::error_code EC;
OS.reset(new llvm::raw_fd_ostream(
*OSFile, EC,
- (Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text)));
+ (Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_TextWithCRLF)));
if (EC)
return llvm::errorCodeToError(EC);
}
- // Make sure the out stream file gets removed if we crash.
- if (RemoveFileOnSignal)
- llvm::sys::RemoveFileOnSignal(*OSFile);
-
// Add the output file -- but don't try to remove "-", since this means we are
// using stdin.
OutputFiles.emplace_back(((OutputPath != "-") ? OutputPath : "").str(),
- std::move(TempFile));
+ std::move(Temp));
if (!Binary || OS->supportsSeeking())
return std::move(OS);
@@ -878,51 +945,9 @@
if (!Act.PrepareToExecute(*this))
return false;
- // Create the target instance.
- setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
- getInvocation().TargetOpts));
- if (!hasTarget())
+ if (!createTarget())
return false;
- // Create TargetInfo for the other side of CUDA/OpenMP/SYCL compilation.
- if ((getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
- getLangOpts().SYCLIsDevice) &&
- !getFrontendOpts().AuxTriple.empty()) {
- auto TO = std::make_shared<TargetOptions>();
- TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple);
- if (getFrontendOpts().AuxTargetCPU)
- TO->CPU = getFrontendOpts().AuxTargetCPU.getValue();
- if (getFrontendOpts().AuxTargetFeatures)
- TO->FeaturesAsWritten = getFrontendOpts().AuxTargetFeatures.getValue();
- TO->HostTriple = getTarget().getTriple().str();
- setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
- }
-
- if (!getTarget().hasStrictFP() && !getLangOpts().ExpStrictFP) {
- if (getLangOpts().getFPRoundingMode() !=
- llvm::RoundingMode::NearestTiesToEven) {
- getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_rounding);
- getLangOpts().setFPRoundingMode(llvm::RoundingMode::NearestTiesToEven);
- }
- if (getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore) {
- getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_exceptions);
- getLangOpts().setFPExceptionMode(LangOptions::FPE_Ignore);
- }
- // FIXME: can we disable FEnvAccess?
- }
-
- // Inform the target of the language options.
- //
- // FIXME: We shouldn't need to do this, the target should be immutable once
- // created. This complexity should be lifted elsewhere.
- getTarget().adjust(getLangOpts());
-
- // Adjust target options based on codegen options.
- getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
-
- if (auto *Aux = getAuxTarget())
- getTarget().setAuxTarget(Aux);
-
// rewriter project will change target built-in bool type from its default.
if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
getTarget().noSignedCharForObjCBool();
@@ -992,7 +1017,7 @@
if (!StatsFile.empty()) {
std::error_code EC;
auto StatS = std::make_unique<llvm::raw_fd_ostream>(
- StatsFile, EC, llvm::sys::fs::OF_Text);
+ StatsFile, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file)
<< StatsFile << EC.message();
@@ -1029,6 +1054,15 @@
[](CompilerInstance &) {}) {
llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
+ // Never compile a module that's already finalized - this would cause the
+ // existing module to be freed, causing crashes if it is later referenced
+ if (ImportingInstance.getModuleCache().isPCMFinal(ModuleFileName)) {
+ ImportingInstance.getDiagnostics().Report(
+ ImportLoc, diag::err_module_rebuild_finalized)
+ << ModuleName;
+ return false;
+ }
+
// Construct a compiler invocation for creating this module.
auto Invocation =
std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation());
@@ -1144,7 +1178,10 @@
// module generation thread crashed.
Instance.clearOutputFiles(/*EraseFiles=*/true);
- return !Instance.getDiagnostics().hasErrorOccurred();
+ // If \p AllowPCMWithCompilerErrors is set return 'success' even if errors
+ // occurred.
+ return !Instance.getDiagnostics().hasErrorOccurred() ||
+ Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
}
static const FileEntry *getPublicModuleMap(const FileEntry *File,
@@ -1664,9 +1701,7 @@
// We can't find a module, error out here.
getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
<< ModuleName << SourceRange(ImportLoc, ModuleNameLoc);
- ModuleBuildFailed = true;
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
if (ModuleFilename.empty()) {
if (M && M->HasIncompatibleModuleFile) {
@@ -1677,9 +1712,7 @@
getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
<< ModuleName;
- ModuleBuildFailed = true;
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
// Create an ASTReader on demand.
@@ -1697,7 +1730,8 @@
// Try to load the module file. If we are not trying to load from the
// module cache, we don't know how to rebuild modules.
unsigned ARRFlags = Source == MS_ModuleCache
- ? ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing
+ ? ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing |
+ ASTReader::ARR_TreatModuleWithErrorsAsOutOfDate
: Source == MS_PrebuiltModulePath
? 0
: ASTReader::ARR_ConfigurationMismatch;
@@ -1724,7 +1758,6 @@
if (*ModuleFile == M->getASTFile())
return M;
- ModuleBuildFailed = true;
getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt)
<< ModuleName;
return ModuleLoadResult();
@@ -1746,14 +1779,12 @@
LLVM_FALLTHROUGH;
case ASTReader::VersionMismatch:
case ASTReader::HadErrors:
- // FIXME: Should this set ModuleBuildFailed = true?
ModuleLoader::HadFatalFailure = true;
// FIXME: The ASTReader will already have complained, but can we shoehorn
// that diagnostic information into a more useful form?
return ModuleLoadResult();
case ASTReader::Failure:
- // FIXME: Should this set ModuleBuildFailed = true?
ModuleLoader::HadFatalFailure = true;
return ModuleLoadResult();
}
@@ -1763,7 +1794,6 @@
// We don't know the desired configuration for this module and don't
// necessarily even have a module map. Since ReadAST already produces
// diagnostics for these two cases, we simply error out here.
- ModuleBuildFailed = true;
return ModuleLoadResult();
}
@@ -1788,9 +1818,7 @@
getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
<< ModuleName << CyclePath;
- // FIXME: Should this set ModuleBuildFailed = true?
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
// Check whether we have already attempted to build this module (but
@@ -1799,9 +1827,7 @@
getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) {
getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built)
<< ModuleName << SourceRange(ImportLoc, ModuleNameLoc);
- ModuleBuildFailed = true;
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
// Try to compile and then read the AST.
@@ -1811,9 +1837,7 @@
"undiagnosed error in compileModuleAndReadAST");
if (getPreprocessorOpts().FailedModules)
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
- ModuleBuildFailed = true;
- // FIXME: Why is this not cached?
- return ModuleLoadResult::OtherUncachedFailure;
+ return nullptr;
}
// Okay, we've rebuilt and now loaded the module.
@@ -1856,22 +1880,19 @@
//if (Module == nullptr) {
// getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
// << ModuleName;
- // ModuleBuildFailed = true;
+ // DisableGeneratingGlobalModuleIndex = true;
// return ModuleLoadResult();
//}
MM.cacheModuleLoad(*Path[0].first, Module);
} else {
ModuleLoadResult Result = findOrCompileModuleAndReadAST(
ModuleName, ImportLoc, ModuleNameLoc, IsInclusionDirective);
- // FIXME: Can we pull 'ModuleBuildFailed = true' out of the return
- // sequences for findOrCompileModuleAndReadAST and do it here (as long as
- // the result is not a config mismatch)? See FIXMEs there.
if (!Result.isNormal())
return Result;
+ if (!Result)
+ DisableGeneratingGlobalModuleIndex = true;
Module = Result;
MM.cacheModuleLoad(*Path[0].first, Module);
- if (!Module)
- return Module;
}
// If we never found the module, fail. Otherwise, verify the module and link
diff --git a/src/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp b/src/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp
index 5c5cf46..7025028 100644
--- a/src/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/src/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp
@@ -38,6 +38,7 @@
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/MigratorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/PreprocessorOptions.h"
@@ -48,10 +49,12 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/CachedHashString.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -106,20 +109,40 @@
// Initialization.
//===----------------------------------------------------------------------===//
-CompilerInvocationBase::CompilerInvocationBase()
+CompilerInvocationRefBase::CompilerInvocationRefBase()
: LangOpts(new LangOptions()), TargetOpts(new TargetOptions()),
DiagnosticOpts(new DiagnosticOptions()),
HeaderSearchOpts(new HeaderSearchOptions()),
- PreprocessorOpts(new PreprocessorOptions()) {}
+ PreprocessorOpts(new PreprocessorOptions()),
+ AnalyzerOpts(new AnalyzerOptions()) {}
-CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
+CompilerInvocationRefBase::CompilerInvocationRefBase(
+ const CompilerInvocationRefBase &X)
: LangOpts(new LangOptions(*X.getLangOpts())),
TargetOpts(new TargetOptions(X.getTargetOpts())),
DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())),
HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
- PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
+ PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())),
+ AnalyzerOpts(new AnalyzerOptions(*X.getAnalyzerOpts())) {}
-CompilerInvocationBase::~CompilerInvocationBase() = default;
+CompilerInvocationRefBase::CompilerInvocationRefBase(
+ CompilerInvocationRefBase &&X) = default;
+
+CompilerInvocationRefBase &
+CompilerInvocationRefBase::operator=(CompilerInvocationRefBase X) {
+ LangOpts.swap(X.LangOpts);
+ TargetOpts.swap(X.TargetOpts);
+ DiagnosticOpts.swap(X.DiagnosticOpts);
+ HeaderSearchOpts.swap(X.HeaderSearchOpts);
+ PreprocessorOpts.swap(X.PreprocessorOpts);
+ AnalyzerOpts.swap(X.AnalyzerOpts);
+ return *this;
+}
+
+CompilerInvocationRefBase &
+CompilerInvocationRefBase::operator=(CompilerInvocationRefBase &&X) = default;
+
+CompilerInvocationRefBase::~CompilerInvocationRefBase() = default;
//===----------------------------------------------------------------------===//
// Normalizers
@@ -129,9 +152,10 @@
#include "clang/Driver/Options.inc"
#undef SIMPLE_ENUM_VALUE_TABLE
-static llvm::Optional<bool>
-normalizeSimpleFlag(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args,
- DiagnosticsEngine &Diags, bool &Success) {
+static llvm::Optional<bool> normalizeSimpleFlag(OptSpecifier Opt,
+ unsigned TableIndex,
+ const ArgList &Args,
+ DiagnosticsEngine &Diags) {
if (Args.hasArg(Opt))
return true;
return None;
@@ -139,8 +163,7 @@
static Optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned,
const ArgList &Args,
- DiagnosticsEngine &,
- bool &Success) {
+ DiagnosticsEngine &) {
if (Args.hasArg(Opt))
return false;
return None;
@@ -166,7 +189,7 @@
std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false>
static auto makeFlagToValueNormalizer(T Value) {
return [Value](OptSpecifier Opt, unsigned, const ArgList &Args,
- DiagnosticsEngine &, bool &Success) -> Optional<T> {
+ DiagnosticsEngine &) -> Optional<T> {
if (Args.hasArg(Opt))
return Value;
return None;
@@ -182,8 +205,8 @@
static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,
OptSpecifier OtherOpt) {
return [Value, OtherValue, OtherOpt](OptSpecifier Opt, unsigned,
- const ArgList &Args, DiagnosticsEngine &,
- bool &Success) -> Optional<bool> {
+ const ArgList &Args,
+ DiagnosticsEngine &) -> Optional<bool> {
if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) {
return A->getOption().matches(Opt) ? Value : OtherValue;
}
@@ -204,14 +227,16 @@
const char *Spelling,
CompilerInvocation::StringAllocator SA,
Option::OptionClass OptClass, unsigned,
- Twine Value) {
+ const Twine &Value) {
switch (OptClass) {
case Option::SeparateClass:
case Option::JoinedOrSeparateClass:
+ case Option::JoinedAndSeparateClass:
Args.push_back(Spelling);
Args.push_back(SA(Value));
break;
case Option::JoinedClass:
+ case Option::CommaJoinedClass:
Args.push_back(SA(Twine(Spelling) + Value));
break;
default:
@@ -246,9 +271,10 @@
return None;
}
-static llvm::Optional<unsigned>
-normalizeSimpleEnum(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args,
- DiagnosticsEngine &Diags, bool &Success) {
+static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
+ unsigned TableIndex,
+ const ArgList &Args,
+ DiagnosticsEngine &Diags) {
assert(TableIndex < SimpleEnumValueTablesSize);
const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
@@ -260,7 +286,6 @@
if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue))
return MaybeEnumVal->Value;
- Success = false;
Diags.Report(diag::err_drv_invalid_value)
<< Arg->getAsString(Args) << ArgValue;
return None;
@@ -294,8 +319,7 @@
static Optional<std::string> normalizeString(OptSpecifier Opt, int TableIndex,
const ArgList &Args,
- DiagnosticsEngine &Diags,
- bool &Success) {
+ DiagnosticsEngine &Diags) {
auto *Arg = Args.getLastArg(Opt);
if (!Arg)
return None;
@@ -303,15 +327,14 @@
}
template <typename IntTy>
-static Optional<IntTy>
-normalizeStringIntegral(OptSpecifier Opt, int, const ArgList &Args,
- DiagnosticsEngine &Diags, bool &Success) {
+static Optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,
+ const ArgList &Args,
+ DiagnosticsEngine &Diags) {
auto *Arg = Args.getLastArg(Opt);
if (!Arg)
return None;
IntTy Res;
if (StringRef(Arg->getValue()).getAsInteger(0, Res)) {
- Success = false;
Diags.Report(diag::err_drv_invalid_int_value)
<< Arg->getAsString(Args) << Arg->getValue();
return None;
@@ -321,7 +344,7 @@
static Optional<std::vector<std::string>>
normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args,
- DiagnosticsEngine &, bool &Success) {
+ DiagnosticsEngine &) {
return Args.getAllArgValues(Opt);
}
@@ -359,8 +382,7 @@
static Optional<std::string> normalizeTriple(OptSpecifier Opt, int TableIndex,
const ArgList &Args,
- DiagnosticsEngine &Diags,
- bool &Success) {
+ DiagnosticsEngine &Diags) {
auto *Arg = Args.getLastArg(Opt);
if (!Arg)
return None;
@@ -382,29 +404,46 @@
template <typename T, typename U, U Value>
static T extractMaskValue(T KeyPath) {
- return KeyPath & Value;
+ return ((KeyPath & Value) == Value) ? static_cast<T>(Value) : T();
}
-#define PARSE_OPTION_WITH_MARSHALLING(ARGS, DIAGS, SUCCESS, ID, FLAGS, PARAM, \
- SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
- IMPLIED_CHECK, IMPLIED_VALUE, \
- NORMALIZER, MERGER, TABLE_INDEX) \
+#define PARSE_OPTION_WITH_MARSHALLING( \
+ ARGS, DIAGS, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX) \
if ((FLAGS)&options::CC1Option) { \
KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \
if (IMPLIED_CHECK) \
KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \
if (SHOULD_PARSE) \
- if (auto MaybeValue = \
- NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS, SUCCESS)) \
+ if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS)) \
KEYPATH = \
MERGER(KEYPATH, static_cast<decltype(KEYPATH)>(*MaybeValue)); \
}
+// Capture the extracted value as a lambda argument to avoid potential issues
+// with lifetime extension of the reference.
+#define GENERATE_OPTION_WITH_MARSHALLING( \
+ ARGS, STRING_ALLOCATOR, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, \
+ TABLE_INDEX) \
+ if ((FLAGS)&options::CC1Option) { \
+ [&](const auto &Extracted) { \
+ if (ALWAYS_EMIT || \
+ (Extracted != \
+ static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE) \
+ : (DEFAULT_VALUE)))) \
+ DENORMALIZER(ARGS, SPELLING, STRING_ALLOCATOR, Option::KIND##Class, \
+ TABLE_INDEX, Extracted); \
+ }(EXTRACTOR(KEYPATH)); \
+ }
+
static const StringRef GetInputKindName(InputKind IK);
-static void FixupInvocation(CompilerInvocation &Invocation,
- DiagnosticsEngine &Diags, const InputArgList &Args,
+static bool FixupInvocation(CompilerInvocation &Invocation,
+ DiagnosticsEngine &Diags, const ArgList &Args,
InputKind IK) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
LangOptions &LangOpts = *Invocation.getLangOpts();
CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts();
TargetOptions &TargetOpts = Invocation.getTargetOpts();
@@ -414,7 +453,7 @@
CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents;
CodeGenOpts.DisableFree = FrontendOpts.DisableFree;
FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex;
-
+ LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage();
LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;
LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;
LangOpts.CurrentModule = LangOpts.ModuleName;
@@ -424,7 +463,8 @@
CodeGenOpts.CodeModel = TargetOpts.CodeModel;
- if (LangOpts.getExceptionHandling() != llvm::ExceptionHandling::None &&
+ if (LangOpts.getExceptionHandling() !=
+ LangOptions::ExceptionHandlingKind::None &&
T.isWindowsMSVCEnvironment())
Diags.Report(diag::err_fe_invalid_exception_model)
<< static_cast<unsigned>(LangOpts.getExceptionHandling()) << T.str();
@@ -432,6 +472,9 @@
if (LangOpts.AppleKext && !LangOpts.CPlusPlus)
Diags.Report(diag::warn_c_kext);
+ if (Args.hasArg(OPT_fconcepts_ts))
+ Diags.Report(diag::warn_fe_concepts_ts_flag);
+
if (LangOpts.NewAlignOverride &&
!llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) {
Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
@@ -440,6 +483,11 @@
LangOpts.NewAlignOverride = 0;
}
+ // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.
+ if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)
+ Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"
+ << "-fsycl-is-host";
+
if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus)
Diags.Report(diag::err_drv_argument_not_allowed_with)
<< "-fgnu89-inline" << GetInputKindName(IK);
@@ -478,6 +526,8 @@
Diags.Report(diag::err_drv_argument_only_allowed_with)
<< Args.getLastArg(OPT_fprofile_remapping_file_EQ)->getAsString(Args)
<< "-fno-legacy-pass-manager";
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
//===----------------------------------------------------------------------===//
@@ -487,7 +537,9 @@
static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
unsigned DefaultOpt = llvm::CodeGenOpt::None;
- if (IK.getLanguage() == Language::OpenCL && !Args.hasArg(OPT_cl_opt_disable))
+ if ((IK.getLanguage() == Language::OpenCL ||
+ IK.getLanguage() == Language::OpenCLCXX) &&
+ !Args.hasArg(OPT_cl_opt_disable))
DefaultOpt = llvm::CodeGenOpt::Default;
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
@@ -528,9 +580,163 @@
return 0;
}
-static std::string GetOptName(llvm::opt::OptSpecifier OptSpecifier) {
- static const OptTable &OptTable = getDriverOptTable();
- return OptTable.getOption(OptSpecifier).getPrefixedName();
+static void GenerateArg(SmallVectorImpl<const char *> &Args,
+ llvm::opt::OptSpecifier OptSpecifier,
+ CompilerInvocation::StringAllocator SA) {
+ Option Opt = getDriverOptTable().getOption(OptSpecifier);
+ denormalizeSimpleFlag(Args, SA(Opt.getPrefix() + Opt.getName()), SA,
+ Option::OptionClass::FlagClass, 0);
+}
+
+static void GenerateArg(SmallVectorImpl<const char *> &Args,
+ llvm::opt::OptSpecifier OptSpecifier,
+ const Twine &Value,
+ CompilerInvocation::StringAllocator SA) {
+ Option Opt = getDriverOptTable().getOption(OptSpecifier);
+ denormalizeString(Args, SA(Opt.getPrefix() + Opt.getName()), SA,
+ Opt.getKind(), 0, Value);
+}
+
+// Parse command line arguments into CompilerInvocation.
+using ParseFn =
+ llvm::function_ref<bool(CompilerInvocation &, ArrayRef<const char *>,
+ DiagnosticsEngine &, const char *)>;
+
+// Generate command line arguments from CompilerInvocation.
+using GenerateFn = llvm::function_ref<void(
+ CompilerInvocation &, SmallVectorImpl<const char *> &,
+ CompilerInvocation::StringAllocator)>;
+
+// May perform round-trip of command line arguments. By default, the round-trip
+// is enabled if CLANG_ROUND_TRIP_CC1_ARGS was defined during build. This can be
+// overwritten at run-time via the "-round-trip-args" and "-no-round-trip-args"
+// command line flags.
+// During round-trip, the command line arguments are parsed into a dummy
+// instance of CompilerInvocation which is used to generate the command line
+// arguments again. The real CompilerInvocation instance is then created by
+// parsing the generated arguments, not the original ones.
+static bool RoundTrip(ParseFn Parse, GenerateFn Generate,
+ CompilerInvocation &RealInvocation,
+ CompilerInvocation &DummyInvocation,
+ ArrayRef<const char *> CommandLineArgs,
+ DiagnosticsEngine &Diags, const char *Argv0) {
+ // FIXME: Switch to '#ifndef NDEBUG' when possible.
+#ifdef CLANG_ROUND_TRIP_CC1_ARGS
+ bool DoRoundTripDefault = true;
+#else
+ bool DoRoundTripDefault = false;
+#endif
+
+ bool DoRoundTrip = DoRoundTripDefault;
+ for (const auto *Arg : CommandLineArgs) {
+ if (Arg == StringRef("-round-trip-args"))
+ DoRoundTrip = true;
+ if (Arg == StringRef("-no-round-trip-args"))
+ DoRoundTrip = false;
+ }
+
+ // If round-trip was not requested, simply run the parser with the real
+ // invocation diagnostics.
+ if (!DoRoundTrip)
+ return Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
+
+ // Serializes quoted (and potentially escaped) arguments.
+ auto SerializeArgs = [](ArrayRef<const char *> Args) {
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ for (const char *Arg : Args) {
+ llvm::sys::printArg(OS, Arg, /*Quote=*/true);
+ OS << ' ';
+ }
+ OS.flush();
+ return Buffer;
+ };
+
+ // Setup a dummy DiagnosticsEngine.
+ DiagnosticsEngine DummyDiags(new DiagnosticIDs(), new DiagnosticOptions());
+ DummyDiags.setClient(new TextDiagnosticBuffer());
+
+ // Run the first parse on the original arguments with the dummy invocation and
+ // diagnostics.
+ if (!Parse(DummyInvocation, CommandLineArgs, DummyDiags, Argv0) ||
+ DummyDiags.getNumWarnings() != 0) {
+ // If the first parse did not succeed, it must be user mistake (invalid
+ // command line arguments). We won't be able to generate arguments that
+ // would reproduce the same result. Let's fail again with the real
+ // invocation and diagnostics, so all side-effects of parsing are visible.
+ unsigned NumWarningsBefore = Diags.getNumWarnings();
+ auto Success = Parse(RealInvocation, CommandLineArgs, Diags, Argv0);
+ if (!Success || Diags.getNumWarnings() != NumWarningsBefore)
+ return Success;
+
+ // Parse with original options and diagnostics succeeded even though it
+ // shouldn't have. Something is off.
+ Diags.Report(diag::err_cc1_round_trip_fail_then_ok);
+ Diags.Report(diag::note_cc1_round_trip_original)
+ << SerializeArgs(CommandLineArgs);
+ return false;
+ }
+
+ // Setup string allocator.
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver StringPool(Alloc);
+ auto SA = [&StringPool](const Twine &Arg) {
+ return StringPool.save(Arg).data();
+ };
+
+ // Generate arguments from the dummy invocation. If Generate is the
+ // inverse of Parse, the newly generated arguments must have the same
+ // semantics as the original.
+ SmallVector<const char *> GeneratedArgs1;
+ Generate(DummyInvocation, GeneratedArgs1, SA);
+
+ // Run the second parse, now on the generated arguments, and with the real
+ // invocation and diagnostics. The result is what we will end up using for the
+ // rest of compilation, so if Generate is not inverse of Parse, something down
+ // the line will break.
+ bool Success2 = Parse(RealInvocation, GeneratedArgs1, Diags, Argv0);
+
+ // The first parse on original arguments succeeded, but second parse of
+ // generated arguments failed. Something must be wrong with the generator.
+ if (!Success2) {
+ Diags.Report(diag::err_cc1_round_trip_ok_then_fail);
+ Diags.Report(diag::note_cc1_round_trip_generated)
+ << 1 << SerializeArgs(GeneratedArgs1);
+ return false;
+ }
+
+ // Generate arguments again, this time from the options we will end up using
+ // for the rest of the compilation.
+ SmallVector<const char *> GeneratedArgs2;
+ Generate(RealInvocation, GeneratedArgs2, SA);
+
+ // Compares two lists of generated arguments.
+ auto Equal = [](const ArrayRef<const char *> A,
+ const ArrayRef<const char *> B) {
+ return std::equal(A.begin(), A.end(), B.begin(), B.end(),
+ [](const char *AElem, const char *BElem) {
+ return StringRef(AElem) == StringRef(BElem);
+ });
+ };
+
+ // If we generated different arguments from what we assume are two
+ // semantically equivalent CompilerInvocations, the Generate function may
+ // be non-deterministic.
+ if (!Equal(GeneratedArgs1, GeneratedArgs2)) {
+ Diags.Report(diag::err_cc1_round_trip_mismatch);
+ Diags.Report(diag::note_cc1_round_trip_generated)
+ << 1 << SerializeArgs(GeneratedArgs1);
+ Diags.Report(diag::note_cc1_round_trip_generated)
+ << 2 << SerializeArgs(GeneratedArgs2);
+ return false;
+ }
+
+ Diags.Report(diag::remark_cc1_round_trip_generated)
+ << 1 << SerializeArgs(GeneratedArgs1);
+ Diags.Report(diag::remark_cc1_round_trip_generated)
+ << 2 << SerializeArgs(GeneratedArgs2);
+
+ return Success2;
}
static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
@@ -539,17 +745,17 @@
for (auto *A : Args.filtered(Group)) {
if (A->getOption().getKind() == Option::FlagClass) {
// The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add
- // its name (minus the "W" or "R" at the beginning) to the warning list.
+ // its name (minus the "W" or "R" at the beginning) to the diagnostics.
Diagnostics.push_back(
std::string(A->getOption().getName().drop_front(1)));
} else if (A->getOption().matches(GroupWithValue)) {
- // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic group.
+ // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic
+ // group. Add only the group name to the diagnostics.
Diagnostics.push_back(
std::string(A->getOption().getName().drop_front(1).rtrim("=-")));
} else {
// Otherwise, add its value (for OPT_W_Joined and similar).
- for (const auto *Arg : A->getValues())
- Diagnostics.emplace_back(Arg);
+ Diagnostics.push_back(A->getValue());
}
}
}
@@ -561,21 +767,128 @@
static void getAllNoBuiltinFuncValues(ArgList &Args,
std::vector<std::string> &Funcs) {
- SmallVector<const char *, 8> Values;
- for (const auto &Arg : Args) {
- const Option &O = Arg->getOption();
- if (O.matches(options::OPT_fno_builtin_)) {
- const char *FuncName = Arg->getValue();
- if (Builtin::Context::isBuiltinFunc(FuncName))
- Values.push_back(FuncName);
+ std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);
+ auto BuiltinEnd = llvm::partition(Values, [](const std::string FuncName) {
+ return Builtin::Context::isBuiltinFunc(FuncName);
+ });
+ Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);
+}
+
+static void GenerateAnalyzerArgs(AnalyzerOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ const AnalyzerOptions *AnalyzerOpts = &Opts;
+
+#define ANALYZER_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef ANALYZER_OPTION_WITH_MARSHALLING
+
+ if (Opts.AnalysisStoreOpt != RegionStoreModel) {
+ switch (Opts.AnalysisStoreOpt) {
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: \
+ GenerateArg(Args, OPT_analyzer_store, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis store.");
}
}
- Funcs.insert(Funcs.end(), Values.begin(), Values.end());
+
+ if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
+ switch (Opts.AnalysisConstraintsOpt) {
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
+ case NAME##Model: \
+ GenerateArg(Args, OPT_analyzer_constraints, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis constraint.");
+ }
+ }
+
+ if (Opts.AnalysisDiagOpt != PD_HTML) {
+ switch (Opts.AnalysisDiagOpt) {
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \
+ case PD_##NAME: \
+ GenerateArg(Args, OPT_analyzer_output, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis diagnostic client.");
+ }
+ }
+
+ if (Opts.AnalysisPurgeOpt != PurgeStmt) {
+ switch (Opts.AnalysisPurgeOpt) {
+#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \
+ case NAME: \
+ GenerateArg(Args, OPT_analyzer_purge, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis purge mode.");
+ }
+ }
+
+ if (Opts.InliningMode != NoRedundancy) {
+ switch (Opts.InliningMode) {
+#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \
+ case NAME: \
+ GenerateArg(Args, OPT_analyzer_inlining_mode, CMDFLAG, SA); \
+ break;
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+ default:
+ llvm_unreachable("Tried to generate unknown analysis inlining mode.");
+ }
+ }
+
+ for (const auto &CP : Opts.CheckersAndPackages) {
+ OptSpecifier Opt =
+ CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker;
+ GenerateArg(Args, Opt, CP.first, SA);
+ }
+
+ AnalyzerOptions ConfigOpts;
+ parseAnalyzerConfigs(ConfigOpts, nullptr);
+
+ for (const auto &C : Opts.Config) {
+ // Don't generate anything that came from parseAnalyzerConfigs. It would be
+ // redundant and may not be valid on the command line.
+ auto Entry = ConfigOpts.Config.find(C.getKey());
+ if (Entry != ConfigOpts.Config.end() && Entry->getValue() == C.getValue())
+ continue;
+
+ GenerateArg(Args, OPT_analyzer_config, C.getKey() + "=" + C.getValue(), SA);
+ }
+
+ // Nothing to generate for FullCompilerInvocation.
}
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
- bool Success = true;
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ AnalyzerOptions *AnalyzerOpts = &Opts;
+
+#define ANALYZER_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef ANALYZER_OPTION_WITH_MARSHALLING
+
if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
StringRef Name = A->getValue();
AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
@@ -586,7 +899,6 @@
if (Value == NumStores) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << Name;
- Success = false;
} else {
Opts.AnalysisStoreOpt = Value;
}
@@ -602,7 +914,6 @@
if (Value == NumConstraints) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << Name;
- Success = false;
} else {
Opts.AnalysisConstraintsOpt = Value;
}
@@ -618,7 +929,6 @@
if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << Name;
- Success = false;
} else {
Opts.AnalysisDiagOpt = Value;
}
@@ -634,7 +944,6 @@
if (Value == NumPurgeModes) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << Name;
- Success = false;
} else {
Opts.AnalysisPurgeOpt = Value;
}
@@ -650,7 +959,6 @@
if (Value == NumInliningModes) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << Name;
- Success = false;
} else {
Opts.InliningMode = Value;
}
@@ -685,14 +993,12 @@
if (val.empty()) {
Diags.Report(SourceLocation(),
diag::err_analyzer_config_no_value) << configVal;
- Success = false;
break;
}
if (val.find('=') != StringRef::npos) {
Diags.Report(SourceLocation(),
diag::err_analyzer_config_multiple_values)
<< configVal;
- Success = false;
break;
}
@@ -722,7 +1028,7 @@
}
os.flush();
- return Success;
+ return Diags.getNumErrors() == NumErrorsBefore;
}
static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,
@@ -843,20 +1149,69 @@
<< "a filename";
}
-/// Create a new Regex instance out of the string value in \p RpassArg.
-/// It returns a pointer to the newly generated Regex instance.
-static std::shared_ptr<llvm::Regex>
-GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args,
- Arg *RpassArg) {
- StringRef Val = RpassArg->getValue();
- std::string RegexError;
- std::shared_ptr<llvm::Regex> Pattern = std::make_shared<llvm::Regex>(Val);
- if (!Pattern->isValid(RegexError)) {
- Diags.Report(diag::err_drv_optimization_remark_pattern)
- << RegexError << RpassArg->getAsString(Args);
- Pattern.reset();
+/// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.
+static void
+GenerateOptimizationRemark(SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA,
+ OptSpecifier OptEQ, StringRef Name,
+ const CodeGenOptions::OptRemark &Remark) {
+ if (Remark.hasValidPattern()) {
+ GenerateArg(Args, OptEQ, Remark.Pattern, SA);
+ } else if (Remark.Kind == CodeGenOptions::RK_Enabled) {
+ GenerateArg(Args, OPT_R_Joined, Name, SA);
+ } else if (Remark.Kind == CodeGenOptions::RK_Disabled) {
+ GenerateArg(Args, OPT_R_Joined, StringRef("no-") + Name, SA);
}
- return Pattern;
+}
+
+/// Parse a remark command line argument. It may be missing, disabled/enabled by
+/// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.
+/// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.
+static CodeGenOptions::OptRemark
+ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args,
+ OptSpecifier OptEQ, StringRef Name) {
+ CodeGenOptions::OptRemark Result;
+
+ auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A) {
+ Result.Pattern = A->getValue();
+
+ std::string RegexError;
+ Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);
+ if (!Result.Regex->isValid(RegexError)) {
+ Diags.Report(diag::err_drv_optimization_remark_pattern)
+ << RegexError << A->getAsString(Args);
+ return false;
+ }
+
+ return true;
+ };
+
+ for (Arg *A : Args) {
+ if (A->getOption().matches(OPT_R_Joined)) {
+ StringRef Value = A->getValue();
+
+ if (Value == Name)
+ Result.Kind = CodeGenOptions::RK_Enabled;
+ else if (Value == "everything")
+ Result.Kind = CodeGenOptions::RK_EnabledEverything;
+ else if (Value.split('-') == std::make_pair(StringRef("no"), Name))
+ Result.Kind = CodeGenOptions::RK_Disabled;
+ else if (Value == "no-everything")
+ Result.Kind = CodeGenOptions::RK_DisabledEverything;
+ } else if (A->getOption().matches(OptEQ)) {
+ Result.Kind = CodeGenOptions::RK_WithPattern;
+ if (!InitializeResultPattern(A))
+ return CodeGenOptions::OptRemark();
+ }
+ }
+
+ if (Result.Kind == CodeGenOptions::RK_Disabled ||
+ Result.Kind == CodeGenOptions::RK_DisabledEverything) {
+ Result.Pattern = "";
+ Result.Regex = nullptr;
+ }
+
+ return Result;
}
static bool parseDiagnosticLevelMask(StringRef FlagName,
@@ -893,6 +1248,12 @@
}
}
+static SmallVector<StringRef, 4> serializeSanitizerKinds(SanitizerSet S) {
+ SmallVector<StringRef, 4> Values;
+ serializeSanitizerSet(S, Values);
+ return Values;
+}
+
static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,
ArgList &Args, DiagnosticsEngine &D,
XRayInstrSet &S) {
@@ -912,6 +1273,15 @@
}
}
+static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) {
+ llvm::SmallVector<StringRef, 2> BundleParts;
+ serializeXRayInstrValue(S, BundleParts);
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");
+ return OS.str();
+}
+
// Set the profile kind using fprofile-instrument-use-path.
static void setPGOUseInstrumentor(CodeGenOptions &Opts,
const Twine &ProfileName) {
@@ -933,13 +1303,250 @@
Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
}
+void CompilerInvocation::GenerateCodeGenArgs(
+ const CodeGenOptions &Opts, SmallVectorImpl<const char *> &Args,
+ StringAllocator SA, const llvm::Triple &T, const std::string &OutputFile,
+ const LangOptions *LangOpts) {
+ const CodeGenOptions &CodeGenOpts = Opts;
+
+ if (Opts.OptimizationLevel == 0)
+ GenerateArg(Args, OPT_O0, SA);
+ else
+ GenerateArg(Args, OPT_O, Twine(Opts.OptimizationLevel), SA);
+
+#define CODEGEN_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef CODEGEN_OPTION_WITH_MARSHALLING
+
+ if (Opts.OptimizationLevel > 0) {
+ if (Opts.Inlining == CodeGenOptions::NormalInlining)
+ GenerateArg(Args, OPT_finline_functions, SA);
+ else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)
+ GenerateArg(Args, OPT_finline_hint_functions, SA);
+ else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)
+ GenerateArg(Args, OPT_fno_inline, SA);
+ }
+
+ if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)
+ GenerateArg(Args, OPT_fdirect_access_external_data, SA);
+ else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)
+ GenerateArg(Args, OPT_fno_direct_access_external_data, SA);
+
+ Optional<StringRef> DebugInfoVal;
+ switch (Opts.DebugInfo) {
+ case codegenoptions::DebugLineTablesOnly:
+ DebugInfoVal = "line-tables-only";
+ break;
+ case codegenoptions::DebugDirectivesOnly:
+ DebugInfoVal = "line-directives-only";
+ break;
+ case codegenoptions::DebugInfoConstructor:
+ DebugInfoVal = "constructor";
+ break;
+ case codegenoptions::LimitedDebugInfo:
+ DebugInfoVal = "limited";
+ break;
+ case codegenoptions::FullDebugInfo:
+ DebugInfoVal = "standalone";
+ break;
+ case codegenoptions::UnusedTypeInfo:
+ DebugInfoVal = "unused-types";
+ break;
+ case codegenoptions::NoDebugInfo: // default value
+ DebugInfoVal = None;
+ break;
+ case codegenoptions::LocTrackingOnly: // implied value
+ DebugInfoVal = None;
+ break;
+ }
+ if (DebugInfoVal)
+ GenerateArg(Args, OPT_debug_info_kind_EQ, *DebugInfoVal, SA);
+
+ for (const auto &Prefix : Opts.DebugPrefixMap)
+ GenerateArg(Args, OPT_fdebug_prefix_map_EQ,
+ Prefix.first + "=" + Prefix.second, SA);
+
+ for (const auto &Prefix : Opts.CoveragePrefixMap)
+ GenerateArg(Args, OPT_fcoverage_prefix_map_EQ,
+ Prefix.first + "=" + Prefix.second, SA);
+
+ if (Opts.NewStructPathTBAA)
+ GenerateArg(Args, OPT_new_struct_path_tbaa, SA);
+
+ if (Opts.OptimizeSize == 1)
+ GenerateArg(Args, OPT_O, "s", SA);
+ else if (Opts.OptimizeSize == 2)
+ GenerateArg(Args, OPT_O, "z", SA);
+
+ // SimplifyLibCalls is set only in the absence of -fno-builtin and
+ // -ffreestanding. We'll consider that when generating them.
+
+ // NoBuiltinFuncs are generated by LangOptions.
+
+ if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)
+ GenerateArg(Args, OPT_funroll_loops, SA);
+ else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)
+ GenerateArg(Args, OPT_fno_unroll_loops, SA);
+
+ if (!Opts.BinutilsVersion.empty())
+ GenerateArg(Args, OPT_fbinutils_version_EQ, Opts.BinutilsVersion, SA);
+
+ if (Opts.DebugNameTable ==
+ static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))
+ GenerateArg(Args, OPT_ggnu_pubnames, SA);
+ else if (Opts.DebugNameTable ==
+ static_cast<unsigned>(
+ llvm::DICompileUnit::DebugNameTableKind::Default))
+ GenerateArg(Args, OPT_gpubnames, SA);
+
+ // ProfileInstrumentUsePath is marshalled automatically, no need to generate
+ // it or PGOUseInstrumentor.
+
+ if (Opts.TimePasses) {
+ if (Opts.TimePassesPerRun)
+ GenerateArg(Args, OPT_ftime_report_EQ, "per-pass-run", SA);
+ else
+ GenerateArg(Args, OPT_ftime_report, SA);
+ }
+
+ if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)
+ GenerateArg(Args, OPT_flto, SA);
+
+ if (Opts.PrepareForThinLTO)
+ GenerateArg(Args, OPT_flto_EQ, "thin", SA);
+
+ if (!Opts.ThinLTOIndexFile.empty())
+ GenerateArg(Args, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile, SA);
+
+ if (Opts.SaveTempsFilePrefix == OutputFile)
+ GenerateArg(Args, OPT_save_temps_EQ, "obj", SA);
+
+ StringRef MemProfileBasename("memprof.profraw");
+ if (!Opts.MemoryProfileOutput.empty()) {
+ if (Opts.MemoryProfileOutput == MemProfileBasename) {
+ GenerateArg(Args, OPT_fmemory_profile, SA);
+ } else {
+ size_t ArgLength =
+ Opts.MemoryProfileOutput.size() - MemProfileBasename.size();
+ GenerateArg(Args, OPT_fmemory_profile_EQ,
+ Opts.MemoryProfileOutput.substr(0, ArgLength), SA);
+ }
+ }
+
+ if (memcmp(Opts.CoverageVersion, "408*", 4) != 0)
+ GenerateArg(Args, OPT_coverage_version_EQ,
+ StringRef(Opts.CoverageVersion, 4), SA);
+
+ // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely
+ // '-fembed_bitcode', which does not map to any CompilerInvocation field and
+ // won't be generated.)
+
+ if (Opts.XRayInstrumentationBundle.Mask != XRayInstrKind::All) {
+ std::string InstrBundle =
+ serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle);
+ if (!InstrBundle.empty())
+ GenerateArg(Args, OPT_fxray_instrumentation_bundle, InstrBundle, SA);
+ }
+
+ if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)
+ GenerateArg(Args, OPT_fcf_protection_EQ, "full", SA);
+ else if (Opts.CFProtectionReturn)
+ GenerateArg(Args, OPT_fcf_protection_EQ, "return", SA);
+ else if (Opts.CFProtectionBranch)
+ GenerateArg(Args, OPT_fcf_protection_EQ, "branch", SA);
+
+ for (const auto &F : Opts.LinkBitcodeFiles) {
+ bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
+ F.PropagateAttrs && F.Internalize;
+ GenerateArg(Args,
+ Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,
+ F.Filename, SA);
+ }
+
+ // TODO: Consider removing marshalling annotations from f[no_]emulated_tls.
+ // That would make it easy to generate the option only **once** if it was
+ // explicitly set to non-default value.
+ if (Opts.ExplicitEmulatedTLS) {
+ GenerateArg(
+ Args, Opts.EmulatedTLS ? OPT_femulated_tls : OPT_fno_emulated_tls, SA);
+ }
+
+ if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE())
+ GenerateArg(Args, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str(), SA);
+
+ if (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE())
+ GenerateArg(Args, OPT_fdenormal_fp_math_f32_EQ, Opts.FP32DenormalMode.str(),
+ SA);
+
+ if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {
+ OptSpecifier Opt =
+ T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;
+ GenerateArg(Args, Opt, SA);
+ } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {
+ OptSpecifier Opt =
+ T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;
+ GenerateArg(Args, Opt, SA);
+ }
+
+ if (Opts.EnableAIXExtendedAltivecABI)
+ GenerateArg(Args, OPT_mabi_EQ_vec_extabi, SA);
+
+ if (!Opts.OptRecordPasses.empty())
+ GenerateArg(Args, OPT_opt_record_passes, Opts.OptRecordPasses, SA);
+
+ if (!Opts.OptRecordFormat.empty())
+ GenerateArg(Args, OPT_opt_record_format, Opts.OptRecordFormat, SA);
+
+ GenerateOptimizationRemark(Args, SA, OPT_Rpass_EQ, "pass",
+ Opts.OptimizationRemark);
+
+ GenerateOptimizationRemark(Args, SA, OPT_Rpass_missed_EQ, "pass-missed",
+ Opts.OptimizationRemarkMissed);
+
+ GenerateOptimizationRemark(Args, SA, OPT_Rpass_analysis_EQ, "pass-analysis",
+ Opts.OptimizationRemarkAnalysis);
+
+ GenerateArg(Args, OPT_fdiagnostics_hotness_threshold_EQ,
+ Opts.DiagnosticsHotnessThreshold
+ ? Twine(*Opts.DiagnosticsHotnessThreshold)
+ : "auto",
+ SA);
+
+ for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))
+ GenerateArg(Args, OPT_fsanitize_recover_EQ, Sanitizer, SA);
+
+ for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))
+ GenerateArg(Args, OPT_fsanitize_trap_EQ, Sanitizer, SA);
+
+ if (!Opts.EmitVersionIdentMetadata)
+ GenerateArg(Args, OPT_Qn, SA);
+
+ switch (Opts.FiniteLoops) {
+ case CodeGenOptions::FiniteLoopsKind::Language:
+ break;
+ case CodeGenOptions::FiniteLoopsKind::Always:
+ GenerateArg(Args, OPT_ffinite_loops, SA);
+ break;
+ case CodeGenOptions::FiniteLoopsKind::Never:
+ GenerateArg(Args, OPT_fno_finite_loops, SA);
+ break;
+ }
+}
+
bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
InputKind IK,
DiagnosticsEngine &Diags,
const llvm::Triple &T,
const std::string &OutputFile,
const LangOptions &LangOptsRef) {
- bool Success = true;
+ unsigned NumErrorsBefore = Diags.getNumErrors();
unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
// TODO: This could be done in Driver
@@ -965,10 +1572,9 @@
HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
MERGER, EXTRACTOR, TABLE_INDEX) \
- PARSE_OPTION_WITH_MARSHALLING(Args, Diags, Success, ID, FLAGS, PARAM, \
- SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
- IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \
- MERGER, TABLE_INDEX)
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
#include "clang/Driver/Options.inc"
#undef CODEGEN_OPTION_WITH_MARSHALLING
@@ -998,13 +1604,36 @@
Opts.DirectAccessExternalData =
Args.hasArg(OPT_fdirect_access_external_data) ||
(!Args.hasArg(OPT_fno_direct_access_external_data) &&
- getLastArgIntValue(Args, OPT_pic_level, 0, Diags) == 0);
+ LangOpts->PICLevel == 0);
+
+ if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
+ unsigned Val =
+ llvm::StringSwitch<unsigned>(A->getValue())
+ .Case("line-tables-only", codegenoptions::DebugLineTablesOnly)
+ .Case("line-directives-only", codegenoptions::DebugDirectivesOnly)
+ .Case("constructor", codegenoptions::DebugInfoConstructor)
+ .Case("limited", codegenoptions::LimitedDebugInfo)
+ .Case("standalone", codegenoptions::FullDebugInfo)
+ .Case("unused-types", codegenoptions::UnusedTypeInfo)
+ .Default(~0U);
+ if (Val == ~0U)
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
+ << A->getValue();
+ else
+ Opts.setDebugInfo(static_cast<codegenoptions::DebugInfoKind>(Val));
+ }
// If -fuse-ctor-homing is set and limited debug info is already on, then use
- // constructor homing.
- if (Args.getLastArg(OPT_fuse_ctor_homing))
- if (Opts.getDebugInfo() == codegenoptions::LimitedDebugInfo)
+ // constructor homing, and vice versa for -fno-use-ctor-homing.
+ if (const Arg *A =
+ Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) {
+ if (A->getOption().matches(OPT_fuse_ctor_homing) &&
+ Opts.getDebugInfo() == codegenoptions::LimitedDebugInfo)
Opts.setDebugInfo(codegenoptions::DebugInfoConstructor);
+ if (A->getOption().matches(OPT_fno_use_ctor_homing) &&
+ Opts.getDebugInfo() == codegenoptions::DebugInfoConstructor)
+ Opts.setDebugInfo(codegenoptions::LimitedDebugInfo);
+ }
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {
auto Split = StringRef(Arg).split('=');
@@ -1012,9 +1641,9 @@
{std::string(Split.first), std::string(Split.second)});
}
- for (const auto &Arg : Args.getAllArgValues(OPT_fprofile_prefix_map_EQ)) {
+ for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {
auto Split = StringRef(Arg).split('=');
- Opts.ProfilePrefixMap.insert(
+ Opts.CoveragePrefixMap.insert(
{std::string(Split.first), std::string(Split.second)});
}
@@ -1027,13 +1656,18 @@
llvm::is_contained(DebugEntryValueArchs, T.getArch()))
Opts.EmitCallSiteInfo = true;
+ if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) {
+ Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export)
+ << Opts.DIBugsReportFilePath;
+ Opts.DIBugsReportFilePath = "";
+ }
+
Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
Args.hasArg(OPT_new_struct_path_tbaa);
Opts.OptimizeSize = getOptimizationLevelSize(Args);
- Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
- Args.hasArg(OPT_ffreestanding));
+ Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;
if (Opts.SimplifyLibCalls)
- getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
+ Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;
Opts.UnrollLoops =
Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
(Opts.OptimizationLevel > 1));
@@ -1070,11 +1704,6 @@
}
}
- // Basic Block Sections implies Function Sections.
- Opts.FunctionSections =
- Args.hasArg(OPT_ffunction_sections) ||
- (Opts.BBSections != "none" && Opts.BBSections != "labels");
-
Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ);
Opts.PrepareForThinLTO = false;
if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
@@ -1107,6 +1736,7 @@
} else if (Args.hasArg(OPT_fmemory_profile))
Opts.MemoryProfileOutput = MemProfileBasename;
+ memcpy(Opts.CoverageVersion, "408*", 4);
if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
if (Args.hasArg(OPT_coverage_version_EQ)) {
StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);
@@ -1158,10 +1788,8 @@
Opts.CFProtectionReturn = 1;
else if (Name == "branch")
Opts.CFProtectionBranch = 1;
- else if (Name != "none") {
+ else if (Name != "none")
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
- Success = false;
- }
}
for (auto *A :
@@ -1183,6 +1811,14 @@
Opts.ExplicitEmulatedTLS = true;
}
+ if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
+ if (T.isOSAIX()) {
+ StringRef Name = A->getValue();
+ if (Name != "global-dynamic")
+ Diags.Report(diag::err_aix_unsupported_tls_model) << Name;
+ }
+ }
+
if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
StringRef Val = A->getValue();
Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);
@@ -1219,10 +1855,6 @@
}
}
- if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility) ||
- !Args.hasArg(OPT_fvisibility)))
- Opts.IgnoreXCOFFVisibility = 1;
-
if (Arg *A =
Args.getLastArg(OPT_mabi_EQ_vec_default, OPT_mabi_EQ_vec_extabi)) {
if (!T.isOSAIX())
@@ -1230,13 +1862,7 @@
<< A->getSpelling() << T.str();
const Option &O = A->getOption();
- if (O.matches(OPT_mabi_EQ_vec_default))
- Diags.Report(diag::err_aix_default_altivec_abi)
- << A->getSpelling() << T.str();
- else {
- assert(O.matches(OPT_mabi_EQ_vec_extabi));
- Opts.EnableAIXExtendedAltivecABI = 1;
- }
+ Opts.EnableAIXExtendedAltivecABI = O.matches(OPT_mabi_EQ_vec_extabi);
}
bool NeedLocTracking = false;
@@ -1254,23 +1880,18 @@
NeedLocTracking = true;
}
- if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
- Opts.OptimizationRemarkPattern =
- GenerateOptimizationRemarkRegex(Diags, Args, A);
- NeedLocTracking = true;
- }
+ Opts.OptimizationRemark =
+ ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass");
- if (Arg *A = Args.getLastArg(OPT_Rpass_missed_EQ)) {
- Opts.OptimizationRemarkMissedPattern =
- GenerateOptimizationRemarkRegex(Diags, Args, A);
- NeedLocTracking = true;
- }
+ Opts.OptimizationRemarkMissed =
+ ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed");
- if (Arg *A = Args.getLastArg(OPT_Rpass_analysis_EQ)) {
- Opts.OptimizationRemarkAnalysisPattern =
- GenerateOptimizationRemarkRegex(Diags, Args, A);
- NeedLocTracking = true;
- }
+ Opts.OptimizationRemarkAnalysis = ParseOptimizationRemark(
+ Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis");
+
+ NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() ||
+ Opts.OptimizationRemarkMissed.hasValidPattern() ||
+ Opts.OptimizationRemarkAnalysis.hasValidPattern();
bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
bool UsingProfile = UsingSampleProfile ||
@@ -1307,6 +1928,9 @@
if (UsingSampleProfile)
NeedLocTracking = true;
+ if (!Opts.StackUsageOutput.empty())
+ NeedLocTracking = true;
+
// If the user requested a flag that requires source locations available in
// the backend, make sure that the backend tracks source location information.
if (NeedLocTracking && Opts.getDebugInfo() == codegenoptions::NoDebugInfo)
@@ -1327,55 +1951,118 @@
Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;
else if (Args.hasArg(options::OPT_fno_finite_loops))
Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;
- return Success;
+
+ Opts.EmitIEEENaNCompliantInsts =
+ Args.hasFlag(options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee);
+ if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)
+ Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
-static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
- ArgList &Args) {
+static void
+GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ const DependencyOutputOptions &DependencyOutputOpts = Opts;
+#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING
+
+ if (Opts.ShowIncludesDest != ShowIncludesDestination::None)
+ GenerateArg(Args, OPT_show_includes, SA);
+
+ for (const auto &Dep : Opts.ExtraDeps) {
+ switch (Dep.second) {
+ case EDK_SanitizeIgnorelist:
+ // Sanitizer ignorelist arguments are generated from LanguageOptions.
+ continue;
+ case EDK_ModuleFile:
+ // Module file arguments are generated from FrontendOptions and
+ // HeaderSearchOptions.
+ continue;
+ case EDK_ProfileList:
+ // Profile list arguments are generated from LanguageOptions via the
+ // marshalling infrastructure.
+ continue;
+ case EDK_DepFileEntry:
+ GenerateArg(Args, OPT_fdepfile_entry, Dep.first, SA);
+ break;
+ }
+ }
+}
+
+static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
+ ArgList &Args, DiagnosticsEngine &Diags,
+ frontend::ActionKind Action,
+ bool ShowLineMarkers) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ DependencyOutputOptions &DependencyOutputOpts = Opts;
+#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING
+
if (Args.hasArg(OPT_show_includes)) {
// Writing both /showIncludes and preprocessor output to stdout
// would produce interleaved output, so use stderr for /showIncludes.
// This behaves the same as cl.exe, when /E, /EP or /P are passed.
- if (Args.hasArg(options::OPT_E) || Args.hasArg(options::OPT_P))
+ if (Action == frontend::PrintPreprocessedInput || !ShowLineMarkers)
Opts.ShowIncludesDest = ShowIncludesDestination::Stderr;
else
Opts.ShowIncludesDest = ShowIncludesDestination::Stdout;
} else {
Opts.ShowIncludesDest = ShowIncludesDestination::None;
}
- // Add sanitizer blacklists as extra dependencies.
+
+ // Add sanitizer ignorelists as extra dependencies.
// They won't be discovered by the regular preprocessor, so
// we let make / ninja to know about this implicit dependency.
- if (!Args.hasArg(OPT_fno_sanitize_blacklist)) {
- for (const auto *A : Args.filtered(OPT_fsanitize_blacklist)) {
+ if (!Args.hasArg(OPT_fno_sanitize_ignorelist)) {
+ for (const auto *A : Args.filtered(OPT_fsanitize_ignorelist_EQ)) {
StringRef Val = A->getValue();
if (Val.find('=') == StringRef::npos)
- Opts.ExtraDeps.push_back(std::string(Val));
+ Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
}
if (Opts.IncludeSystemHeaders) {
- for (const auto *A : Args.filtered(OPT_fsanitize_system_blacklist)) {
+ for (const auto *A : Args.filtered(OPT_fsanitize_system_ignorelist_EQ)) {
StringRef Val = A->getValue();
if (Val.find('=') == StringRef::npos)
- Opts.ExtraDeps.push_back(std::string(Val));
+ Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);
}
}
}
// -fprofile-list= dependencies.
for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ))
- Opts.ExtraDeps.push_back(Filename);
+ Opts.ExtraDeps.emplace_back(Filename, EDK_ProfileList);
// Propagate the extra dependencies.
- for (const auto *A : Args.filtered(OPT_fdepfile_entry)) {
- Opts.ExtraDeps.push_back(A->getValue());
- }
+ for (const auto *A : Args.filtered(OPT_fdepfile_entry))
+ Opts.ExtraDeps.emplace_back(A->getValue(), EDK_DepFileEntry);
// Only the -fmodule-file=<file> form.
for (const auto *A : Args.filtered(OPT_fmodule_file)) {
StringRef Val = A->getValue();
if (Val.find('=') == StringRef::npos)
- Opts.ExtraDeps.push_back(std::string(Val));
+ Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile);
}
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
@@ -1429,23 +2116,143 @@
return Success;
}
-bool CompilerInvocation::parseSimpleArgs(const ArgList &Args,
- DiagnosticsEngine &Diags) {
- bool Success = true;
+static void GenerateFileSystemArgs(const FileSystemOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ const FileSystemOptions &FileSystemOpts = Opts;
-#define OPTION_WITH_MARSHALLING( \
+#define FILE_SYSTEM_OPTION_WITH_MARSHALLING( \
PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
MERGER, EXTRACTOR, TABLE_INDEX) \
- PARSE_OPTION_WITH_MARSHALLING(Args, Diags, Success, ID, FLAGS, PARAM, \
- SHOULD_PARSE, this->KEYPATH, DEFAULT_VALUE, \
- IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \
- MERGER, TABLE_INDEX)
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
#include "clang/Driver/Options.inc"
-#undef OPTION_WITH_MARSHALLING
+#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
+}
- return Success;
+static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args,
+ DiagnosticsEngine &Diags) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ FileSystemOptions &FileSystemOpts = Opts;
+
+#define FILE_SYSTEM_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING
+
+ return Diags.getNumErrors() == NumErrorsBefore;
+}
+
+static void GenerateMigratorArgs(const MigratorOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ const MigratorOptions &MigratorOpts = Opts;
+#define MIGRATOR_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef MIGRATOR_OPTION_WITH_MARSHALLING
+}
+
+static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args,
+ DiagnosticsEngine &Diags) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ MigratorOptions &MigratorOpts = Opts;
+
+#define MIGRATOR_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef MIGRATOR_OPTION_WITH_MARSHALLING
+
+ return Diags.getNumErrors() == NumErrorsBefore;
+}
+
+void CompilerInvocation::GenerateDiagnosticArgs(
+ const DiagnosticOptions &Opts, SmallVectorImpl<const char *> &Args,
+ StringAllocator SA, bool DefaultDiagColor) {
+ const DiagnosticOptions *DiagnosticOpts = &Opts;
+#define DIAG_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef DIAG_OPTION_WITH_MARSHALLING
+
+ if (!Opts.DiagnosticSerializationFile.empty())
+ GenerateArg(Args, OPT_diagnostic_serialized_file,
+ Opts.DiagnosticSerializationFile, SA);
+
+ if (Opts.ShowColors)
+ GenerateArg(Args, OPT_fcolor_diagnostics, SA);
+
+ if (Opts.VerifyDiagnostics &&
+ llvm::is_contained(Opts.VerifyPrefixes, "expected"))
+ GenerateArg(Args, OPT_verify, SA);
+
+ for (const auto &Prefix : Opts.VerifyPrefixes)
+ if (Prefix != "expected")
+ GenerateArg(Args, OPT_verify_EQ, Prefix, SA);
+
+ DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected();
+ if (VIU == DiagnosticLevelMask::None) {
+ // This is the default, don't generate anything.
+ } else if (VIU == DiagnosticLevelMask::All) {
+ GenerateArg(Args, OPT_verify_ignore_unexpected, SA);
+ } else {
+ if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0)
+ GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "note", SA);
+ if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0)
+ GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "remark", SA);
+ if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0)
+ GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "warning", SA);
+ if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0)
+ GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "error", SA);
+ }
+
+ for (const auto &Warning : Opts.Warnings) {
+ // This option is automatically generated from UndefPrefixes.
+ if (Warning == "undef-prefix")
+ continue;
+ Args.push_back(SA(StringRef("-W") + Warning));
+ }
+
+ for (const auto &Remark : Opts.Remarks) {
+ // These arguments are generated from OptimizationRemark fields of
+ // CodeGenOptions.
+ StringRef IgnoredRemarks[] = {"pass", "no-pass",
+ "pass-analysis", "no-pass-analysis",
+ "pass-missed", "no-pass-missed"};
+ if (llvm::is_contained(IgnoredRemarks, Remark))
+ continue;
+
+ Args.push_back(SA(StringRef("-R") + Remark));
+ }
}
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
@@ -1458,20 +2265,20 @@
Diags = &*IgnoringDiags;
}
+ unsigned NumErrorsBefore = Diags->getNumErrors();
+
// The key paths of diagnostic options defined in Options.td start with
// "DiagnosticOpts->". Let's provide the expected variable name and type.
DiagnosticOptions *DiagnosticOpts = &Opts;
- bool Success = true;
#define DIAG_OPTION_WITH_MARSHALLING( \
PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
MERGER, EXTRACTOR, TABLE_INDEX) \
- PARSE_OPTION_WITH_MARSHALLING(Args, *Diags, Success, ID, FLAGS, PARAM, \
- SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
- IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \
- MERGER, TABLE_INDEX)
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, *Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
#include "clang/Driver/Options.inc"
#undef DIAG_OPTION_WITH_MARSHALLING
@@ -1482,24 +2289,20 @@
Opts.DiagnosticSerializationFile = A->getValue();
Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
- if (Args.getLastArgValue(OPT_fdiagnostics_format) == "msvc-fallback")
- Opts.CLFallbackMode = true;
-
Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
+ Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
if (Args.hasArg(OPT_verify))
Opts.VerifyPrefixes.push_back("expected");
// Keep VerifyPrefixes in its original order for the sake of diagnostics, and
// then sort it to prepare for fast lookup using std::binary_search.
- if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags)) {
+ if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags))
Opts.VerifyDiagnostics = false;
- Success = false;
- }
else
llvm::sort(Opts.VerifyPrefixes);
DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
- Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
- Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
- *Diags, DiagMask);
+ parseDiagnosticLevelMask(
+ "-verify-ignore-unexpected=",
+ Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), *Diags, DiagMask);
if (Args.hasArg(OPT_verify_ignore_unexpected))
DiagMask = DiagnosticLevelMask::All;
Opts.setVerifyIgnoreUnexpected(DiagMask);
@@ -1512,7 +2315,7 @@
addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);
addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);
- return Success;
+ return Diags->getNumErrors() == NumErrorsBefore;
}
/// Parse the argument to the -ftest-module-file-extension
@@ -1539,18 +2342,264 @@
return false;
}
-static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
- DiagnosticsEngine &Diags,
- bool &IsHeaderFile) {
+/// Return a table that associates command line option specifiers with the
+/// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is
+/// intentionally missing, as this case is handled separately from other
+/// frontend options.
+static const auto &getFrontendActionTable() {
+ static const std::pair<frontend::ActionKind, unsigned> Table[] = {
+ {frontend::ASTDeclList, OPT_ast_list},
+
+ {frontend::ASTDump, OPT_ast_dump_all_EQ},
+ {frontend::ASTDump, OPT_ast_dump_all},
+ {frontend::ASTDump, OPT_ast_dump_EQ},
+ {frontend::ASTDump, OPT_ast_dump},
+ {frontend::ASTDump, OPT_ast_dump_lookups},
+ {frontend::ASTDump, OPT_ast_dump_decl_types},
+
+ {frontend::ASTPrint, OPT_ast_print},
+ {frontend::ASTView, OPT_ast_view},
+ {frontend::DumpCompilerOptions, OPT_compiler_options_dump},
+ {frontend::DumpRawTokens, OPT_dump_raw_tokens},
+ {frontend::DumpTokens, OPT_dump_tokens},
+ {frontend::EmitAssembly, OPT_S},
+ {frontend::EmitBC, OPT_emit_llvm_bc},
+ {frontend::EmitHTML, OPT_emit_html},
+ {frontend::EmitLLVM, OPT_emit_llvm},
+ {frontend::EmitLLVMOnly, OPT_emit_llvm_only},
+ {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
+ {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
+ {frontend::EmitObj, OPT_emit_obj},
+
+ {frontend::FixIt, OPT_fixit_EQ},
+ {frontend::FixIt, OPT_fixit},
+
+ {frontend::GenerateModule, OPT_emit_module},
+ {frontend::GenerateModuleInterface, OPT_emit_module_interface},
+ {frontend::GenerateHeaderModule, OPT_emit_header_module},
+ {frontend::GeneratePCH, OPT_emit_pch},
+ {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
+ {frontend::InitOnly, OPT_init_only},
+ {frontend::ParseSyntaxOnly, OPT_fsyntax_only},
+ {frontend::ModuleFileInfo, OPT_module_file_info},
+ {frontend::VerifyPCH, OPT_verify_pch},
+ {frontend::PrintPreamble, OPT_print_preamble},
+ {frontend::PrintPreprocessedInput, OPT_E},
+ {frontend::TemplightDump, OPT_templight_dump},
+ {frontend::RewriteMacros, OPT_rewrite_macros},
+ {frontend::RewriteObjC, OPT_rewrite_objc},
+ {frontend::RewriteTest, OPT_rewrite_test},
+ {frontend::RunAnalysis, OPT_analyze},
+ {frontend::MigrateSource, OPT_migrate},
+ {frontend::RunPreprocessorOnly, OPT_Eonly},
+ {frontend::PrintDependencyDirectivesSourceMinimizerOutput,
+ OPT_print_dependency_directives_minimized_source},
+ };
+
+ return Table;
+}
+
+/// Maps command line option to frontend action.
+static Optional<frontend::ActionKind> getFrontendAction(OptSpecifier &Opt) {
+ for (const auto &ActionOpt : getFrontendActionTable())
+ if (ActionOpt.second == Opt.getID())
+ return ActionOpt.first;
+
+ return None;
+}
+
+/// Maps frontend action to command line option.
+static Optional<OptSpecifier>
+getProgramActionOpt(frontend::ActionKind ProgramAction) {
+ for (const auto &ActionOpt : getFrontendActionTable())
+ if (ActionOpt.first == ProgramAction)
+ return OptSpecifier(ActionOpt.second);
+
+ return None;
+}
+
+static void GenerateFrontendArgs(const FrontendOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA,
+ bool IsHeader) {
+ const FrontendOptions &FrontendOpts = Opts;
+#define FRONTEND_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef FRONTEND_OPTION_WITH_MARSHALLING
+
+ Optional<OptSpecifier> ProgramActionOpt =
+ getProgramActionOpt(Opts.ProgramAction);
+
+ // Generating a simple flag covers most frontend actions.
+ std::function<void()> GenerateProgramAction = [&]() {
+ GenerateArg(Args, *ProgramActionOpt, SA);
+ };
+
+ if (!ProgramActionOpt) {
+ // PluginAction is the only program action handled separately.
+ assert(Opts.ProgramAction == frontend::PluginAction &&
+ "Frontend action without option.");
+ GenerateProgramAction = [&]() {
+ GenerateArg(Args, OPT_plugin, Opts.ActionName, SA);
+ };
+ }
+
+ // FIXME: Simplify the complex 'AST dump' command line.
+ if (Opts.ProgramAction == frontend::ASTDump) {
+ GenerateProgramAction = [&]() {
+ // ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via
+ // marshalling infrastructure.
+
+ if (Opts.ASTDumpFormat != ADOF_Default) {
+ StringRef Format;
+ switch (Opts.ASTDumpFormat) {
+ case ADOF_Default:
+ llvm_unreachable("Default AST dump format.");
+ case ADOF_JSON:
+ Format = "json";
+ break;
+ }
+
+ if (Opts.ASTDumpAll)
+ GenerateArg(Args, OPT_ast_dump_all_EQ, Format, SA);
+ if (Opts.ASTDumpDecls)
+ GenerateArg(Args, OPT_ast_dump_EQ, Format, SA);
+ } else {
+ if (Opts.ASTDumpAll)
+ GenerateArg(Args, OPT_ast_dump_all, SA);
+ if (Opts.ASTDumpDecls)
+ GenerateArg(Args, OPT_ast_dump, SA);
+ }
+ };
+ }
+
+ if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) {
+ GenerateProgramAction = [&]() {
+ GenerateArg(Args, OPT_fixit_EQ, Opts.FixItSuffix, SA);
+ };
+ }
+
+ GenerateProgramAction();
+
+ for (const auto &PluginArgs : Opts.PluginArgs) {
+ Option Opt = getDriverOptTable().getOption(OPT_plugin_arg);
+ const char *Spelling =
+ SA(Opt.getPrefix() + Opt.getName() + PluginArgs.first);
+ for (const auto &PluginArg : PluginArgs.second)
+ denormalizeString(Args, Spelling, SA, Opt.getKind(), 0, PluginArg);
+ }
+
+ for (const auto &Ext : Opts.ModuleFileExtensions)
+ if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get()))
+ GenerateArg(Args, OPT_ftest_module_file_extension_EQ, TestExt->str(), SA);
+
+ if (!Opts.CodeCompletionAt.FileName.empty())
+ GenerateArg(Args, OPT_code_completion_at, Opts.CodeCompletionAt.ToString(),
+ SA);
+
+ for (const auto &Plugin : Opts.Plugins)
+ GenerateArg(Args, OPT_load, Plugin, SA);
+
+ // ASTDumpDecls and ASTDumpAll already handled with ProgramAction.
+
+ for (const auto &ModuleFile : Opts.ModuleFiles)
+ GenerateArg(Args, OPT_fmodule_file, ModuleFile, SA);
+
+ if (Opts.AuxTargetCPU.hasValue())
+ GenerateArg(Args, OPT_aux_target_cpu, *Opts.AuxTargetCPU, SA);
+
+ if (Opts.AuxTargetFeatures.hasValue())
+ for (const auto &Feature : *Opts.AuxTargetFeatures)
+ GenerateArg(Args, OPT_aux_target_feature, Feature, SA);
+
+ {
+ StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : "";
+ StringRef ModuleMap =
+ Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : "";
+ StringRef Header = IsHeader ? "-header" : "";
+
+ StringRef Lang;
+ switch (Opts.DashX.getLanguage()) {
+ case Language::C:
+ Lang = "c";
+ break;
+ case Language::OpenCL:
+ Lang = "cl";
+ break;
+ case Language::OpenCLCXX:
+ Lang = "clcpp";
+ break;
+ case Language::CUDA:
+ Lang = "cuda";
+ break;
+ case Language::HIP:
+ Lang = "hip";
+ break;
+ case Language::CXX:
+ Lang = "c++";
+ break;
+ case Language::ObjC:
+ Lang = "objective-c";
+ break;
+ case Language::ObjCXX:
+ Lang = "objective-c++";
+ break;
+ case Language::RenderScript:
+ Lang = "renderscript";
+ break;
+ case Language::Asm:
+ Lang = "assembler-with-cpp";
+ break;
+ case Language::Unknown:
+ assert(Opts.DashX.getFormat() == InputKind::Precompiled &&
+ "Generating -x argument for unknown language (not precompiled).");
+ Lang = "ast";
+ break;
+ case Language::LLVM_IR:
+ Lang = "ir";
+ break;
+ }
+
+ GenerateArg(Args, OPT_x, Lang + Header + ModuleMap + Preprocessed, SA);
+ }
+
+ // OPT_INPUT has a unique class, generate it directly.
+ for (const auto &Input : Opts.Inputs)
+ Args.push_back(SA(Input.getFile()));
+}
+
+static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
+ DiagnosticsEngine &Diags, bool &IsHeaderFile) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ FrontendOptions &FrontendOpts = Opts;
+
+#define FRONTEND_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef FRONTEND_OPTION_WITH_MARSHALLING
+
Opts.ProgramAction = frontend::ParseSyntaxOnly;
if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
- switch (A->getOption().getID()) {
- default:
- llvm_unreachable("Invalid option in group!");
- case OPT_ast_list:
- Opts.ProgramAction = frontend::ASTDeclList; break;
- case OPT_ast_dump_all_EQ:
- case OPT_ast_dump_EQ: {
+ OptSpecifier Opt = OptSpecifier(A->getOption().getID());
+ Optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt);
+ assert(ProgramAction && "Option specifier not in Action_Group.");
+
+ if (ProgramAction == frontend::ASTDump &&
+ (Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) {
unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
.CaseLower("default", ADOF_Default)
.CaseLower("json", ADOF_JSON)
@@ -1563,108 +2612,39 @@
<< A->getAsString(Args) << A->getValue();
Opts.ASTDumpFormat = ADOF_Default;
}
- LLVM_FALLTHROUGH;
}
- case OPT_ast_dump:
- case OPT_ast_dump_all:
- case OPT_ast_dump_lookups:
- case OPT_ast_dump_decl_types:
- Opts.ProgramAction = frontend::ASTDump; break;
- case OPT_ast_print:
- Opts.ProgramAction = frontend::ASTPrint; break;
- case OPT_ast_view:
- Opts.ProgramAction = frontend::ASTView; break;
- case OPT_compiler_options_dump:
- Opts.ProgramAction = frontend::DumpCompilerOptions; break;
- case OPT_dump_raw_tokens:
- Opts.ProgramAction = frontend::DumpRawTokens; break;
- case OPT_dump_tokens:
- Opts.ProgramAction = frontend::DumpTokens; break;
- case OPT_S:
- Opts.ProgramAction = frontend::EmitAssembly; break;
- case OPT_emit_llvm_bc:
- Opts.ProgramAction = frontend::EmitBC; break;
- case OPT_emit_html:
- Opts.ProgramAction = frontend::EmitHTML; break;
- case OPT_emit_llvm:
- Opts.ProgramAction = frontend::EmitLLVM; break;
- case OPT_emit_llvm_only:
- Opts.ProgramAction = frontend::EmitLLVMOnly; break;
- case OPT_emit_codegen_only:
- Opts.ProgramAction = frontend::EmitCodeGenOnly; break;
- case OPT_emit_obj:
- Opts.ProgramAction = frontend::EmitObj; break;
- case OPT_fixit_EQ:
+
+ if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ)
Opts.FixItSuffix = A->getValue();
- LLVM_FALLTHROUGH;
- case OPT_fixit:
- Opts.ProgramAction = frontend::FixIt; break;
- case OPT_emit_module:
- Opts.ProgramAction = frontend::GenerateModule; break;
- case OPT_emit_module_interface:
- Opts.ProgramAction = frontend::GenerateModuleInterface; break;
- case OPT_emit_header_module:
- Opts.ProgramAction = frontend::GenerateHeaderModule; break;
- case OPT_emit_pch:
- Opts.ProgramAction = frontend::GeneratePCH; break;
- case OPT_emit_interface_stubs: {
+
+ if (ProgramAction == frontend::GenerateInterfaceStubs) {
StringRef ArgStr =
Args.hasArg(OPT_interface_stub_version_EQ)
? Args.getLastArgValue(OPT_interface_stub_version_EQ)
- : "experimental-ifs-v2";
+ : "ifs-v1";
if (ArgStr == "experimental-yaml-elf-v1" ||
- ArgStr == "experimental-ifs-v1" ||
+ ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||
ArgStr == "experimental-tapi-elf-v1") {
std::string ErrorMessage =
"Invalid interface stub format: " + ArgStr.str() +
" is deprecated.";
Diags.Report(diag::err_drv_invalid_value)
<< "Must specify a valid interface stub format type, ie: "
- "-interface-stub-version=experimental-ifs-v2"
+ "-interface-stub-version=ifs-v1"
<< ErrorMessage;
- } else if (!ArgStr.startswith("experimental-ifs-")) {
+ ProgramAction = frontend::ParseSyntaxOnly;
+ } else if (!ArgStr.startswith("ifs-")) {
std::string ErrorMessage =
"Invalid interface stub format: " + ArgStr.str() + ".";
Diags.Report(diag::err_drv_invalid_value)
<< "Must specify a valid interface stub format type, ie: "
- "-interface-stub-version=experimental-ifs-v2"
+ "-interface-stub-version=ifs-v1"
<< ErrorMessage;
- } else {
- Opts.ProgramAction = frontend::GenerateInterfaceStubs;
+ ProgramAction = frontend::ParseSyntaxOnly;
}
- break;
}
- case OPT_init_only:
- Opts.ProgramAction = frontend::InitOnly; break;
- case OPT_fsyntax_only:
- Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
- case OPT_module_file_info:
- Opts.ProgramAction = frontend::ModuleFileInfo; break;
- case OPT_verify_pch:
- Opts.ProgramAction = frontend::VerifyPCH; break;
- case OPT_print_preamble:
- Opts.ProgramAction = frontend::PrintPreamble; break;
- case OPT_E:
- Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
- case OPT_templight_dump:
- Opts.ProgramAction = frontend::TemplightDump; break;
- case OPT_rewrite_macros:
- Opts.ProgramAction = frontend::RewriteMacros; break;
- case OPT_rewrite_objc:
- Opts.ProgramAction = frontend::RewriteObjC; break;
- case OPT_rewrite_test:
- Opts.ProgramAction = frontend::RewriteTest; break;
- case OPT_analyze:
- Opts.ProgramAction = frontend::RunAnalysis; break;
- case OPT_migrate:
- Opts.ProgramAction = frontend::MigrateSource; break;
- case OPT_Eonly:
- Opts.ProgramAction = frontend::RunPreprocessorOnly; break;
- case OPT_print_dependency_directives_minimized_source:
- Opts.ProgramAction =
- frontend::PrintDependencyDirectivesSourceMinimizerOutput;
- break;
- }
+
+ Opts.ProgramAction = *ProgramAction;
}
if (const Arg* A = Args.getLastArg(OPT_plugin)) {
@@ -1744,6 +2724,7 @@
DashX = llvm::StringSwitch<InputKind>(XValue)
.Case("c", Language::C)
.Case("cl", Language::OpenCL)
+ .Case("clcpp", Language::OpenCLCXX)
.Case("cuda", Language::CUDA)
.Case("hip", Language::HIP)
.Case("c++", Language::CXX)
@@ -1810,7 +2791,9 @@
Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);
}
- return DashX;
+ Opts.DashX = DashX;
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
@@ -1820,8 +2803,150 @@
return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
}
-static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
+static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ const HeaderSearchOptions *HeaderSearchOpts = &Opts;
+#define HEADER_SEARCH_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
+
+ if (Opts.UseLibcxx)
+ GenerateArg(Args, OPT_stdlib_EQ, "libc++", SA);
+
+ if (!Opts.ModuleCachePath.empty())
+ GenerateArg(Args, OPT_fmodules_cache_path, Opts.ModuleCachePath, SA);
+
+ for (const auto &File : Opts.PrebuiltModuleFiles)
+ GenerateArg(Args, OPT_fmodule_file, File.first + "=" + File.second, SA);
+
+ for (const auto &Path : Opts.PrebuiltModulePaths)
+ GenerateArg(Args, OPT_fprebuilt_module_path, Path, SA);
+
+ for (const auto &Macro : Opts.ModulesIgnoreMacros)
+ GenerateArg(Args, OPT_fmodules_ignore_macro, Macro.val(), SA);
+
+ auto Matches = [](const HeaderSearchOptions::Entry &Entry,
+ llvm::ArrayRef<frontend::IncludeDirGroup> Groups,
+ llvm::Optional<bool> IsFramework,
+ llvm::Optional<bool> IgnoreSysRoot) {
+ return llvm::find(Groups, Entry.Group) != Groups.end() &&
+ (!IsFramework || (Entry.IsFramework == *IsFramework)) &&
+ (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot));
+ };
+
+ auto It = Opts.UserEntries.begin();
+ auto End = Opts.UserEntries.end();
+
+ // Add -I..., -F..., and -index-header-map options in order.
+ for (; It < End &&
+ Matches(*It, {frontend::IndexHeaderMap, frontend::Angled}, None, true);
+ ++It) {
+ OptSpecifier Opt = [It, Matches]() {
+ if (Matches(*It, frontend::IndexHeaderMap, true, true))
+ return OPT_F;
+ if (Matches(*It, frontend::IndexHeaderMap, false, true))
+ return OPT_I;
+ if (Matches(*It, frontend::Angled, true, true))
+ return OPT_F;
+ if (Matches(*It, frontend::Angled, false, true))
+ return OPT_I;
+ llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");
+ }();
+
+ if (It->Group == frontend::IndexHeaderMap)
+ GenerateArg(Args, OPT_index_header_map, SA);
+ GenerateArg(Args, Opt, It->Path, SA);
+ };
+
+ // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may
+ // have already been generated as "-I[xx]yy". If that's the case, their
+ // position on command line was such that this has no semantic impact on
+ // include paths.
+ for (; It < End &&
+ Matches(*It, {frontend::After, frontend::Angled}, false, true);
+ ++It) {
+ OptSpecifier Opt =
+ It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore;
+ GenerateArg(Args, Opt, It->Path, SA);
+ }
+
+ // Note: Some paths that came from "-idirafter=xxyy" may have already been
+ // generated as "-iwithprefix=xxyy". If that's the case, their position on
+ // command line was such that this has no semantic impact on include paths.
+ for (; It < End && Matches(*It, {frontend::After}, false, true); ++It)
+ GenerateArg(Args, OPT_idirafter, It->Path, SA);
+ for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It)
+ GenerateArg(Args, OPT_iquote, It->Path, SA);
+ for (; It < End && Matches(*It, {frontend::System}, false, None); ++It)
+ GenerateArg(Args, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot,
+ It->Path, SA);
+ for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
+ GenerateArg(Args, OPT_iframework, It->Path, SA);
+ for (; It < End && Matches(*It, {frontend::System}, true, false); ++It)
+ GenerateArg(Args, OPT_iframeworkwithsysroot, It->Path, SA);
+
+ // Add the paths for the various language specific isystem flags.
+ for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It)
+ GenerateArg(Args, OPT_c_isystem, It->Path, SA);
+ for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It)
+ GenerateArg(Args, OPT_cxx_isystem, It->Path, SA);
+ for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It)
+ GenerateArg(Args, OPT_objc_isystem, It->Path, SA);
+ for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It)
+ GenerateArg(Args, OPT_objcxx_isystem, It->Path, SA);
+
+ // Add the internal paths from a driver that detects standard include paths.
+ // Note: Some paths that came from "-internal-isystem" arguments may have
+ // already been generated as "-isystem". If that's the case, their position on
+ // command line was such that this has no semantic impact on include paths.
+ for (; It < End &&
+ Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true);
+ ++It) {
+ OptSpecifier Opt = It->Group == frontend::System
+ ? OPT_internal_isystem
+ : OPT_internal_externc_isystem;
+ GenerateArg(Args, Opt, It->Path, SA);
+ }
+
+ assert(It == End && "Unhandled HeaderSearchOption::Entry.");
+
+ // Add the path prefixes which are implicitly treated as being system headers.
+ for (const auto &P : Opts.SystemHeaderPrefixes) {
+ OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix
+ : OPT_no_system_header_prefix;
+ GenerateArg(Args, Opt, P.Prefix, SA);
+ }
+
+ for (const std::string &F : Opts.VFSOverlayFiles)
+ GenerateArg(Args, OPT_ivfsoverlay, F, SA);
+}
+
+static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
+ DiagnosticsEngine &Diags,
const std::string &WorkingDir) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ HeaderSearchOptions *HeaderSearchOpts = &Opts;
+
+#define HEADER_SEARCH_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING
+
if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
@@ -1935,6 +3060,8 @@
for (const auto *A : Args.filtered(OPT_ivfsoverlay))
Opts.AddVFSOverlayFile(A->getValue());
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
@@ -1961,7 +3088,10 @@
case Language::LLVM_IR:
llvm_unreachable("Invalid input kind!");
case Language::OpenCL:
- LangStd = LangStandard::lang_opencl10;
+ LangStd = LangStandard::lang_opencl12;
+ break;
+ case Language::OpenCLCXX:
+ LangStd = LangStandard::lang_openclcpp;
break;
case Language::CUDA:
LangStd = LangStandard::lang_cuda;
@@ -2020,6 +3150,8 @@
Opts.HexFloats = Std.hasHexFloats();
Opts.ImplicitInt = Std.hasImplicitInt();
+ Opts.CPlusPlusModules = Opts.CPlusPlus20;
+
// Set OpenCL Version.
Opts.OpenCL = Std.isOpenCL();
if (LangStd == LangStandard::lang_opencl10)
@@ -2041,6 +3173,9 @@
Opts.ZVector = 0;
Opts.setDefaultFPContractMode(LangOptions::FPM_On);
Opts.OpenCLCPlusPlus = Opts.CPlusPlus;
+ Opts.OpenCLPipes = Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200;
+ Opts.OpenCLGenericAddressSpace =
+ Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200;
// Include default header file for OpenCL.
if (Opts.IncludeDefaultHeader) {
@@ -2077,18 +3212,6 @@
// OpenCL has half keyword
Opts.Half = Opts.OpenCL;
-
- // C++ has wchar_t keyword.
- Opts.WChar = Opts.CPlusPlus;
-
- Opts.CXXOperatorNames = Opts.CPlusPlus;
-
- Opts.AlignedAllocation = Opts.CPlusPlus17;
-
- Opts.DollarIdents = !Opts.AsmPreprocessor;
-
- // Enable [[]] attributes in C++11 and C2x by default.
- Opts.DoubleSquareBracketAttributes = Opts.CPlusPlus11 || Opts.C2x;
}
/// Check if input file kind and language standard are compatible.
@@ -2105,7 +3228,11 @@
return S.getLanguage() == Language::C;
case Language::OpenCL:
- return S.getLanguage() == Language::OpenCL;
+ return S.getLanguage() == Language::OpenCL ||
+ S.getLanguage() == Language::OpenCLCXX;
+
+ case Language::OpenCLCXX:
+ return S.getLanguage() == Language::OpenCLCXX;
case Language::CXX:
case Language::ObjCXX:
@@ -2142,6 +3269,8 @@
return "Objective-C++";
case Language::OpenCL:
return "OpenCL";
+ case Language::OpenCLCXX:
+ return "C++ for OpenCL";
case Language::CUDA:
return "CUDA";
case Language::RenderScript:
@@ -2160,19 +3289,276 @@
llvm_unreachable("unknown input language");
}
-static void GenerateLangArgs(const LangOptions &Opts,
- SmallVectorImpl<const char *> &Args,
- CompilerInvocation::StringAllocator SA) {
+void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ StringAllocator SA,
+ const llvm::Triple &T, InputKind IK) {
+ if (IK.getFormat() == InputKind::Precompiled ||
+ IK.getLanguage() == Language::LLVM_IR) {
+ if (Opts.ObjCAutoRefCount)
+ GenerateArg(Args, OPT_fobjc_arc, SA);
+ if (Opts.PICLevel != 0)
+ GenerateArg(Args, OPT_pic_level, Twine(Opts.PICLevel), SA);
+ if (Opts.PIE)
+ GenerateArg(Args, OPT_pic_is_pie, SA);
+ for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
+ GenerateArg(Args, OPT_fsanitize_EQ, Sanitizer, SA);
+
+ return;
+ }
+
+ OptSpecifier StdOpt;
+ switch (Opts.LangStd) {
+ case LangStandard::lang_opencl10:
+ case LangStandard::lang_opencl11:
+ case LangStandard::lang_opencl12:
+ case LangStandard::lang_opencl20:
+ case LangStandard::lang_opencl30:
+ case LangStandard::lang_openclcpp:
+ StdOpt = OPT_cl_std_EQ;
+ break;
+ default:
+ StdOpt = OPT_std_EQ;
+ break;
+ }
+
+ auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd);
+ GenerateArg(Args, StdOpt, LangStandard.getName(), SA);
+
if (Opts.IncludeDefaultHeader)
- Args.push_back(SA(GetOptName(OPT_finclude_default_header)));
+ GenerateArg(Args, OPT_finclude_default_header, SA);
if (Opts.DeclareOpenCLBuiltins)
- Args.push_back(SA(GetOptName(OPT_fdeclare_opencl_builtins)));
+ GenerateArg(Args, OPT_fdeclare_opencl_builtins, SA);
+
+ const LangOptions *LangOpts = &Opts;
+
+#define LANG_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef LANG_OPTION_WITH_MARSHALLING
+
+ // The '-fcf-protection=' option is generated by CodeGenOpts generator.
+
+ if (Opts.ObjC) {
+ GenerateArg(Args, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString(), SA);
+
+ if (Opts.GC == LangOptions::GCOnly)
+ GenerateArg(Args, OPT_fobjc_gc_only, SA);
+ else if (Opts.GC == LangOptions::HybridGC)
+ GenerateArg(Args, OPT_fobjc_gc, SA);
+ else if (Opts.ObjCAutoRefCount == 1)
+ GenerateArg(Args, OPT_fobjc_arc, SA);
+
+ if (Opts.ObjCWeakRuntime)
+ GenerateArg(Args, OPT_fobjc_runtime_has_weak, SA);
+
+ if (Opts.ObjCWeak)
+ GenerateArg(Args, OPT_fobjc_weak, SA);
+
+ if (Opts.ObjCSubscriptingLegacyRuntime)
+ GenerateArg(Args, OPT_fobjc_subscripting_legacy_runtime, SA);
+ }
+
+ if (Opts.GNUCVersion != 0) {
+ unsigned Major = Opts.GNUCVersion / 100 / 100;
+ unsigned Minor = (Opts.GNUCVersion / 100) % 100;
+ unsigned Patch = Opts.GNUCVersion % 100;
+ GenerateArg(Args, OPT_fgnuc_version_EQ,
+ Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch), SA);
+ }
+
+ if (Opts.IgnoreXCOFFVisibility)
+ GenerateArg(Args, OPT_mignore_xcoff_visibility, SA);
+
+ if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {
+ GenerateArg(Args, OPT_ftrapv, SA);
+ GenerateArg(Args, OPT_ftrapv_handler, Opts.OverflowHandler, SA);
+ } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
+ GenerateArg(Args, OPT_fwrapv, SA);
+ }
+
+ if (Opts.MSCompatibilityVersion != 0) {
+ unsigned Major = Opts.MSCompatibilityVersion / 10000000;
+ unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;
+ unsigned Subminor = Opts.MSCompatibilityVersion % 100000;
+ GenerateArg(Args, OPT_fms_compatibility_version,
+ Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor), SA);
+ }
+
+ if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17) || T.isOSzOS()) {
+ if (!Opts.Trigraphs)
+ GenerateArg(Args, OPT_fno_trigraphs, SA);
+ } else {
+ if (Opts.Trigraphs)
+ GenerateArg(Args, OPT_ftrigraphs, SA);
+ }
+
+ if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
+ GenerateArg(Args, OPT_fblocks, SA);
+
+ if (Opts.ConvergentFunctions &&
+ !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice))
+ GenerateArg(Args, OPT_fconvergent_functions, SA);
+
+ if (Opts.NoBuiltin && !Opts.Freestanding)
+ GenerateArg(Args, OPT_fno_builtin, SA);
+
+ if (!Opts.NoBuiltin)
+ for (const auto &Func : Opts.NoBuiltinFuncs)
+ GenerateArg(Args, OPT_fno_builtin_, Func, SA);
+
+ if (Opts.LongDoubleSize == 128)
+ GenerateArg(Args, OPT_mlong_double_128, SA);
+ else if (Opts.LongDoubleSize == 64)
+ GenerateArg(Args, OPT_mlong_double_64, SA);
+
+ // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.
+
+ // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or
+ // '-fopenmp-targets='.
+ if (Opts.OpenMP && !Opts.OpenMPSimd) {
+ GenerateArg(Args, OPT_fopenmp, SA);
+
+ if (Opts.OpenMP != 50)
+ GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA);
+
+ if (!Opts.OpenMPUseTLS)
+ GenerateArg(Args, OPT_fnoopenmp_use_tls, SA);
+
+ if (Opts.OpenMPIsDevice)
+ GenerateArg(Args, OPT_fopenmp_is_device, SA);
+
+ if (Opts.OpenMPIRBuilder)
+ GenerateArg(Args, OPT_fopenmp_enable_irbuilder, SA);
+ }
+
+ if (Opts.OpenMPSimd) {
+ GenerateArg(Args, OPT_fopenmp_simd, SA);
+
+ if (Opts.OpenMP != 50)
+ GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA);
+ }
+
+ if (Opts.OpenMPCUDANumSMs != 0)
+ GenerateArg(Args, OPT_fopenmp_cuda_number_of_sm_EQ,
+ Twine(Opts.OpenMPCUDANumSMs), SA);
+
+ if (Opts.OpenMPCUDABlocksPerSM != 0)
+ GenerateArg(Args, OPT_fopenmp_cuda_blocks_per_sm_EQ,
+ Twine(Opts.OpenMPCUDABlocksPerSM), SA);
+
+ if (Opts.OpenMPCUDAReductionBufNum != 1024)
+ GenerateArg(Args, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,
+ Twine(Opts.OpenMPCUDAReductionBufNum), SA);
+
+ if (!Opts.OMPTargetTriples.empty()) {
+ std::string Targets;
+ llvm::raw_string_ostream OS(Targets);
+ llvm::interleave(
+ Opts.OMPTargetTriples, OS,
+ [&OS](const llvm::Triple &T) { OS << T.str(); }, ",");
+ GenerateArg(Args, OPT_fopenmp_targets_EQ, OS.str(), SA);
+ }
+
+ if (!Opts.OMPHostIRFile.empty())
+ GenerateArg(Args, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile, SA);
+
+ if (Opts.OpenMPCUDAMode)
+ GenerateArg(Args, OPT_fopenmp_cuda_mode, SA);
+
+ if (Opts.OpenMPCUDAForceFullRuntime)
+ GenerateArg(Args, OPT_fopenmp_cuda_force_full_runtime, SA);
+
+ // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are
+ // generated from CodeGenOptions.
+
+ if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)
+ GenerateArg(Args, OPT_ffp_contract, "fast", SA);
+ else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)
+ GenerateArg(Args, OPT_ffp_contract, "on", SA);
+ else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)
+ GenerateArg(Args, OPT_ffp_contract, "off", SA);
+ else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)
+ GenerateArg(Args, OPT_ffp_contract, "fast-honor-pragmas", SA);
+
+ for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))
+ GenerateArg(Args, OPT_fsanitize_EQ, Sanitizer, SA);
+
+ // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'.
+ for (const std::string &F : Opts.NoSanitizeFiles)
+ GenerateArg(Args, OPT_fsanitize_ignorelist_EQ, F, SA);
+
+ if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver3_8)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "3.8", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver4)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "4.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver6)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "6.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver7)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "7.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver9)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "9.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver11)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "11.0", SA);
+ else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver12)
+ GenerateArg(Args, OPT_fclang_abi_compat_EQ, "12.0", SA);
+
+ if (Opts.getSignReturnAddressScope() ==
+ LangOptions::SignReturnAddressScopeKind::All)
+ GenerateArg(Args, OPT_msign_return_address_EQ, "all", SA);
+ else if (Opts.getSignReturnAddressScope() ==
+ LangOptions::SignReturnAddressScopeKind::NonLeaf)
+ GenerateArg(Args, OPT_msign_return_address_EQ, "non-leaf", SA);
+
+ if (Opts.getSignReturnAddressKey() ==
+ LangOptions::SignReturnAddressKeyKind::BKey)
+ GenerateArg(Args, OPT_msign_return_address_key_EQ, "b_key", SA);
+
+ if (Opts.CXXABI)
+ GenerateArg(Args, OPT_fcxx_abi_EQ, TargetCXXABI::getSpelling(*Opts.CXXABI),
+ SA);
+
+ if (Opts.RelativeCXXABIVTables)
+ GenerateArg(Args, OPT_fexperimental_relative_cxx_abi_vtables, SA);
+ else
+ GenerateArg(Args, OPT_fno_experimental_relative_cxx_abi_vtables, SA);
+
+ for (const auto &MP : Opts.MacroPrefixMap)
+ GenerateArg(Args, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second, SA);
}
-void CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
+bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
InputKind IK, const llvm::Triple &T,
std::vector<std::string> &Includes,
DiagnosticsEngine &Diags) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ if (IK.getFormat() == InputKind::Precompiled ||
+ IK.getLanguage() == Language::LLVM_IR) {
+ // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
+ // PassManager in BackendUtil.cpp. They need to be initialized no matter
+ // what the input type is.
+ if (Args.hasArg(OPT_fobjc_arc))
+ Opts.ObjCAutoRefCount = 1;
+ // PICLevel and PIELevel are needed during code generation and this should
+ // be set regardless of the input type.
+ Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
+ Opts.PIE = Args.hasArg(OPT_pic_is_pie);
+ parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
+ Diags, Opts.Sanitize);
+
+ return Diags.getNumErrors() == NumErrorsBefore;
+ }
+
+ // Other LangOpts are only initialized when the input is not AST or LLVM IR.
+ // FIXME: Should we really be parsing this for an Language::Asm input?
+
// FIXME: Cleanup per-file based stuff.
LangStandard::Kind LangStd = LangStandard::lang_unspecified;
if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
@@ -2245,17 +3631,15 @@
// The key paths of codegen options defined in Options.td start with
// "LangOpts->". Let's provide the expected variable name and type.
LangOptions *LangOpts = &Opts;
- bool Success = true;
#define LANG_OPTION_WITH_MARSHALLING( \
PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
MERGER, EXTRACTOR, TABLE_INDEX) \
- PARSE_OPTION_WITH_MARSHALLING(Args, Diags, Success, ID, FLAGS, PARAM, \
- SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
- IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \
- MERGER, TABLE_INDEX)
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
#include "clang/Driver/Options.inc"
#undef LANG_OPTION_WITH_MARSHALLING
@@ -2266,8 +3650,15 @@
}
}
- if (Args.hasArg(OPT_fno_operator_names))
- Opts.CXXOperatorNames = 0;
+ if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&
+ !Args.hasArg(OPT_sycl_std_EQ)) {
+ // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to
+ // provide -sycl-std=, we want to default it to whatever the default SYCL
+ // version is. I could not find a way to express this with the options
+ // tablegen because we still want this value to be SYCL_None when the user
+ // is not in device or host mode.
+ Opts.setSYCLVersion(LangOptions::SYCL_Default);
+ }
if (Opts.ObjC) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
@@ -2331,6 +3722,30 @@
Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch;
}
+ // In AIX OS, the -mignore-xcoff-visibility is enable by default if there is
+ // no -fvisibility=* option.
+ // This is the reason why '-fvisibility' needs to be always generated:
+ // its absence implies '-mignore-xcoff-visibility'.
+ //
+ // Suppose the original cc1 command line does contain '-fvisibility default':
+ // '-mignore-xcoff-visibility' should not be implied.
+ // * If '-fvisibility' is not generated (as most options with default values
+ // don't), its absence would imply '-mignore-xcoff-visibility'. This changes
+ // the command line semantics.
+ // * If '-fvisibility' is generated regardless of its presence and value,
+ // '-mignore-xcoff-visibility' won't be implied and the command line
+ // semantics are kept intact.
+ //
+ // When the original cc1 command line does **not** contain '-fvisibility',
+ // '-mignore-xcoff-visibility' is implied. The generated command line will
+ // contain both '-fvisibility default' and '-mignore-xcoff-visibility' and
+ // subsequent calls to `CreateFromArgs`/`generateCC1CommandLine` will always
+ // produce the same arguments.
+
+ if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility) ||
+ !Args.hasArg(OPT_fvisibility)))
+ Opts.IgnoreXCOFFVisibility = 1;
+
if (Args.hasArg(OPT_ftrapv)) {
Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
// Set the handler, if one is specified.
@@ -2340,8 +3755,6 @@
else if (Args.hasArg(OPT_fwrapv))
Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
- Opts.MicrosoftExt = Opts.MSVCCompat || Args.hasArg(OPT_fms_extensions);
- Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt;
Opts.MSCompatibilityVersion = 0;
if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
VersionTuple VT;
@@ -2362,89 +3775,23 @@
Opts.Trigraphs =
Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
- Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
- OPT_fno_dollars_in_identifiers,
- Opts.DollarIdents);
-
- // -ffixed-point
- Opts.FixedPoint =
- Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) &&
- !Opts.CPlusPlus;
- Opts.PaddingOnUnsignedFixedPoint =
- Args.hasFlag(OPT_fpadding_on_unsigned_fixed_point,
- OPT_fno_padding_on_unsigned_fixed_point,
- /*Default=*/false) &&
- Opts.FixedPoint;
-
- Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti);
- Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data);
Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
&& Opts.OpenCLVersion == 200);
- Opts.Coroutines = Opts.CPlusPlus20 || Args.hasArg(OPT_fcoroutines_ts);
Opts.ConvergentFunctions = Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) ||
Opts.SYCLIsDevice ||
Args.hasArg(OPT_fconvergent_functions);
- Opts.DoubleSquareBracketAttributes =
- Args.hasFlag(OPT_fdouble_square_bracket_attributes,
- OPT_fno_double_square_bracket_attributes,
- Opts.DoubleSquareBracketAttributes);
-
- Opts.CPlusPlusModules = Opts.CPlusPlus20;
- Opts.Modules =
- Args.hasArg(OPT_fmodules) || Opts.ModulesTS || Opts.CPlusPlusModules;
- Opts.ModulesDeclUse =
- Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
- // FIXME: We only need this in C++ modules / Modules TS if we might textually
- // enter a different module (eg, when building a header unit).
- Opts.ModulesLocalVisibility =
- Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS ||
- Opts.CPlusPlusModules;
- Opts.ModulesSearchAll = Opts.Modules &&
- !Args.hasArg(OPT_fno_modules_search_all) &&
- Args.hasArg(OPT_fmodules_search_all);
- Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
- Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
- Opts.Char8 = Args.hasFlag(OPT_fchar8__t, OPT_fno_char8__t, Opts.CPlusPlus20);
Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
if (!Opts.NoBuiltin)
getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
- Opts.AlignedAllocation =
- Args.hasFlag(OPT_faligned_allocation, OPT_fno_aligned_allocation,
- Opts.AlignedAllocation);
- Opts.AlignedAllocationUnavailable =
- Opts.AlignedAllocation && Args.hasArg(OPT_aligned_alloc_unavailable);
- if (Args.hasArg(OPT_fconcepts_ts))
- Diags.Report(diag::warn_fe_concepts_ts_flag);
- Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno);
Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128)
? 128
: Args.hasArg(OPT_mlong_double_64) ? 64 : 0;
- Opts.EnableAIXExtendedAltivecABI = Args.hasArg(OPT_mabi_EQ_vec_extabi);
- Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
- Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple
- || Args.hasArg(OPT_fdump_record_layouts);
if (Opts.FastRelaxedMath)
Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
- Opts.XLPragmaPack = Args.hasArg(OPT_fxl_pragma_pack);
llvm::sort(Opts.ModuleFeatures);
- Opts.ArmSveVectorBits =
- getLastArgIntValue(Args, options::OPT_msve_vector_bits_EQ, 0, Diags);
-
- // __declspec is enabled by default for the PS4 by the driver, and also
- // enabled for Microsoft Extensions or Borland Extensions, here.
- //
- // FIXME: __declspec is also currently enabled for CUDA, but isn't really a
- // CUDA extension. However, it is required for supporting
- // __clang_cuda_builtin_vars.h, which uses __declspec(property). Once that has
- // been rewritten in terms of something more generic, remove the Opts.CUDA
- // term here.
- Opts.DeclSpecKeyword =
- Args.hasFlag(OPT_fdeclspec, OPT_fno_declspec,
- (Opts.MicrosoftExt || Opts.Borland || Opts.CUDA));
-
// -mrtd option
if (Arg *A = Args.getLastArg(OPT_mrtd)) {
if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)
@@ -2459,6 +3806,8 @@
}
}
+ // Check if -fopenmp is specified and set default version to 5.0.
+ Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 50 : 0;
// Check if -fopenmp-simd is specified.
bool IsSimdSpecified =
Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,
@@ -2558,22 +3907,11 @@
Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && (T.isNVPTX() || T.isAMDGCN()) &&
Args.hasArg(options::OPT_fopenmp_cuda_mode);
- // Set CUDA support for parallel execution of target regions for OpenMP target
- // NVPTX/AMDGCN if specified in options.
- Opts.OpenMPCUDATargetParallel =
- Opts.OpenMPIsDevice && (T.isNVPTX() || T.isAMDGCN()) &&
- Args.hasArg(options::OPT_fopenmp_cuda_parallel_target_regions);
-
// Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options
Opts.OpenMPCUDAForceFullRuntime =
Opts.OpenMPIsDevice && (T.isNVPTX() || T.isAMDGCN()) &&
Args.hasArg(options::OPT_fopenmp_cuda_force_full_runtime);
- // Record whether the __DEPRECATED define was requested.
- Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro,
- OPT_fno_deprecated_macro,
- Opts.Deprecated);
-
// FIXME: Eliminate this dependency.
unsigned Opt = getOptimizationLevel(Args, IK, Diags),
OptSize = getOptimizationLevelSize(Args);
@@ -2604,28 +3942,15 @@
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
}
- LangOptions::FPExceptionModeKind FPEB = LangOptions::FPE_Ignore;
- if (Arg *A = Args.getLastArg(OPT_ffp_exception_behavior_EQ)) {
- StringRef Val = A->getValue();
- if (Val.equals("ignore"))
- FPEB = LangOptions::FPE_Ignore;
- else if (Val.equals("maytrap"))
- FPEB = LangOptions::FPE_MayTrap;
- else if (Val.equals("strict"))
- FPEB = LangOptions::FPE_Strict;
- else
- Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
- }
- Opts.setFPExceptionMode(FPEB);
-
// Parse -fsanitize= arguments.
parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
Diags, Opts.Sanitize);
- std::vector<std::string> systemBlacklists =
- Args.getAllArgValues(OPT_fsanitize_system_blacklist);
- Opts.SanitizerBlacklistFiles.insert(Opts.SanitizerBlacklistFiles.end(),
- systemBlacklists.begin(),
- systemBlacklists.end());
+ Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ);
+ std::vector<std::string> systemIgnorelists =
+ Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ);
+ Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(),
+ systemIgnorelists.begin(),
+ systemIgnorelists.end());
if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
Opts.setClangABICompat(LangOptions::ClangABI::Latest);
@@ -2656,6 +3981,8 @@
Opts.setClangABICompat(LangOptions::ClangABI::Ver9);
else if (Major <= 11)
Opts.setClangABICompat(LangOptions::ClangABI::Ver11);
+ else if (Major <= 12)
+ Opts.setClangABICompat(LangOptions::ClangABI::Ver12);
} else if (Ver != "latest") {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
@@ -2665,13 +3992,13 @@
if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {
StringRef SignScope = A->getValue();
- if (SignScope.equals_lower("none"))
+ if (SignScope.equals_insensitive("none"))
Opts.setSignReturnAddressScope(
LangOptions::SignReturnAddressScopeKind::None);
- else if (SignScope.equals_lower("all"))
+ else if (SignScope.equals_insensitive("all"))
Opts.setSignReturnAddressScope(
LangOptions::SignReturnAddressScopeKind::All);
- else if (SignScope.equals_lower("non-leaf"))
+ else if (SignScope.equals_insensitive("non-leaf"))
Opts.setSignReturnAddressScope(
LangOptions::SignReturnAddressScopeKind::NonLeaf);
else
@@ -2681,10 +4008,10 @@
if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {
StringRef SignKey = A->getValue();
if (!SignScope.empty() && !SignKey.empty()) {
- if (SignKey.equals_lower("a_key"))
+ if (SignKey.equals_insensitive("a_key"))
Opts.setSignReturnAddressKey(
LangOptions::SignReturnAddressKeyKind::AKey);
- else if (SignKey.equals_lower("b_key"))
+ else if (SignKey.equals_insensitive("b_key"))
Opts.setSignReturnAddressKey(
LangOptions::SignReturnAddressKeyKind::BKey);
else
@@ -2694,15 +4021,32 @@
}
}
- std::string ThreadModel =
- std::string(Args.getLastArgValue(OPT_mthread_model, "posix"));
- if (ThreadModel != "posix" && ThreadModel != "single")
- Diags.Report(diag::err_drv_invalid_value)
- << Args.getLastArg(OPT_mthread_model)->getAsString(Args) << ThreadModel;
- Opts.setThreadModel(
- llvm::StringSwitch<LangOptions::ThreadModelKind>(ThreadModel)
- .Case("posix", LangOptions::ThreadModelKind::POSIX)
- .Case("single", LangOptions::ThreadModelKind::Single));
+ // The value can be empty, which indicates the system default should be used.
+ StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ);
+ if (!CXXABI.empty()) {
+ if (!TargetCXXABI::isABI(CXXABI)) {
+ Diags.Report(diag::err_invalid_cxx_abi) << CXXABI;
+ } else {
+ auto Kind = TargetCXXABI::getKind(CXXABI);
+ if (!TargetCXXABI::isSupportedCXXABI(T, Kind))
+ Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str();
+ else
+ Opts.CXXABI = Kind;
+ }
+ }
+
+ Opts.RelativeCXXABIVTables =
+ Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
+ options::OPT_fno_experimental_relative_cxx_abi_vtables,
+ TargetCXXABI::usesRelativeVTables(T));
+
+ for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
+ auto Split = StringRef(A).split('=');
+ Opts.MacroPrefixMap.insert(
+ {std::string(Split.first), std::string(Split.second)});
+ }
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
@@ -2749,21 +4093,99 @@
llvm_unreachable("invalid frontend action");
}
-static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
+static void GeneratePreprocessorArgs(PreprocessorOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA,
+ const LangOptions &LangOpts,
+ const FrontendOptions &FrontendOpts,
+ const CodeGenOptions &CodeGenOpts) {
+ PreprocessorOptions *PreprocessorOpts = &Opts;
+
+#define PREPROCESSOR_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef PREPROCESSOR_OPTION_WITH_MARSHALLING
+
+ if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate)
+ GenerateArg(Args, OPT_pch_through_hdrstop_use, SA);
+
+ for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)
+ GenerateArg(Args, OPT_error_on_deserialized_pch_decl, D, SA);
+
+ if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))
+ GenerateArg(Args, OPT_preamble_bytes_EQ,
+ Twine(Opts.PrecompiledPreambleBytes.first) + "," +
+ (Opts.PrecompiledPreambleBytes.second ? "1" : "0"),
+ SA);
+
+ for (const auto &M : Opts.Macros) {
+ // Don't generate __CET__ macro definitions. They are implied by the
+ // -fcf-protection option that is generated elsewhere.
+ if (M.first == "__CET__=1" && !M.second &&
+ !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch)
+ continue;
+ if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn &&
+ !CodeGenOpts.CFProtectionBranch)
+ continue;
+ if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn &&
+ CodeGenOpts.CFProtectionBranch)
+ continue;
+
+ GenerateArg(Args, M.second ? OPT_U : OPT_D, M.first, SA);
+ }
+
+ for (const auto &I : Opts.Includes) {
+ // Don't generate OpenCL includes. They are implied by other flags that are
+ // generated elsewhere.
+ if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader &&
+ ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") ||
+ I == "opencl-c.h"))
+ continue;
+
+ GenerateArg(Args, OPT_include, I, SA);
+ }
+
+ for (const auto &CI : Opts.ChainedIncludes)
+ GenerateArg(Args, OPT_chain_include, CI, SA);
+
+ for (const auto &RF : Opts.RemappedFiles)
+ GenerateArg(Args, OPT_remap_file, RF.first + ";" + RF.second, SA);
+
+ // Don't handle LexEditorPlaceholders. It is implied by the action that is
+ // generated elsewhere.
+}
+
+static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags,
- frontend::ActionKind Action) {
+ frontend::ActionKind Action,
+ const FrontendOptions &FrontendOpts) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ PreprocessorOptions *PreprocessorOpts = &Opts;
+
+#define PREPROCESSOR_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef PREPROCESSOR_OPTION_WITH_MARSHALLING
+
Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||
Args.hasArg(OPT_pch_through_hdrstop_use);
for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());
- for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {
- auto Split = StringRef(A).split('=');
- Opts.MacroPrefixMap.insert(
- {std::string(Split.first), std::string(Split.second)});
- }
-
if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
StringRef Value(A->getValue());
size_t Comma = Value.find(',');
@@ -2822,21 +4244,94 @@
// "editor placeholder in source file" error in PP only mode.
if (isStrictlyPreprocessorAction(Action))
Opts.LexEditorPlaceholders = false;
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
-static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
- ArgList &Args,
+static void GeneratePreprocessorOutputArgs(
+ const PreprocessorOutputOptions &Opts, SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA, frontend::ActionKind Action) {
+ const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
+
+#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
+
+ bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP;
+ if (Generate_dM)
+ GenerateArg(Args, OPT_dM, SA);
+ if (!Generate_dM && Opts.ShowMacros)
+ GenerateArg(Args, OPT_dD, SA);
+}
+
+static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
+ ArgList &Args, DiagnosticsEngine &Diags,
frontend::ActionKind Action) {
- if (isStrictlyPreprocessorAction(Action))
- Opts.ShowCPP = !Args.hasArg(OPT_dM);
- else
- Opts.ShowCPP = 0;
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+ PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;
+
+#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING
+
+ Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);
Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
-static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
+static void GenerateTargetArgs(const TargetOptions &Opts,
+ SmallVectorImpl<const char *> &Args,
+ CompilerInvocation::StringAllocator SA) {
+ const TargetOptions *TargetOpts = &Opts;
+#define TARGET_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ GENERATE_OPTION_WITH_MARSHALLING( \
+ Args, SA, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef TARGET_OPTION_WITH_MARSHALLING
+
+ if (!Opts.SDKVersion.empty())
+ GenerateArg(Args, OPT_target_sdk_version_EQ, Opts.SDKVersion.getAsString(),
+ SA);
+}
+
+static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
DiagnosticsEngine &Diags) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
+
+ TargetOptions *TargetOpts = &Opts;
+
+#define TARGET_OPTION_WITH_MARSHALLING( \
+ PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
+ DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
+ MERGER, EXTRACTOR, TABLE_INDEX) \
+ PARSE_OPTION_WITH_MARSHALLING( \
+ Args, Diags, ID, FLAGS, PARAM, SHOULD_PARSE, KEYPATH, DEFAULT_VALUE, \
+ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, MERGER, TABLE_INDEX)
+#include "clang/Driver/Options.inc"
+#undef TARGET_OPTION_WITH_MARSHALLING
+
if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {
llvm::VersionTuple Version;
if (Version.tryParse(A->getValue()))
@@ -2845,13 +4340,14 @@
else
Opts.SDKVersion = Version;
}
+
+ return Diags.getNumErrors() == NumErrorsBefore;
}
-bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
- ArrayRef<const char *> CommandLineArgs,
- DiagnosticsEngine &Diags,
- const char *Argv0) {
- bool Success = true;
+bool CompilerInvocation::CreateFromArgsImpl(
+ CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,
+ DiagnosticsEngine &Diags, const char *Argv0) {
+ unsigned NumErrorsBefore = Diags.getNumErrors();
// Parse the arguments.
const OptTable &Opts = getDriverOptTable();
@@ -2862,11 +4358,9 @@
LangOptions &LangOpts = *Res.getLangOpts();
// Check for missing argument error.
- if (MissingArgCount) {
+ if (MissingArgCount)
Diags.Report(diag::err_drv_missing_argument)
<< Args.getArgString(MissingArgIndex) << MissingArgCount;
- Success = false;
- }
// Issue errors on unknown arguments.
for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
@@ -2877,54 +4371,25 @@
else
Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
<< ArgString << Nearest;
- Success = false;
}
- Success &= Res.parseSimpleArgs(Args, Diags);
-
- Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
- ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args);
- if (!Res.getDependencyOutputOpts().OutputFile.empty() &&
- Res.getDependencyOutputOpts().Targets.empty()) {
- Diags.Report(diag::err_fe_dependency_file_requires_MT);
- Success = false;
- }
- Success &= ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
- /*DefaultDiagColor=*/false);
+ ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);
+ ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);
+ ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
+ ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
+ /*DefaultDiagColor=*/false);
+ ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);
// FIXME: We shouldn't have to pass the DashX option around here
- InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags,
- LangOpts.IsHeaderFile);
+ InputKind DashX = Res.getFrontendOpts().DashX;
ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
llvm::Triple T(Res.getTargetOpts().Triple);
- ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args,
+ ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,
Res.getFileSystemOpts().WorkingDir);
- if (DashX.getFormat() == InputKind::Precompiled ||
- DashX.getLanguage() == Language::LLVM_IR) {
- // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
- // PassManager in BackendUtil.cpp. They need to be initializd no matter
- // what the input type is.
- if (Args.hasArg(OPT_fobjc_arc))
- LangOpts.ObjCAutoRefCount = 1;
- // PIClevel and PIELevel are needed during code generation and this should be
- // set regardless of the input type.
- LangOpts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
- LangOpts.PIE = Args.hasArg(OPT_pic_is_pie);
- parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
- Diags, LangOpts.Sanitize);
- } else {
- // Other LangOpts are only initialized when the input is not AST or LLVM IR.
- // FIXME: Should we really be calling this for an Language::Asm input?
- ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
- Diags);
- if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
- LangOpts.ObjCExceptions = 1;
- if (T.isOSDarwin() && DashX.isPreprocessed()) {
- // Supress the darwin-specific 'stdlibcxx-not-found' diagnostic for
- // preprocessed input as we don't expect it to be used with -std=libc++
- // anyway.
- Res.getDiagnosticOpts().Warnings.push_back("no-stdlibcxx-not-found");
- }
- }
+
+ ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,
+ Diags);
+ if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
+ LangOpts.ObjCExceptions = 1;
if (LangOpts.CUDA) {
// During CUDA device-side compilation, the aux triple is the
@@ -2937,8 +4402,8 @@
if (LangOpts.OpenMPIsDevice)
Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
- Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
- Res.getFrontendOpts().OutputFile, LangOpts);
+ ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,
+ Res.getFrontendOpts().OutputFile, LangOpts);
// FIXME: Override value name discarding when asan or msan is used because the
// backend passes depend on the name of the alloca in order to print out
@@ -2950,13 +4415,17 @@
!LangOpts.Sanitize.has(SanitizerKind::KernelMemory);
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,
- Res.getFrontendOpts().ProgramAction);
- ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
+ Res.getFrontendOpts().ProgramAction,
+ Res.getFrontendOpts());
+ ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Diags,
Res.getFrontendOpts().ProgramAction);
- // Turn on -Wspir-compat for SPIR target.
- if (T.isSPIR())
- Res.getDiagnosticOpts().Warnings.push_back("spir-compat");
+ ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args, Diags,
+ Res.getFrontendOpts().ProgramAction,
+ Res.getPreprocessorOutputOpts().ShowLineMarkers);
+ if (!Res.getDependencyOutputOpts().OutputFile.empty() &&
+ Res.getDependencyOutputOpts().Targets.empty())
+ Diags.Report(diag::err_fe_dependency_file_requires_MT);
// If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
@@ -2971,7 +4440,23 @@
FixupInvocation(Res, Diags, Args, DashX);
- return Success;
+ return Diags.getNumErrors() == NumErrorsBefore;
+}
+
+bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Invocation,
+ ArrayRef<const char *> CommandLineArgs,
+ DiagnosticsEngine &Diags,
+ const char *Argv0) {
+ CompilerInvocation DummyInvocation;
+
+ return RoundTrip(
+ [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,
+ DiagnosticsEngine &Diags, const char *Argv0) {
+ return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);
+ },
+ [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,
+ StringAllocator SA) { Invocation.generateCC1CommandLine(Args, SA); },
+ Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0);
}
std::string CompilerInvocation::getModuleHash() const {
@@ -3084,51 +4569,28 @@
if (!SanHash.empty())
code = hash_combine(code, SanHash.Mask);
- return llvm::APInt(64, code).toString(36, /*Signed=*/false);
+ return toString(llvm::APInt(64, code), 36, /*Signed=*/false);
}
void CompilerInvocation::generateCC1CommandLine(
SmallVectorImpl<const char *> &Args, StringAllocator SA) const {
- // Capture the extracted value as a lambda argument to avoid potential issues
- // with lifetime extension of the reference.
-#define GENERATE_OPTION_WITH_MARSHALLING( \
- ARGS, STRING_ALLOCATOR, KIND, FLAGS, SPELLING, ALWAYS_EMIT, KEYPATH, \
- DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, EXTRACTOR, \
- TABLE_INDEX) \
- if ((FLAGS)&options::CC1Option) { \
- [&](const auto &Extracted) { \
- if (ALWAYS_EMIT || \
- (Extracted != \
- static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE) \
- : (DEFAULT_VALUE)))) \
- DENORMALIZER(ARGS, SPELLING, STRING_ALLOCATOR, Option::KIND##Class, \
- TABLE_INDEX, Extracted); \
- }(EXTRACTOR(KEYPATH)); \
- }
+ llvm::Triple T(TargetOpts->Triple);
-#define OPTION_WITH_MARSHALLING( \
- PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \
- DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, \
- MERGER, EXTRACTOR, TABLE_INDEX) \
- GENERATE_OPTION_WITH_MARSHALLING(Args, SA, KIND, FLAGS, SPELLING, \
- ALWAYS_EMIT, this->KEYPATH, DEFAULT_VALUE, \
- IMPLIED_CHECK, IMPLIED_VALUE, DENORMALIZER, \
- EXTRACTOR, TABLE_INDEX)
-
-#define DIAG_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
-#define LANG_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
-#define CODEGEN_OPTION_WITH_MARSHALLING OPTION_WITH_MARSHALLING
-
-#include "clang/Driver/Options.inc"
-
-#undef CODEGEN_OPTION_WITH_MARSHALLING
-#undef LANG_OPTION_WITH_MARSHALLING
-#undef DIAG_OPTION_WITH_MARSHALLING
-#undef OPTION_WITH_MARSHALLING
-#undef GENERATE_OPTION_WITH_MARSHALLING
-
- GenerateLangArgs(*LangOpts, Args, SA);
+ GenerateFileSystemArgs(FileSystemOpts, Args, SA);
+ GenerateMigratorArgs(MigratorOpts, Args, SA);
+ GenerateAnalyzerArgs(*AnalyzerOpts, Args, SA);
+ GenerateDiagnosticArgs(*DiagnosticOpts, Args, SA, false);
+ GenerateFrontendArgs(FrontendOpts, Args, SA, LangOpts->IsHeaderFile);
+ GenerateTargetArgs(*TargetOpts, Args, SA);
+ GenerateHeaderSearchArgs(*HeaderSearchOpts, Args, SA);
+ GenerateLangArgs(*LangOpts, Args, SA, T, FrontendOpts.DashX);
+ GenerateCodeGenArgs(CodeGenOpts, Args, SA, T, FrontendOpts.OutputFile,
+ &*LangOpts);
+ GeneratePreprocessorArgs(*PreprocessorOpts, Args, SA, *LangOpts, FrontendOpts,
+ CodeGenOpts);
+ GeneratePreprocessorOutputArgs(PreprocessorOutputOpts, Args, SA,
+ FrontendOpts.ProgramAction);
+ GenerateDependencyOutputArgs(DependencyOutputOpts, Args, SA);
}
IntrusiveRefCntPtr<llvm::vfs::FileSystem>
diff --git a/src/llvm-project/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/src/llvm-project/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
index ff0aa6f..2e23ebf 100644
--- a/src/llvm-project/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/src/llvm-project/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -10,15 +10,17 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/Utils.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
-#include "clang/Driver/Action.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Host.h"
using namespace clang;
@@ -37,7 +39,10 @@
SmallVector<const char *, 16> Args(ArgList.begin(), ArgList.end());
// FIXME: Find a cleaner way to force the driver into restricted modes.
- Args.push_back("-fsyntax-only");
+ Args.insert(
+ llvm::find_if(
+ Args, [](const char *Elem) { return llvm::StringRef(Elem) == "--"; }),
+ "-fsyntax-only");
// FIXME: We shouldn't have to pass in the path info.
driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(), *Diags,
diff --git a/src/llvm-project/clang/lib/Frontend/DependencyFile.cpp b/src/llvm-project/clang/lib/Frontend/DependencyFile.cpp
index fe8ab71..2888273 100644
--- a/src/llvm-project/clang/lib/Frontend/DependencyFile.cpp
+++ b/src/llvm-project/clang/lib/Frontend/DependencyFile.cpp
@@ -141,7 +141,18 @@
}
bool DependencyCollector::addDependency(StringRef Filename) {
- if (Seen.insert(Filename).second) {
+ StringRef SearchPath;
+#ifdef _WIN32
+ // Make the search insensitive to case and separators.
+ llvm::SmallString<256> TmpPath = Filename;
+ llvm::sys::path::native(TmpPath);
+ std::transform(TmpPath.begin(), TmpPath.end(), TmpPath.begin(), ::tolower);
+ SearchPath = TmpPath.str();
+#else
+ SearchPath = Filename;
+#endif
+
+ if (Seen.insert(SearchPath).second) {
Dependencies.push_back(std::string(Filename));
return true;
}
@@ -182,7 +193,7 @@
IncludeModuleFiles(Opts.IncludeModuleFiles),
OutputFormat(Opts.OutputFormat), InputFileIndex(0) {
for (const auto &ExtraDep : Opts.ExtraDeps) {
- if (addDependency(ExtraDep))
+ if (addDependency(ExtraDep.first))
++InputFileIndex;
}
}
@@ -307,7 +318,7 @@
}
std::error_code EC;
- llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
Diags.Report(diag::err_fe_error_opening) << OutputFile << EC.message();
return;
diff --git a/src/llvm-project/clang/lib/Frontend/DependencyGraph.cpp b/src/llvm-project/clang/lib/Frontend/DependencyGraph.cpp
index 8a6e491..4bed4e2 100644
--- a/src/llvm-project/clang/lib/Frontend/DependencyGraph.cpp
+++ b/src/llvm-project/clang/lib/Frontend/DependencyGraph.cpp
@@ -100,7 +100,7 @@
void DependencyGraphCallback::OutputGraphFile() {
std::error_code EC;
- llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
<< EC.message();
diff --git a/src/llvm-project/clang/lib/Frontend/DiagnosticRenderer.cpp b/src/llvm-project/clang/lib/Frontend/DiagnosticRenderer.cpp
index 22b9579..0afc8f3 100644
--- a/src/llvm-project/clang/lib/Frontend/DiagnosticRenderer.cpp
+++ b/src/llvm-project/clang/lib/Frontend/DiagnosticRenderer.cpp
@@ -394,6 +394,13 @@
}
}
+ // There is a chance that begin or end is invalid here, for example if
+ // specific compile error is reported.
+ // It is possible that the FileID's do not match, if one comes from an
+ // included file. In this case we can not produce a meaningful source range.
+ if (Begin.isInvalid() || End.isInvalid() || BeginFileID != EndFileID)
+ continue;
+
// Do the backtracking.
SmallVector<FileID, 4> CommonArgExpansions;
computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions);
diff --git a/src/llvm-project/clang/lib/Frontend/FrontendAction.cpp b/src/llvm-project/clang/lib/Frontend/FrontendAction.cpp
index 11b25b1..c996c9c 100644
--- a/src/llvm-project/clang/lib/Frontend/FrontendAction.cpp
+++ b/src/llvm-project/clang/lib/Frontend/FrontendAction.cpp
@@ -342,7 +342,8 @@
// file relative to the module build directory (the directory containing
// the module map file) so this will find the same file that we found
// while parsing the module map.
- addHeaderInclude(H.NameAsWritten, Includes, LangOpts, Module->IsExternC);
+ addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts,
+ Module->IsExternC);
}
}
// Note that Module->PrivateHeaders will not be a TopHeader.
@@ -351,8 +352,8 @@
Module->addTopHeader(UmbrellaHeader.Entry);
if (Module->Parent)
// Include the umbrella header for submodules.
- addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts,
- Module->IsExternC);
+ addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory,
+ Includes, LangOpts, Module->IsExternC);
} else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) {
// Add all of the headers we find in this subdirectory.
std::error_code EC;
@@ -386,7 +387,8 @@
auto PathIt = llvm::sys::path::rbegin(Dir->path());
for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)
Components.push_back(*PathIt);
- SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten);
+ SmallString<128> RelativeHeader(
+ UmbrellaDir.PathRelativeToRootModuleDirectory);
for (auto It = Components.rbegin(), End = Components.rend(); It != End;
++It)
llvm::sys::path::append(RelativeHeader, *It);
@@ -470,7 +472,7 @@
// Dig out the module definition.
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule,
- /*AllowSearch=*/false);
+ /*AllowSearch=*/true);
if (!M) {
CI.getDiagnostics().Report(diag::err_missing_module)
<< CI.getLangOpts().CurrentModule << ModuleMapFilename;
@@ -528,8 +530,8 @@
SmallString<256> HeaderContents;
std::error_code Err = std::error_code();
if (Module::Header UmbrellaHeader = M->getUmbrellaHeader())
- addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents,
- CI.getLangOpts(), M->IsExternC);
+ addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory,
+ HeaderContents, CI.getLangOpts(), M->IsExternC);
Err = collectModuleHeaderIncludes(
CI.getLangOpts(), FileMgr, CI.getDiagnostics(),
CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M,
@@ -1087,6 +1089,7 @@
void WrapperFrontendAction::ExecuteAction() {
WrappedAction->ExecuteAction();
}
+void WrapperFrontendAction::EndSourceFile() { WrappedAction->EndSourceFile(); }
void WrapperFrontendAction::EndSourceFileAction() {
WrappedAction->EndSourceFileAction();
}
diff --git a/src/llvm-project/clang/lib/Frontend/FrontendActions.cpp b/src/llvm-project/clang/lib/Frontend/FrontendActions.cpp
index 060cec2..c6ebbdc 100644
--- a/src/llvm-project/clang/lib/Frontend/FrontendActions.cpp
+++ b/src/llvm-project/clang/lib/Frontend/FrontendActions.cpp
@@ -62,6 +62,27 @@
void InitOnlyAction::ExecuteAction() {
}
+// Basically PreprocessOnlyAction::ExecuteAction.
+void ReadPCHAndPreprocessAction::ExecuteAction() {
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
+
+ // Ignore unknown pragmas.
+ PP.IgnorePragmas();
+
+ Token Tok;
+ // Start parsing the specified input file.
+ PP.EnterMainSourceFile();
+ do {
+ PP.Lex(Tok);
+ } while (Tok.isNot(tok::eof));
+}
+
+std::unique_ptr<ASTConsumer>
+ReadPCHAndPreprocessAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ return std::make_unique<ASTConsumer>();
+}
+
//===----------------------------------------------------------------------===//
// AST Consumer Actions
//===----------------------------------------------------------------------===//
@@ -218,7 +239,8 @@
// Because this is exposed via libclang we must disable RemoveFileOnSignal.
return CI.createDefaultOutputFile(/*Binary=*/true, InFile, /*Extension=*/"",
/*RemoveFileOnSignal=*/false,
- /*CreateMissingDirectories=*/true);
+ /*CreateMissingDirectories=*/true,
+ /*ForceUseTemporary=*/true);
}
bool GenerateModuleInterfaceAction::BeginSourceFileAction(
@@ -297,7 +319,8 @@
<< Name;
continue;
}
- Headers.push_back({std::string(Name), *FE});
+ Headers.push_back(
+ {std::string(Name), std::string(Name), &FE->getFileEntry()});
}
HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers);
@@ -722,7 +745,7 @@
if (!OutputFileName.empty() && OutputFileName != "-") {
std::error_code EC;
OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC,
- llvm::sys::fs::OF_Text));
+ llvm::sys::fs::OF_TextWithCRLF));
}
llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
@@ -795,7 +818,7 @@
void PrintPreprocessedAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
// Output file may need to be set to 'Binary', to avoid converting Unix style
- // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
+ // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>) on Windows.
//
// Look to see what type of line endings the file uses. If there's a
// CRLF, then we won't open the file up in binary mode. If there is
@@ -807,30 +830,35 @@
// all of their source code on a single line. However, that is still a
// concern, so if we scan for too long, we'll just assume the file should
// be opened in binary mode.
- bool BinaryMode = true;
- const SourceManager& SM = CI.getSourceManager();
- if (llvm::Optional<llvm::MemoryBufferRef> Buffer =
- SM.getBufferOrNone(SM.getMainFileID())) {
- const char *cur = Buffer->getBufferStart();
- const char *end = Buffer->getBufferEnd();
- const char *next = (cur != end) ? cur + 1 : end;
- // Limit ourselves to only scanning 256 characters into the source
- // file. This is mostly a sanity check in case the file has no
- // newlines whatsoever.
- if (end - cur > 256) end = cur + 256;
+ bool BinaryMode = false;
+ if (llvm::Triple(LLVM_HOST_TRIPLE).isOSWindows()) {
+ BinaryMode = true;
+ const SourceManager &SM = CI.getSourceManager();
+ if (llvm::Optional<llvm::MemoryBufferRef> Buffer =
+ SM.getBufferOrNone(SM.getMainFileID())) {
+ const char *cur = Buffer->getBufferStart();
+ const char *end = Buffer->getBufferEnd();
+ const char *next = (cur != end) ? cur + 1 : end;
- while (next < end) {
- if (*cur == 0x0D) { // CR
- if (*next == 0x0A) // CRLF
- BinaryMode = false;
+ // Limit ourselves to only scanning 256 characters into the source
+ // file. This is mostly a sanity check in case the file has no
+ // newlines whatsoever.
+ if (end - cur > 256)
+ end = cur + 256;
- break;
- } else if (*cur == 0x0A) // LF
- break;
+ while (next < end) {
+ if (*cur == 0x0D) { // CR
+ if (*next == 0x0A) // CRLF
+ BinaryMode = false;
- ++cur;
- ++next;
+ break;
+ } else if (*cur == 0x0A) // LF
+ break;
+
+ ++cur;
+ ++next;
+ }
}
}
@@ -862,6 +890,7 @@
case Language::ObjC:
case Language::ObjCXX:
case Language::OpenCL:
+ case Language::OpenCLCXX:
case Language::CUDA:
case Language::HIP:
break;
diff --git a/src/llvm-project/clang/lib/Frontend/FrontendOptions.cpp b/src/llvm-project/clang/lib/Frontend/FrontendOptions.cpp
index 4ea13cf..37ac428 100644
--- a/src/llvm-project/clang/lib/Frontend/FrontendOptions.cpp
+++ b/src/llvm-project/clang/lib/Frontend/FrontendOptions.cpp
@@ -29,6 +29,7 @@
.Case("cppm", Language::CXX)
.Case("iim", InputKind(Language::CXX).getPreprocessed())
.Case("cl", Language::OpenCL)
+ .Case("clcpp", Language::OpenCLCXX)
.Cases("cu", "cuh", Language::CUDA)
.Case("hip", Language::HIP)
.Cases("ll", "bc", Language::LLVM_IR)
diff --git a/src/llvm-project/clang/lib/Frontend/HeaderIncludeGen.cpp b/src/llvm-project/clang/lib/Frontend/HeaderIncludeGen.cpp
index 97fac8a..1ee47d8 100644
--- a/src/llvm-project/clang/lib/Frontend/HeaderIncludeGen.cpp
+++ b/src/llvm-project/clang/lib/Frontend/HeaderIncludeGen.cpp
@@ -45,6 +45,9 @@
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID) override;
+
+ void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) override;
};
}
@@ -101,7 +104,7 @@
std::error_code EC;
llvm::raw_fd_ostream *OS = new llvm::raw_fd_ostream(
OutputPath.str(), EC,
- llvm::sys::fs::OF_Append | llvm::sys::fs::OF_Text);
+ llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
PP.getDiagnostics().Report(clang::diag::warn_fe_cc_print_header_failure)
<< EC.message();
@@ -119,7 +122,7 @@
// as sanitizer blacklists. It's only important for cl.exe compatibility,
// the GNU way to generate rules is -M / -MM / -MD / -MMD.
for (const auto &Header : DepOpts.ExtraDeps)
- PrintHeaderInfo(OutputFile, Header, ShowDepth, 2, MSStyle);
+ PrintHeaderInfo(OutputFile, Header.first, ShowDepth, 2, MSStyle);
PP.addPPCallbacks(std::make_unique<HeaderIncludesCallback>(
&PP, ShowAllHeaders, OutputFile, DepOpts, OwnsOutputFile, ShowDepth,
MSStyle));
@@ -181,3 +184,16 @@
MSStyle);
}
}
+
+void HeaderIncludesCallback::FileSkipped(const FileEntryRef &SkippedFile, const
+ Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {
+ if (!DepOpts.ShowSkippedHeaderIncludes)
+ return;
+
+ if (!DepOpts.IncludeSystemHeaders && isSystem(FileType))
+ return;
+
+ PrintHeaderInfo(OutputFile, SkippedFile.getName(), ShowDepth,
+ CurrentIncludeDepth + 1, MSStyle);
+}
diff --git a/src/llvm-project/clang/lib/Frontend/InitHeaderSearch.cpp b/src/llvm-project/clang/lib/Frontend/InitHeaderSearch.cpp
index bc31445..ba9f963 100644
--- a/src/llvm-project/clang/lib/Frontend/InitHeaderSearch.cpp
+++ b/src/llvm-project/clang/lib/Frontend/InitHeaderSearch.cpp
@@ -32,14 +32,20 @@
using namespace clang::frontend;
namespace {
+/// Holds information about a single DirectoryLookup object.
+struct DirectoryLookupInfo {
+ IncludeDirGroup Group;
+ DirectoryLookup Lookup;
+
+ DirectoryLookupInfo(IncludeDirGroup Group, DirectoryLookup Lookup)
+ : Group(Group), Lookup(Lookup) {}
+};
/// InitHeaderSearch - This class makes it easier to set the search paths of
/// a HeaderSearch object. InitHeaderSearch stores several search path lists
/// internally, which can be sent to a HeaderSearch object in one swoop.
class InitHeaderSearch {
- std::vector<std::pair<IncludeDirGroup, DirectoryLookup> > IncludePath;
- typedef std::vector<std::pair<IncludeDirGroup,
- DirectoryLookup> >::const_iterator path_iterator;
+ std::vector<DirectoryLookupInfo> IncludePath;
std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
HeaderSearch &Headers;
bool Verbose;
@@ -154,8 +160,7 @@
// If the directory exists, add it.
if (auto DE = FM.getOptionalDirectoryRef(MappedPathStr)) {
- IncludePath.push_back(
- std::make_pair(Group, DirectoryLookup(*DE, Type, isFramework)));
+ IncludePath.emplace_back(Group, DirectoryLookup(*DE, Type, isFramework));
return true;
}
@@ -165,9 +170,8 @@
if (auto FE = FM.getFile(MappedPathStr)) {
if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
// It is a headermap, add it to the search path.
- IncludePath.push_back(
- std::make_pair(Group,
- DirectoryLookup(HM, Type, Group == IndexHeaderMap)));
+ IncludePath.emplace_back(
+ Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap));
return true;
}
}
@@ -558,32 +562,32 @@
// Quoted arguments go first.
for (auto &Include : IncludePath)
- if (Include.first == Quoted)
- SearchList.push_back(Include.second);
+ if (Include.Group == Quoted)
+ SearchList.push_back(Include.Lookup);
// Deduplicate and remember index.
RemoveDuplicates(SearchList, 0, Verbose);
unsigned NumQuoted = SearchList.size();
for (auto &Include : IncludePath)
- if (Include.first == Angled || Include.first == IndexHeaderMap)
- SearchList.push_back(Include.second);
+ if (Include.Group == Angled || Include.Group == IndexHeaderMap)
+ SearchList.push_back(Include.Lookup);
RemoveDuplicates(SearchList, NumQuoted, Verbose);
unsigned NumAngled = SearchList.size();
for (auto &Include : IncludePath)
- if (Include.first == System || Include.first == ExternCSystem ||
- (!Lang.ObjC && !Lang.CPlusPlus && Include.first == CSystem) ||
+ if (Include.Group == System || Include.Group == ExternCSystem ||
+ (!Lang.ObjC && !Lang.CPlusPlus && Include.Group == CSystem) ||
(/*FIXME !Lang.ObjC && */ Lang.CPlusPlus &&
- Include.first == CXXSystem) ||
- (Lang.ObjC && !Lang.CPlusPlus && Include.first == ObjCSystem) ||
- (Lang.ObjC && Lang.CPlusPlus && Include.first == ObjCXXSystem))
- SearchList.push_back(Include.second);
+ Include.Group == CXXSystem) ||
+ (Lang.ObjC && !Lang.CPlusPlus && Include.Group == ObjCSystem) ||
+ (Lang.ObjC && Lang.CPlusPlus && Include.Group == ObjCXXSystem))
+ SearchList.push_back(Include.Lookup);
for (auto &Include : IncludePath)
- if (Include.first == After)
- SearchList.push_back(Include.second);
+ if (Include.Group == After)
+ SearchList.push_back(Include.Lookup);
// Remove duplicates across both the Angled and System directories. GCC does
// this and failing to remove duplicates across these two groups breaks
diff --git a/src/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp b/src/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp
index c64a912..bca0bb4 100644
--- a/src/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/src/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp
@@ -168,7 +168,7 @@
MacroBuilder &Builder) {
llvm::APInt MaxVal = isSigned ? llvm::APInt::getSignedMaxValue(TypeWidth)
: llvm::APInt::getMaxValue(TypeWidth);
- Builder.defineMacro(MacroName, MaxVal.toString(10, isSigned) + ValSuffix);
+ Builder.defineMacro(MacroName, toString(MaxVal, 10, isSigned) + ValSuffix);
}
/// DefineTypeSize - An overloaded helper that uses TargetInfo to determine
@@ -216,6 +216,11 @@
if (TypeWidth == 64)
Ty = IsSigned ? TI.getInt64Type() : TI.getUInt64Type();
+ // Use the target specified int16 type when appropriate. Some MCU targets
+ // (such as AVR) have definition of [u]int16_t to [un]signed int.
+ if (TypeWidth == 16)
+ Ty = IsSigned ? TI.getInt16Type() : TI.getUInt16Type();
+
const char *Prefix = IsSigned ? "__INT" : "__UINT";
DefineType(Prefix + Twine(TypeWidth) + "_TYPE__", Ty, Builder);
@@ -474,10 +479,12 @@
Builder.defineMacro("__FAST_RELAXED_MATH__");
}
- if (LangOpts.SYCL) {
+ if (LangOpts.SYCLIsDevice || LangOpts.SYCLIsHost) {
// SYCL Version is set to a value when building SYCL applications
if (LangOpts.getSYCLVersion() == LangOptions::SYCL_2017)
Builder.defineMacro("CL_SYCL_LANGUAGE_VERSION", "121");
+ else if (LangOpts.getSYCLVersion() == LangOptions::SYCL_2020)
+ Builder.defineMacro("SYCL_LANGUAGE_VERSION", "202001");
}
// Not "standard" per se, but available even with the -undef flag.
@@ -587,7 +594,12 @@
Builder.defineMacro("__cpp_designated_initializers", "201707L");
Builder.defineMacro("__cpp_impl_three_way_comparison", "201907L");
//Builder.defineMacro("__cpp_modules", "201907L");
- //Builder.defineMacro("__cpp_using_enum", "201907L");
+ Builder.defineMacro("__cpp_using_enum", "201907L");
+ }
+ // C++2b features.
+ if (LangOpts.CPlusPlus2b) {
+ Builder.defineMacro("__cpp_implicit_move", "202011L");
+ Builder.defineMacro("__cpp_size_t_suffix", "202011L");
}
if (LangOpts.Char8)
Builder.defineMacro("__cpp_char8_t", "201811L");
@@ -598,6 +610,29 @@
Builder.defineMacro("__cpp_coroutines", "201703L");
}
+/// InitializeOpenCLFeatureTestMacros - Define OpenCL macros based on target
+/// settings and language version
+void InitializeOpenCLFeatureTestMacros(const TargetInfo &TI,
+ const LangOptions &Opts,
+ MacroBuilder &Builder) {
+ const llvm::StringMap<bool> &OpenCLFeaturesMap = TI.getSupportedOpenCLOpts();
+ // FIXME: OpenCL options which affect language semantics/syntax
+ // should be moved into LangOptions.
+ auto defineOpenCLExtMacro = [&](llvm::StringRef Name, auto... OptArgs) {
+ // Check if extension is supported by target and is available in this
+ // OpenCL version
+ if (TI.hasFeatureEnabled(OpenCLFeaturesMap, Name) &&
+ OpenCLOptions::isOpenCLOptionAvailableIn(Opts, OptArgs...))
+ Builder.defineMacro(Name);
+ };
+#define OPENCL_GENERIC_EXTENSION(Ext, ...) \
+ defineOpenCLExtMacro(#Ext, __VA_ARGS__);
+#include "clang/Basic/OpenCLExtensions.def"
+
+ // Assume compiling for FULL profile
+ Builder.defineMacro("__opencl_c_int64");
+}
+
static void InitializePredefinedMacros(const TargetInfo &TI,
const LangOptions &LangOpts,
const FrontendOptions &FEOpts,
@@ -775,6 +810,21 @@
}
}
+ // Macros to help identify the narrow and wide character sets
+ // FIXME: clang currently ignores -fexec-charset=. If this changes,
+ // then this may need to be updated.
+ Builder.defineMacro("__clang_literal_encoding__", "\"UTF-8\"");
+ if (TI.getTypeWidth(TI.getWCharType()) >= 32) {
+ // FIXME: 32-bit wchar_t signals UTF-32. This may change
+ // if -fwide-exec-charset= is ever supported.
+ Builder.defineMacro("__clang_wide_literal_encoding__", "\"UTF-32\"");
+ } else {
+ // FIXME: Less-than 32-bit wchar_t generally means UTF-16
+ // (e.g., Windows, 32-bit IBM). This may need to be
+ // updated if -fwide-exec-charset= is ever supported.
+ Builder.defineMacro("__clang_wide_literal_encoding__", "\"UTF-16\"");
+ }
+
if (LangOpts.Optimize)
Builder.defineMacro("__OPTIMIZE__");
if (LangOpts.OptimizeSize)
@@ -967,8 +1017,7 @@
DefineFastIntType(64, true, TI, Builder);
DefineFastIntType(64, false, TI, Builder);
- char UserLabelPrefix[2] = {TI.getDataLayout().getGlobalPrefix(), 0};
- Builder.defineMacro("__USER_LABEL_PREFIX__", UserLabelPrefix);
+ Builder.defineMacro("__USER_LABEL_PREFIX__", TI.getUserLabelPrefix());
if (LangOpts.FastMath || LangOpts.FiniteMathOnly)
Builder.defineMacro("__FINITE_MATH_ONLY__", "1");
@@ -1120,7 +1169,7 @@
// OpenCL definitions.
if (LangOpts.OpenCL) {
- TI.getOpenCLFeatureDefines(LangOpts, Builder);
+ InitializeOpenCLFeatureTestMacros(TI, LangOpts, Builder);
if (TI.getTriple().isSPIR())
Builder.defineMacro("__IMAGE_SUPPORT__");
diff --git a/src/llvm-project/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp b/src/llvm-project/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
index b7c1e69..d58f5bb 100644
--- a/src/llvm-project/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
+++ b/src/llvm-project/clang/lib/Frontend/InterfaceStubFunctionsConsumer.cpp
@@ -290,11 +290,8 @@
const ASTContext &context, StringRef Format,
raw_ostream &OS) -> void {
OS << "--- !" << Format << "\n";
- OS << "IfsVersion: 2.0\n";
- OS << "Triple: " << T.str() << "\n";
- OS << "ObjectFileFormat: "
- << "ELF"
- << "\n"; // TODO: For now, just ELF.
+ OS << "IfsVersion: 3.0\n";
+ OS << "Target: " << T.str() << "\n";
OS << "Symbols:\n";
for (const auto &E : Symbols) {
const MangledSymbol &Symbol = E.second;
@@ -330,7 +327,7 @@
OS.flush();
};
- assert(Format == "experimental-ifs-v2" && "Unexpected IFS Format.");
+ assert(Format == "ifs-v1" && "Unexpected IFS Format.");
writeIfsV1(Instance.getTarget().getTriple(), Symbols, context, Format, *OS);
}
};
@@ -339,6 +336,5 @@
std::unique_ptr<ASTConsumer>
GenerateInterfaceStubsAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
- return std::make_unique<InterfaceStubFunctionsConsumer>(
- CI, InFile, "experimental-ifs-v2");
+ return std::make_unique<InterfaceStubFunctionsConsumer>(CI, InFile, "ifs-v1");
}
diff --git a/src/llvm-project/clang/lib/Frontend/ModuleDependencyCollector.cpp b/src/llvm-project/clang/lib/Frontend/ModuleDependencyCollector.cpp
index 2e4e64f..4301e49 100644
--- a/src/llvm-project/clang/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/src/llvm-project/clang/lib/Frontend/ModuleDependencyCollector.cpp
@@ -148,7 +148,7 @@
std::error_code EC;
SmallString<256> YAMLPath = VFSDir;
llvm::sys::path::append(YAMLPath, "vfs.yaml");
- llvm::raw_fd_ostream OS(YAMLPath, EC, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream OS(YAMLPath, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
HasErrors = true;
return;
diff --git a/src/llvm-project/clang/lib/Frontend/PrecompiledPreamble.cpp b/src/llvm-project/clang/lib/Frontend/PrecompiledPreamble.cpp
index 77b9371..af82ab3 100644
--- a/src/llvm-project/clang/lib/Frontend/PrecompiledPreamble.cpp
+++ b/src/llvm-project/clang/lib/Frontend/PrecompiledPreamble.cpp
@@ -365,17 +365,9 @@
Clang->setDiagnostics(&Diagnostics);
// Create the target instance.
- Clang->setTarget(TargetInfo::CreateTargetInfo(
- Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
- if (!Clang->hasTarget())
+ if (!Clang->createTarget())
return BuildPreambleError::CouldntCreateTargetInfo;
- // Inform the target of the language options.
- //
- // FIXME: We shouldn't need to do this, the target should be immutable once
- // created. This complexity should be lifted elsewhere.
- Clang->getTarget().adjust(Clang->getLangOpts());
-
if (Clang->getFrontendOpts().Inputs.size() != 1 ||
Clang->getFrontendOpts().Inputs[0].getKind().getFormat() !=
InputKind::Source ||
diff --git a/src/llvm-project/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/src/llvm-project/clang/lib/Frontend/Rewrite/FrontendActions.cpp
index 5351ff0..09ed07b 100644
--- a/src/llvm-project/clang/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/src/llvm-project/clang/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -185,7 +185,7 @@
void RewriteMacrosAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
std::unique_ptr<raw_ostream> OS =
- CI.createDefaultOutputFile(true, getCurrentFileOrBufferName());
+ CI.createDefaultOutputFile(/*Binary=*/true, getCurrentFileOrBufferName());
if (!OS) return;
RewriteMacrosInInput(CI.getPreprocessor(), OS.get());
@@ -194,7 +194,7 @@
void RewriteTestAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
std::unique_ptr<raw_ostream> OS =
- CI.createDefaultOutputFile(false, getCurrentFileOrBufferName());
+ CI.createDefaultOutputFile(/*Binary=*/false, getCurrentFileOrBufferName());
if (!OS) return;
DoRewriteTest(CI.getPreprocessor(), OS.get());
@@ -270,7 +270,7 @@
bool RewriteIncludesAction::BeginSourceFileAction(CompilerInstance &CI) {
if (!OutputStream) {
OutputStream =
- CI.createDefaultOutputFile(true, getCurrentFileOrBufferName());
+ CI.createDefaultOutputFile(/*Binary=*/true, getCurrentFileOrBufferName());
if (!OutputStream)
return false;
}
diff --git a/src/llvm-project/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/src/llvm-project/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 9d5366b..fd54bcb 100644
--- a/src/llvm-project/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/src/llvm-project/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -585,7 +585,7 @@
CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
CastKind Kind, Expr *E) {
TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
- return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, nullptr,
+ return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,
FPOptionsOverride(), TInfo,
SourceLocation(), SourceLocation());
}
@@ -2107,12 +2107,12 @@
QualType pToFunc = Context->getPointerType(msgSendType);
ImplicitCastExpr *ICE =
ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
- DRE, nullptr, VK_RValue, FPOptionsOverride());
+ DRE, nullptr, VK_PRValue, FPOptionsOverride());
const auto *FT = msgSendType->castAs<FunctionType>();
CallExpr *Exp =
CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
- VK_RValue, EndLoc, FPOptionsOverride());
+ VK_PRValue, EndLoc, FPOptionsOverride());
return Exp;
}
@@ -2591,7 +2591,7 @@
DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
Expr *Unop = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
- Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
@@ -2694,7 +2694,7 @@
auto *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc, FPOptionsOverride());
+ VK_PRValue, EndLoc, FPOptionsOverride());
ReplaceStmt(Exp, CE);
return CE;
}
@@ -2720,7 +2720,7 @@
std::string NSArrayFName("__NSContainer_literal");
FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);
DeclRefExpr *NSArrayDRE = new (Context) DeclRefExpr(
- *Context, NSArrayFD, false, NSArrayFType, VK_RValue, SourceLocation());
+ *Context, NSArrayFD, false, NSArrayFType, VK_PRValue, SourceLocation());
SmallVector<Expr*, 16> InitExprs;
unsigned NumElements = Exp->getNumElements();
@@ -2815,7 +2815,7 @@
const FunctionType *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc, FPOptionsOverride());
+ VK_PRValue, EndLoc, FPOptionsOverride());
ReplaceStmt(Exp, CE);
return CE;
}
@@ -2841,7 +2841,7 @@
std::string NSDictFName("__NSContainer_literal");
FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);
DeclRefExpr *NSDictDRE = new (Context) DeclRefExpr(
- *Context, NSDictFD, false, NSDictFType, VK_RValue, SourceLocation());
+ *Context, NSDictFD, false, NSDictFType, VK_PRValue, SourceLocation());
SmallVector<Expr*, 16> KeyExprs;
SmallVector<Expr*, 16> ValueExprs;
@@ -2967,7 +2967,7 @@
const FunctionType *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc, FPOptionsOverride());
+ VK_PRValue, EndLoc, FPOptionsOverride());
ReplaceStmt(Exp, CE);
return CE;
}
@@ -3177,7 +3177,7 @@
FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(),
ID, FuncType, nullptr, SC_Extern, false, false);
DeclRefExpr *DRE = new (Context)
- DeclRefExpr(*Context, FD, false, castType, VK_RValue, SourceLocation());
+ DeclRefExpr(*Context, FD, false, castType, VK_PRValue, SourceLocation());
CallExpr *STCE =
CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue,
SourceLocation(), FPOptionsOverride());
@@ -3242,16 +3242,11 @@
SmallVector<Expr*, 4> InitExprs;
// set the receiver to self, the first argument to all methods.
- InitExprs.push_back(
- NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CK_BitCast,
- new (Context) DeclRefExpr(*Context,
- CurMethodDef->getSelfDecl(),
- false,
- Context->getObjCIdType(),
- VK_RValue,
- SourceLocation()))
- ); // set the 'receiver'.
+ InitExprs.push_back(NoTypeInfoCStyleCastExpr(
+ Context, Context->getObjCIdType(), CK_BitCast,
+ new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
+ Context->getObjCIdType(), VK_PRValue,
+ SourceLocation()))); // set the 'receiver'.
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
SmallVector<Expr*, 8> ClsExprs;
@@ -3291,7 +3286,7 @@
//
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
- Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
@@ -3309,7 +3304,7 @@
// struct __rw_objc_super *
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
- Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
}
MsgExprs.push_back(SuperRep);
@@ -3339,15 +3334,11 @@
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
SmallVector<Expr*, 4> InitExprs;
- InitExprs.push_back(
- NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CK_BitCast,
- new (Context) DeclRefExpr(*Context,
- CurMethodDef->getSelfDecl(),
- false,
- Context->getObjCIdType(),
- VK_RValue, SourceLocation()))
- ); // set the 'receiver'.
+ InitExprs.push_back(NoTypeInfoCStyleCastExpr(
+ Context, Context->getObjCIdType(), CK_BitCast,
+ new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
+ Context->getObjCIdType(), VK_PRValue,
+ SourceLocation()))); // set the 'receiver'.
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
SmallVector<Expr*, 8> ClsExprs;
@@ -3387,7 +3378,7 @@
//
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
- Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
@@ -3399,9 +3390,8 @@
SourceLocation());
TypeSourceInfo *superTInfo
= Context->getTrivialTypeSourceInfo(superType);
- SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
- superType, VK_RValue, ILE,
- false);
+ SuperRep = new (Context) CompoundLiteralExpr(
+ SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);
}
MsgExprs.push_back(SuperRep);
break;
@@ -3543,7 +3533,7 @@
const FunctionType *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc, FPOptionsOverride());
+ VK_PRValue, EndLoc, FPOptionsOverride());
Stmt *ReplacingStmt = CE;
if (MsgSendStretFlavor) {
// We have the method which returns a struct/union. Must also generate
@@ -3684,8 +3674,7 @@
Result += " {\n";
for (const auto *EC : ED->enumerators()) {
Result += "\t"; Result += EC->getName(); Result += " = ";
- llvm::APSInt Val = EC->getInitVal();
- Result += Val.toString(10);
+ Result += toString(EC->getInitVal(), 10);
Result += ",\n";
}
Result += "\t} ";
@@ -4580,11 +4569,9 @@
Expr *RHSExp = CEXPR->getRHS();
Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
Expr *CONDExp = CEXPR->getCond();
- ConditionalOperator *CondExpr =
- new (Context) ConditionalOperator(CONDExp,
- SourceLocation(), cast<Expr>(LHSStmt),
- SourceLocation(), cast<Expr>(RHSStmt),
- Exp->getType(), VK_RValue, OK_Ordinary);
+ ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
+ CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
+ cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
return CondExpr;
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
CPT = IRE->getType()->getAs<BlockPointerType>();
@@ -4654,7 +4641,7 @@
BlkExprs.push_back(*I);
}
CallExpr *CE =
- CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_RValue,
+ CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,
SourceLocation(), FPOptionsOverride());
return CE;
}
@@ -5283,7 +5270,7 @@
FD = SynthBlockInitFunctionDecl(Tag);
DeclRefExpr *DRE = new (Context)
- DeclRefExpr(*Context, FD, false, FType, VK_RValue, SourceLocation());
+ DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());
SmallVector<Expr*, 4> InitExprs;
@@ -5305,7 +5292,7 @@
const_cast<ASTContext &>(*Context),
new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
VK_LValue, SourceLocation()),
- UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
+ UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
InitExprs.push_back(DescRefExpr);
@@ -5323,9 +5310,10 @@
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
- Exp = UnaryOperator::Create(
- const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, QT, VK_RValue,
- OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
+ Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
+ UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
+ SourceLocation(), false,
+ FPOptionsOverride());
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -5340,9 +5328,10 @@
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
- Exp = UnaryOperator::Create(
- const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, QT, VK_RValue,
- OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
+ Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
+ UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
+ SourceLocation(), false,
+ FPOptionsOverride());
}
}
@@ -5382,7 +5371,7 @@
if (!isNestedCapturedVar)
Exp = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
- Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
InitExprs.push_back(Exp);
@@ -5409,7 +5398,7 @@
NewRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
- Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
NewRep);
@@ -7497,7 +7486,7 @@
VK_LValue, SourceLocation());
BinaryOperator *addExpr = BinaryOperator::Create(
*Context, castExpr, DRE, BO_Add,
- Context->getPointerType(Context->CharTy), VK_RValue, OK_Ordinary,
+ Context->getPointerType(Context->CharTy), VK_PRValue, OK_Ordinary,
SourceLocation(), FPOptionsOverride());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
diff --git a/src/llvm-project/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/src/llvm-project/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
index 543b3b0..0750d36 100644
--- a/src/llvm-project/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/src/llvm-project/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -491,7 +491,7 @@
CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
CastKind Kind, Expr *E) {
TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
- return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, nullptr,
+ return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,
FPOptionsOverride(), TInfo,
SourceLocation(), SourceLocation());
}
@@ -2024,13 +2024,13 @@
QualType pToFunc = Context->getPointerType(msgSendType);
ImplicitCastExpr *ICE =
ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
- DRE, nullptr, VK_RValue, FPOptionsOverride());
+ DRE, nullptr, VK_PRValue, FPOptionsOverride());
const auto *FT = msgSendType->castAs<FunctionType>();
CallExpr *Exp =
CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
- VK_RValue, EndLoc, FPOptionsOverride());
+ VK_PRValue, EndLoc, FPOptionsOverride());
return Exp;
}
@@ -2518,7 +2518,7 @@
DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
Expr *Unop = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
- Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
@@ -2617,7 +2617,7 @@
const auto *FT = msgSendType->castAs<FunctionType>();
CallExpr *STCE =
- CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue,
+ CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_PRValue,
SourceLocation(), FPOptionsOverride());
return STCE;
}
@@ -2670,16 +2670,11 @@
SmallVector<Expr*, 4> InitExprs;
// set the receiver to self, the first argument to all methods.
- InitExprs.push_back(
- NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CK_BitCast,
- new (Context) DeclRefExpr(*Context,
- CurMethodDef->getSelfDecl(),
- false,
- Context->getObjCIdType(),
- VK_RValue,
- SourceLocation()))
- ); // set the 'receiver'.
+ InitExprs.push_back(NoTypeInfoCStyleCastExpr(
+ Context, Context->getObjCIdType(), CK_BitCast,
+ new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
+ Context->getObjCIdType(), VK_PRValue,
+ SourceLocation()))); // set the 'receiver'.
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
SmallVector<Expr*, 8> ClsExprs;
@@ -2721,7 +2716,7 @@
//
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
- Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
@@ -2739,7 +2734,7 @@
// struct objc_super *
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
- Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
}
MsgExprs.push_back(SuperRep);
@@ -2766,15 +2761,11 @@
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
SmallVector<Expr*, 4> InitExprs;
- InitExprs.push_back(
- NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CK_BitCast,
- new (Context) DeclRefExpr(*Context,
- CurMethodDef->getSelfDecl(),
- false,
- Context->getObjCIdType(),
- VK_RValue, SourceLocation()))
- ); // set the 'receiver'.
+ InitExprs.push_back(NoTypeInfoCStyleCastExpr(
+ Context, Context->getObjCIdType(), CK_BitCast,
+ new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
+ Context->getObjCIdType(), VK_PRValue,
+ SourceLocation()))); // set the 'receiver'.
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
SmallVector<Expr*, 8> ClsExprs;
@@ -2817,7 +2808,7 @@
//
SuperRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
- Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
@@ -2829,9 +2820,8 @@
SourceLocation());
TypeSourceInfo *superTInfo
= Context->getTrivialTypeSourceInfo(superType);
- SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
- superType, VK_RValue, ILE,
- false);
+ SuperRep = new (Context) CompoundLiteralExpr(
+ SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);
}
MsgExprs.push_back(SuperRep);
break;
@@ -2973,7 +2963,7 @@
const auto *FT = msgSendType->castAs<FunctionType>();
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
- VK_RValue, EndLoc, FPOptionsOverride());
+ VK_PRValue, EndLoc, FPOptionsOverride());
Stmt *ReplacingStmt = CE;
if (MsgSendStretFlavor) {
// We have the method which returns a struct/union. Must also generate
@@ -3003,14 +2993,12 @@
Context->IntTy,
SourceLocation());
BinaryOperator *lessThanExpr = BinaryOperator::Create(
- *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_RValue,
+ *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue,
OK_Ordinary, SourceLocation(), FPOptionsOverride());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
- ConditionalOperator *CondExpr =
- new (Context) ConditionalOperator(lessThanExpr,
- SourceLocation(), CE,
- SourceLocation(), STCE,
- returnType, VK_RValue, OK_Ordinary);
+ ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
+ lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType,
+ VK_PRValue, OK_Ordinary);
ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
CondExpr);
}
@@ -3056,7 +3044,7 @@
*Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());
Expr *DerefExpr = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
- Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
CK_BitCast,
@@ -3749,11 +3737,9 @@
Expr *RHSExp = CEXPR->getRHS();
Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
Expr *CONDExp = CEXPR->getCond();
- ConditionalOperator *CondExpr =
- new (Context) ConditionalOperator(CONDExp,
- SourceLocation(), cast<Expr>(LHSStmt),
- SourceLocation(), cast<Expr>(RHSStmt),
- Exp->getType(), VK_RValue, OK_Ordinary);
+ ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
+ CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
+ cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
return CondExpr;
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
CPT = IRE->getType()->getAs<BlockPointerType>();
@@ -3823,7 +3809,7 @@
BlkExprs.push_back(*I);
}
CallExpr *CE =
- CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_RValue,
+ CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,
SourceLocation(), FPOptionsOverride());
return CE;
}
@@ -4422,7 +4408,7 @@
// Simulate a constructor call...
FD = SynthBlockInitFunctionDecl(Tag);
DeclRefExpr *DRE = new (Context)
- DeclRefExpr(*Context, FD, false, FType, VK_RValue, SourceLocation());
+ DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());
SmallVector<Expr*, 4> InitExprs;
@@ -4444,7 +4430,7 @@
const_cast<ASTContext &>(*Context),
new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
VK_LValue, SourceLocation()),
- UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue,
+ UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
InitExprs.push_back(DescRefExpr);
@@ -4462,9 +4448,10 @@
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
- Exp = UnaryOperator::Create(
- const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, QT, VK_RValue,
- OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
+ Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
+ UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
+ SourceLocation(), false,
+ FPOptionsOverride());
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
FD = SynthBlockInitFunctionDecl((*I)->getName());
@@ -4479,9 +4466,10 @@
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
- Exp = UnaryOperator::Create(
- const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, QT, VK_RValue,
- OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
+ Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
+ UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
+ SourceLocation(), false,
+ FPOptionsOverride());
}
}
InitExprs.push_back(Exp);
@@ -4520,7 +4508,7 @@
if (!isNestedCapturedVar)
Exp = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
- Context->getPointerType(Exp->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
InitExprs.push_back(Exp);
@@ -4539,7 +4527,7 @@
SourceLocation(), FPOptionsOverride());
NewRep = UnaryOperator::Create(
const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
- Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary,
+ Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,
SourceLocation(), false, FPOptionsOverride());
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
NewRep);
diff --git a/src/llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp b/src/llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp
index 354aa7f..7d4026a 100644
--- a/src/llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp
+++ b/src/llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp
@@ -15,6 +15,8 @@
using namespace clang;
using namespace clang::serialization;
+char TestModuleFileExtension::ID = 0;
+
TestModuleFileExtension::Writer::~Writer() { }
void TestModuleFileExtension::Writer::writeExtensionContents(
@@ -127,3 +129,11 @@
return std::unique_ptr<ModuleFileExtensionReader>(
new TestModuleFileExtension::Reader(this, Stream));
}
+
+std::string TestModuleFileExtension::str() const {
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
+ << ":" << UserInfo;
+ return OS.str();
+}
diff --git a/src/llvm-project/clang/lib/Frontend/TestModuleFileExtension.h b/src/llvm-project/clang/lib/Frontend/TestModuleFileExtension.h
index 13e0907..c8ca4cd 100644
--- a/src/llvm-project/clang/lib/Frontend/TestModuleFileExtension.h
+++ b/src/llvm-project/clang/lib/Frontend/TestModuleFileExtension.h
@@ -17,7 +17,8 @@
namespace clang {
/// A module file extension used for testing purposes.
-class TestModuleFileExtension : public ModuleFileExtension {
+class TestModuleFileExtension
+ : public llvm::RTTIExtends<TestModuleFileExtension, ModuleFileExtension> {
std::string BlockName;
unsigned MajorVersion;
unsigned MinorVersion;
@@ -43,14 +44,13 @@
};
public:
- TestModuleFileExtension(StringRef BlockName,
- unsigned MajorVersion,
- unsigned MinorVersion,
- bool Hashed,
+ static char ID;
+
+ TestModuleFileExtension(StringRef BlockName, unsigned MajorVersion,
+ unsigned MinorVersion, bool Hashed,
StringRef UserInfo)
- : BlockName(BlockName),
- MajorVersion(MajorVersion), MinorVersion(MinorVersion),
- Hashed(Hashed), UserInfo(UserInfo) { }
+ : BlockName(BlockName), MajorVersion(MajorVersion),
+ MinorVersion(MinorVersion), Hashed(Hashed), UserInfo(UserInfo) {}
~TestModuleFileExtension() override;
ModuleFileExtensionMetadata getExtensionMetadata() const override;
@@ -64,6 +64,8 @@
createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
ASTReader &Reader, serialization::ModuleFile &Mod,
const llvm::BitstreamCursor &Stream) override;
+
+ std::string str() const;
};
} // end namespace clang
diff --git a/src/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp b/src/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp
index e781fd2..8df7496 100644
--- a/src/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/src/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp
@@ -684,8 +684,7 @@
OS.resetColor();
if (DiagOpts->ShowLevel)
- printDiagnosticLevel(OS, Level, DiagOpts->ShowColors,
- DiagOpts->CLFallbackMode);
+ printDiagnosticLevel(OS, Level, DiagOpts->ShowColors);
printDiagnosticMessage(OS,
/*IsSupplemental*/ Level == DiagnosticsEngine::Note,
Message, OS.tell() - StartOfLocationInfo,
@@ -695,8 +694,7 @@
/*static*/ void
TextDiagnostic::printDiagnosticLevel(raw_ostream &OS,
DiagnosticsEngine::Level Level,
- bool ShowColors,
- bool CLFallbackMode) {
+ bool ShowColors) {
if (ShowColors) {
// Print diagnostic category in bold and color
switch (Level) {
@@ -713,22 +711,13 @@
switch (Level) {
case DiagnosticsEngine::Ignored:
llvm_unreachable("Invalid diagnostic type");
- case DiagnosticsEngine::Note: OS << "note"; break;
- case DiagnosticsEngine::Remark: OS << "remark"; break;
- case DiagnosticsEngine::Warning: OS << "warning"; break;
- case DiagnosticsEngine::Error: OS << "error"; break;
- case DiagnosticsEngine::Fatal: OS << "fatal error"; break;
+ case DiagnosticsEngine::Note: OS << "note: "; break;
+ case DiagnosticsEngine::Remark: OS << "remark: "; break;
+ case DiagnosticsEngine::Warning: OS << "warning: "; break;
+ case DiagnosticsEngine::Error: OS << "error: "; break;
+ case DiagnosticsEngine::Fatal: OS << "fatal error: "; break;
}
- // In clang-cl /fallback mode, print diagnostics as "error(clang):". This
- // makes it more clear whether a message is coming from clang or cl.exe,
- // and it prevents MSBuild from concluding that the build failed just because
- // there is an "error:" in the output.
- if (CLFallbackMode)
- OS << "(clang)";
-
- OS << ": ";
-
if (ShowColors)
OS.resetColor();
}
diff --git a/src/llvm-project/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/src/llvm-project/clang/lib/Frontend/TextDiagnosticPrinter.cpp
index 9feb3c6..0ff5376 100644
--- a/src/llvm-project/clang/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/src/llvm-project/clang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -133,8 +133,7 @@
// diagnostics in a context that lacks language options, a source manager, or
// other infrastructure necessary when emitting more rich diagnostics.
if (!Info.getLocation().isValid()) {
- TextDiagnostic::printDiagnosticLevel(OS, Level, DiagOpts->ShowColors,
- DiagOpts->CLFallbackMode);
+ TextDiagnostic::printDiagnosticLevel(OS, Level, DiagOpts->ShowColors);
TextDiagnostic::printDiagnosticMessage(
OS, /*IsSupplemental=*/Level == DiagnosticsEngine::Note,
DiagMessageStream.str(), OS.tell() - StartOfLocationInfo,
diff --git a/src/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/src/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index ac64e17..b95851e 100644
--- a/src/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/src/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -187,7 +187,7 @@
bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
// Honor -help.
if (Clang->getFrontendOpts().ShowHelp) {
- driver::getDriverOptTable().PrintHelp(
+ driver::getDriverOptTable().printHelp(
llvm::outs(), "clang -cc1 [options] file...",
"LLVM 'Clang' Compiler: http://clang.llvm.org",
/*Include=*/driver::options::CC1Option,
diff --git a/src/llvm-project/clang/lib/Headers/CMakeLists.txt b/src/llvm-project/clang/lib/Headers/CMakeLists.txt
index b2c0ce8..8131f60 100644
--- a/src/llvm-project/clang/lib/Headers/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/Headers/CMakeLists.txt
@@ -38,6 +38,7 @@
avxvnniintrin.h
bmi2intrin.h
bmiintrin.h
+ builtins.h
__clang_cuda_builtin_vars.h
__clang_cuda_math.h
__clang_cuda_cmath.h
@@ -66,6 +67,10 @@
fmaintrin.h
fxsrintrin.h
gfniintrin.h
+ hexagon_circ_brev_intrinsics.h
+ hexagon_protos.h
+ hexagon_types.h
+ hvx_hexagon_protos.h
hresetintrin.h
htmintrin.h
htmxlintrin.h
@@ -209,6 +214,8 @@
clang_generate_header(-gen-arm-mve-header arm_mve.td arm_mve.h)
# Generate arm_cde.h
clang_generate_header(-gen-arm-cde-header arm_cde.td arm_cde.h)
+# Generate riscv_vector.h
+clang_generate_header(-gen-riscv-vector-header riscv_vector.td riscv_vector.h)
add_custom_target(clang-resource-headers ALL DEPENDS ${out_files})
set_target_properties(clang-resource-headers PROPERTIES
diff --git a/src/llvm-project/clang/lib/Headers/__clang_cuda_math.h b/src/llvm-project/clang/lib/Headers/__clang_cuda_math.h
index acb26ad..538556f 100644
--- a/src/llvm-project/clang/lib/Headers/__clang_cuda_math.h
+++ b/src/llvm-project/clang/lib/Headers/__clang_cuda_math.h
@@ -166,6 +166,8 @@
__DEVICE__ long long llrintf(float __a) { return __nv_llrintf(__a); }
__DEVICE__ long long llround(double __a) { return __nv_llround(__a); }
__DEVICE__ long long llroundf(float __a) { return __nv_llroundf(__a); }
+__DEVICE__ double round(double __a) { return __nv_round(__a); }
+__DEVICE__ float roundf(float __a) { return __nv_roundf(__a); }
__DEVICE__ double log(double __a) { return __nv_log(__a); }
__DEVICE__ double log10(double __a) { return __nv_log10(__a); }
__DEVICE__ float log10f(float __a) { return __nv_log10f(__a); }
@@ -270,8 +272,6 @@
__DEVICE__ float rnormf(int __dim, const float *__t) {
return __nv_rnormf(__dim, __t);
}
-__DEVICE__ double round(double __a) { return __nv_round(__a); }
-__DEVICE__ float roundf(float __a) { return __nv_roundf(__a); }
__DEVICE__ double rsqrt(double __a) { return __nv_rsqrt(__a); }
__DEVICE__ float rsqrtf(float __a) { return __nv_rsqrtf(__a); }
__DEVICE__ double scalbn(double __a, int __b) { return __nv_scalbn(__a, __b); }
diff --git a/src/llvm-project/clang/lib/Headers/__clang_cuda_runtime_wrapper.h b/src/llvm-project/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
index f88c39a..f401964 100644
--- a/src/llvm-project/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
+++ b/src/llvm-project/clang/lib/Headers/__clang_cuda_runtime_wrapper.h
@@ -349,9 +349,14 @@
__device__ int vprintf(const char *, const char *);
__device__ void free(void *) __attribute((nothrow));
__device__ void *malloc(size_t) __attribute((nothrow)) __attribute__((malloc));
+
+// __assertfail() used to have a `noreturn` attribute. Unfortunately that
+// contributed to triggering the longstanding bug in ptxas when assert was used
+// in sufficiently convoluted code. See
+// https://bugs.llvm.org/show_bug.cgi?id=27738 for the details.
__device__ void __assertfail(const char *__message, const char *__file,
unsigned __line, const char *__function,
- size_t __charSize) __attribute__((noreturn));
+ size_t __charSize);
// In order for standard assert() macro on linux to work we need to
// provide device-side __assert_fail()
diff --git a/src/llvm-project/clang/lib/Headers/__clang_hip_cmath.h b/src/llvm-project/clang/lib/Headers/__clang_hip_cmath.h
index cd22a2d..7342705 100644
--- a/src/llvm-project/clang/lib/Headers/__clang_hip_cmath.h
+++ b/src/llvm-project/clang/lib/Headers/__clang_hip_cmath.h
@@ -14,6 +14,7 @@
#error "This file is for HIP and OpenMP AMDGCN device compilation only."
#endif
+#if !defined(__HIPCC_RTC__)
#if defined(__cplusplus)
#include <limits>
#include <type_traits>
@@ -21,6 +22,7 @@
#endif
#include <limits.h>
#include <stdint.h>
+#endif // !defined(__HIPCC_RTC__)
#pragma push_macro("__DEVICE__")
#define __DEVICE__ static __device__ inline __attribute__((always_inline))
@@ -34,6 +36,9 @@
__DEVICE__ float fma(float __x, float __y, float __z) {
return ::fmaf(__x, __y, __z);
}
+#if !defined(__HIPCC_RTC__)
+// The value returned by fpclassify is platform dependent, therefore it is not
+// supported by hipRTC.
__DEVICE__ int fpclassify(float __x) {
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL,
FP_ZERO, __x);
@@ -42,11 +47,51 @@
return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL,
FP_ZERO, __x);
}
+#endif // !defined(__HIPCC_RTC__)
+
__DEVICE__ float frexp(float __arg, int *__exp) {
return ::frexpf(__arg, __exp);
}
+
+#if defined(__OPENMP_AMDGCN__)
+// For OpenMP we work around some old system headers that have non-conforming
+// `isinf(float)` and `isnan(float)` implementations that return an `int`. We do
+// this by providing two versions of these functions, differing only in the
+// return type. To avoid conflicting definitions we disable implicit base
+// function generation. That means we will end up with two specializations, one
+// per type, but only one has a base function defined by the system header.
+#pragma omp begin declare variant match( \
+ implementation = {extension(disable_implicit_base)})
+
+// FIXME: We lack an extension to customize the mangling of the variants, e.g.,
+// add a suffix. This means we would clash with the names of the variants
+// (note that we do not create implicit base functions here). To avoid
+// this clash we add a new trait to some of them that is always true
+// (this is LLVM after all ;)). It will only influence the mangled name
+// of the variants inside the inner region and avoid the clash.
+#pragma omp begin declare variant match(implementation = {vendor(llvm)})
+
+__DEVICE__ int isinf(float __x) { return ::__isinff(__x); }
+__DEVICE__ int isinf(double __x) { return ::__isinf(__x); }
+__DEVICE__ int isfinite(float __x) { return ::__finitef(__x); }
+__DEVICE__ int isfinite(double __x) { return ::__finite(__x); }
+__DEVICE__ int isnan(float __x) { return ::__isnanf(__x); }
+__DEVICE__ int isnan(double __x) { return ::__isnan(__x); }
+
+#pragma omp end declare variant
+#endif // defined(__OPENMP_AMDGCN__)
+
+__DEVICE__ bool isinf(float __x) { return ::__isinff(__x); }
+__DEVICE__ bool isinf(double __x) { return ::__isinf(__x); }
__DEVICE__ bool isfinite(float __x) { return ::__finitef(__x); }
__DEVICE__ bool isfinite(double __x) { return ::__finite(__x); }
+__DEVICE__ bool isnan(float __x) { return ::__isnanf(__x); }
+__DEVICE__ bool isnan(double __x) { return ::__isnan(__x); }
+
+#if defined(__OPENMP_AMDGCN__)
+#pragma omp end declare variant
+#endif // defined(__OPENMP_AMDGCN__)
+
__DEVICE__ bool isgreater(float __x, float __y) {
return __builtin_isgreater(__x, __y);
}
@@ -59,8 +104,6 @@
__DEVICE__ bool isgreaterequal(double __x, double __y) {
return __builtin_isgreaterequal(__x, __y);
}
-__DEVICE__ bool isinf(float __x) { return ::__isinff(__x); }
-__DEVICE__ bool isinf(double __x) { return ::__isinf(__x); }
__DEVICE__ bool isless(float __x, float __y) {
return __builtin_isless(__x, __y);
}
@@ -79,8 +122,6 @@
__DEVICE__ bool islessgreater(double __x, double __y) {
return __builtin_islessgreater(__x, __y);
}
-__DEVICE__ bool isnan(float __x) { return ::__isnanf(__x); }
-__DEVICE__ bool isnan(double __x) { return ::__isnan(__x); }
__DEVICE__ bool isnormal(float __x) { return __builtin_isnormal(__x); }
__DEVICE__ bool isnormal(double __x) { return __builtin_isnormal(__x); }
__DEVICE__ bool isunordered(float __x, float __y) {
@@ -207,11 +248,117 @@
template <class __T> struct __hip_enable_if<true, __T> { typedef __T type; };
+namespace __hip {
+template <class _Tp> struct is_integral {
+ enum { value = 0 };
+};
+template <> struct is_integral<bool> {
+ enum { value = 1 };
+};
+template <> struct is_integral<char> {
+ enum { value = 1 };
+};
+template <> struct is_integral<signed char> {
+ enum { value = 1 };
+};
+template <> struct is_integral<unsigned char> {
+ enum { value = 1 };
+};
+template <> struct is_integral<wchar_t> {
+ enum { value = 1 };
+};
+template <> struct is_integral<short> {
+ enum { value = 1 };
+};
+template <> struct is_integral<unsigned short> {
+ enum { value = 1 };
+};
+template <> struct is_integral<int> {
+ enum { value = 1 };
+};
+template <> struct is_integral<unsigned int> {
+ enum { value = 1 };
+};
+template <> struct is_integral<long> {
+ enum { value = 1 };
+};
+template <> struct is_integral<unsigned long> {
+ enum { value = 1 };
+};
+template <> struct is_integral<long long> {
+ enum { value = 1 };
+};
+template <> struct is_integral<unsigned long long> {
+ enum { value = 1 };
+};
+
+// ToDo: specializes is_arithmetic<_Float16>
+template <class _Tp> struct is_arithmetic {
+ enum { value = 0 };
+};
+template <> struct is_arithmetic<bool> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<char> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<signed char> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<unsigned char> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<wchar_t> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<short> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<unsigned short> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<int> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<unsigned int> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<long> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<unsigned long> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<long long> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<unsigned long long> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<float> {
+ enum { value = 1 };
+};
+template <> struct is_arithmetic<double> {
+ enum { value = 1 };
+};
+
+struct true_type {
+ static const __constant__ bool value = true;
+};
+struct false_type {
+ static const __constant__ bool value = false;
+};
+
+template <typename __T, typename __U> struct is_same : public false_type {};
+template <typename __T> struct is_same<__T, __T> : public true_type {};
+
+template <typename __T> struct add_rvalue_reference { typedef __T &&type; };
+
+template <typename __T> typename add_rvalue_reference<__T>::type declval();
+
// decltype is only available in C++11 and above.
#if __cplusplus >= 201103L
// __hip_promote
-namespace __hip {
-
template <class _Tp> struct __numeric_type {
static void __test(...);
static _Float16 __test(_Float16);
@@ -227,8 +374,8 @@
// No support for long double, use double instead.
static double __test(long double);
- typedef decltype(__test(std::declval<_Tp>())) type;
- static const bool value = !std::is_same<type, void>::value;
+ typedef decltype(__test(declval<_Tp>())) type;
+ static const bool value = !is_same<type, void>::value;
};
template <> struct __numeric_type<void> { static const bool value = true; };
@@ -271,18 +418,17 @@
template <class _A1, class _A2 = void, class _A3 = void>
class __promote : public __promote_imp<_A1, _A2, _A3> {};
-
-} // namespace __hip
#endif //__cplusplus >= 201103L
+} // namespace __hip
// __HIP_OVERLOAD1 is used to resolve function calls with integer argument to
// avoid compilation error due to ambibuity. e.g. floor(5) is resolved with
// floor(double).
#define __HIP_OVERLOAD1(__retty, __fn) \
template <typename __T> \
- __DEVICE__ typename __hip_enable_if<std::numeric_limits<__T>::is_integer, \
- __retty>::type \
- __fn(__T __x) { \
+ __DEVICE__ \
+ typename __hip_enable_if<__hip::is_integral<__T>::value, __retty>::type \
+ __fn(__T __x) { \
return ::__fn((double)__x); \
}
@@ -293,8 +439,7 @@
#define __HIP_OVERLOAD2(__retty, __fn) \
template <typename __T1, typename __T2> \
__DEVICE__ typename __hip_enable_if< \
- std::numeric_limits<__T1>::is_specialized && \
- std::numeric_limits<__T2>::is_specialized, \
+ __hip::is_arithmetic<__T1>::value && __hip::is_arithmetic<__T2>::value, \
typename __hip::__promote<__T1, __T2>::type>::type \
__fn(__T1 __x, __T2 __y) { \
typedef typename __hip::__promote<__T1, __T2>::type __result_type; \
@@ -303,16 +448,14 @@
#else
#define __HIP_OVERLOAD2(__retty, __fn) \
template <typename __T1, typename __T2> \
- __DEVICE__ \
- typename __hip_enable_if<std::numeric_limits<__T1>::is_specialized && \
- std::numeric_limits<__T2>::is_specialized, \
- __retty>::type \
- __fn(__T1 __x, __T2 __y) { \
+ __DEVICE__ typename __hip_enable_if<__hip::is_arithmetic<__T1>::value && \
+ __hip::is_arithmetic<__T2>::value, \
+ __retty>::type \
+ __fn(__T1 __x, __T2 __y) { \
return __fn((double)__x, (double)__y); \
}
#endif
-__HIP_OVERLOAD1(double, abs)
__HIP_OVERLOAD1(double, acos)
__HIP_OVERLOAD1(double, acosh)
__HIP_OVERLOAD1(double, asin)
@@ -336,7 +479,9 @@
__HIP_OVERLOAD2(double, fmax)
__HIP_OVERLOAD2(double, fmin)
__HIP_OVERLOAD2(double, fmod)
+#if !defined(__HIPCC_RTC__)
__HIP_OVERLOAD1(int, fpclassify)
+#endif // !defined(__HIPCC_RTC__)
__HIP_OVERLOAD2(double, hypot)
__HIP_OVERLOAD1(int, ilogb)
__HIP_OVERLOAD1(bool, isfinite)
@@ -382,9 +527,8 @@
#if __cplusplus >= 201103L
template <typename __T1, typename __T2, typename __T3>
__DEVICE__ typename __hip_enable_if<
- std::numeric_limits<__T1>::is_specialized &&
- std::numeric_limits<__T2>::is_specialized &&
- std::numeric_limits<__T3>::is_specialized,
+ __hip::is_arithmetic<__T1>::value && __hip::is_arithmetic<__T2>::value &&
+ __hip::is_arithmetic<__T3>::value,
typename __hip::__promote<__T1, __T2, __T3>::type>::type
fma(__T1 __x, __T2 __y, __T3 __z) {
typedef typename __hip::__promote<__T1, __T2, __T3>::type __result_type;
@@ -392,33 +536,32 @@
}
#else
template <typename __T1, typename __T2, typename __T3>
-__DEVICE__
- typename __hip_enable_if<std::numeric_limits<__T1>::is_specialized &&
- std::numeric_limits<__T2>::is_specialized &&
- std::numeric_limits<__T3>::is_specialized,
- double>::type
- fma(__T1 __x, __T2 __y, __T3 __z) {
+__DEVICE__ typename __hip_enable_if<__hip::is_arithmetic<__T1>::value &&
+ __hip::is_arithmetic<__T2>::value &&
+ __hip::is_arithmetic<__T3>::value,
+ double>::type
+fma(__T1 __x, __T2 __y, __T3 __z) {
return ::fma((double)__x, (double)__y, (double)__z);
}
#endif
template <typename __T>
__DEVICE__
- typename __hip_enable_if<std::numeric_limits<__T>::is_integer, double>::type
+ typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type
frexp(__T __x, int *__exp) {
return ::frexp((double)__x, __exp);
}
template <typename __T>
__DEVICE__
- typename __hip_enable_if<std::numeric_limits<__T>::is_integer, double>::type
+ typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type
ldexp(__T __x, int __exp) {
return ::ldexp((double)__x, __exp);
}
template <typename __T>
__DEVICE__
- typename __hip_enable_if<std::numeric_limits<__T>::is_integer, double>::type
+ typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type
modf(__T __x, double *__exp) {
return ::modf((double)__x, __exp);
}
@@ -426,8 +569,8 @@
#if __cplusplus >= 201103L
template <typename __T1, typename __T2>
__DEVICE__
- typename __hip_enable_if<std::numeric_limits<__T1>::is_specialized &&
- std::numeric_limits<__T2>::is_specialized,
+ typename __hip_enable_if<__hip::is_arithmetic<__T1>::value &&
+ __hip::is_arithmetic<__T2>::value,
typename __hip::__promote<__T1, __T2>::type>::type
remquo(__T1 __x, __T2 __y, int *__quo) {
typedef typename __hip::__promote<__T1, __T2>::type __result_type;
@@ -435,25 +578,24 @@
}
#else
template <typename __T1, typename __T2>
-__DEVICE__
- typename __hip_enable_if<std::numeric_limits<__T1>::is_specialized &&
- std::numeric_limits<__T2>::is_specialized,
- double>::type
- remquo(__T1 __x, __T2 __y, int *__quo) {
+__DEVICE__ typename __hip_enable_if<__hip::is_arithmetic<__T1>::value &&
+ __hip::is_arithmetic<__T2>::value,
+ double>::type
+remquo(__T1 __x, __T2 __y, int *__quo) {
return ::remquo((double)__x, (double)__y, __quo);
}
#endif
template <typename __T>
__DEVICE__
- typename __hip_enable_if<std::numeric_limits<__T>::is_integer, double>::type
+ typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type
scalbln(__T __x, long int __exp) {
return ::scalbln((double)__x, __exp);
}
template <typename __T>
__DEVICE__
- typename __hip_enable_if<std::numeric_limits<__T>::is_integer, double>::type
+ typename __hip_enable_if<__hip::is_integral<__T>::value, double>::type
scalbn(__T __x, int __exp) {
return ::scalbn((double)__x, __exp);
}
@@ -468,14 +610,15 @@
#endif // defined(__cplusplus)
// Define these overloads inside the namespace our standard library uses.
+#if !defined(__HIPCC_RTC__)
#ifdef _LIBCPP_BEGIN_NAMESPACE_STD
_LIBCPP_BEGIN_NAMESPACE_STD
#else
namespace std {
#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_VERSION
-#endif
-#endif
+#endif // _GLIBCXX_BEGIN_NAMESPACE_VERSION
+#endif // _LIBCPP_BEGIN_NAMESPACE_STD
// Pull the new overloads we defined above into namespace std.
// using ::abs; - This may be considered for C++.
@@ -620,11 +763,13 @@
#else
#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_VERSION
-#endif
+#endif // _GLIBCXX_BEGIN_NAMESPACE_VERSION
} // namespace std
-#endif
+#endif // _LIBCPP_END_NAMESPACE_STD
+#endif // !defined(__HIPCC_RTC__)
// Define device-side math functions from <ymath.h> on MSVC.
+#if !defined(__HIPCC_RTC__)
#if defined(_MSC_VER)
// Before VS2019, `<ymath.h>` is also included in `<limits>` and other headers.
@@ -658,6 +803,7 @@
}
#endif // defined(__cplusplus)
#endif // defined(_MSC_VER)
+#endif // !defined(__HIPCC_RTC__)
#pragma pop_macro("__DEVICE__")
diff --git a/src/llvm-project/clang/lib/Headers/__clang_hip_libdevice_declares.h b/src/llvm-project/clang/lib/Headers/__clang_hip_libdevice_declares.h
index ac98907..8be848b 100644
--- a/src/llvm-project/clang/lib/Headers/__clang_hip_libdevice_declares.h
+++ b/src/llvm-project/clang/lib/Headers/__clang_hip_libdevice_declares.h
@@ -138,14 +138,22 @@
__device__ __attribute__((const)) float __ocml_fma_rtp_f32(float, float, float);
__device__ __attribute__((const)) float __ocml_fma_rtz_f32(float, float, float);
-__device__ __attribute__((const)) float
-__llvm_amdgcn_cos_f32(float) __asm("llvm.amdgcn.cos.f32");
-__device__ __attribute__((const)) float
-__llvm_amdgcn_rcp_f32(float) __asm("llvm.amdgcn.rcp.f32");
-__device__ __attribute__((const)) float
-__llvm_amdgcn_rsq_f32(float) __asm("llvm.amdgcn.rsq.f32");
-__device__ __attribute__((const)) float
-__llvm_amdgcn_sin_f32(float) __asm("llvm.amdgcn.sin.f32");
+__device__ inline __attribute__((const)) float
+__llvm_amdgcn_cos_f32(float __x) {
+ return __builtin_amdgcn_cosf(__x);
+}
+__device__ inline __attribute__((const)) float
+__llvm_amdgcn_rcp_f32(float __x) {
+ return __builtin_amdgcn_rcpf(__x);
+}
+__device__ inline __attribute__((const)) float
+__llvm_amdgcn_rsq_f32(float __x) {
+ return __builtin_amdgcn_rsqf(__x);
+}
+__device__ inline __attribute__((const)) float
+__llvm_amdgcn_sin_f32(float __x) {
+ return __builtin_amdgcn_sinf(__x);
+}
// END INTRINSICS
// END FLOAT
@@ -269,10 +277,14 @@
__device__ __attribute__((const)) double __ocml_fma_rtz_f64(double, double,
double);
-__device__ __attribute__((const)) double
-__llvm_amdgcn_rcp_f64(double) __asm("llvm.amdgcn.rcp.f64");
-__device__ __attribute__((const)) double
-__llvm_amdgcn_rsq_f64(double) __asm("llvm.amdgcn.rsq.f64");
+__device__ inline __attribute__((const)) double
+__llvm_amdgcn_rcp_f64(double __x) {
+ return __builtin_amdgcn_rcp(__x);
+}
+__device__ inline __attribute__((const)) double
+__llvm_amdgcn_rsq_f64(double __x) {
+ return __builtin_amdgcn_rsq(__x);
+}
__device__ __attribute__((const)) _Float16 __ocml_ceil_f16(_Float16);
__device__ _Float16 __ocml_cos_f16(_Float16);
diff --git a/src/llvm-project/clang/lib/Headers/__clang_hip_math.h b/src/llvm-project/clang/lib/Headers/__clang_hip_math.h
index 14d91c6..1f0982d 100644
--- a/src/llvm-project/clang/lib/Headers/__clang_hip_math.h
+++ b/src/llvm-project/clang/lib/Headers/__clang_hip_math.h
@@ -13,11 +13,13 @@
#error "This file is for HIP and OpenMP AMDGCN device compilation only."
#endif
+#if !defined(__HIPCC_RTC__)
#if defined(__cplusplus)
#include <algorithm>
#endif
#include <limits.h>
#include <stdint.h>
+#endif // __HIPCC_RTC__
#pragma push_macro("__DEVICE__")
#define __DEVICE__ static __device__ inline __attribute__((always_inline))
@@ -36,7 +38,7 @@
struct __compare_result{};
template<>
struct __compare_result<true> {
- static const bool valid;
+ static const __device__ bool valid;
};
__DEVICE__
@@ -1260,6 +1262,7 @@
__DEVICE__
double min(double __x, double __y) { return fmin(__x, __y); }
+#if !defined(__HIPCC_RTC__)
__host__ inline static int min(int __arg1, int __arg2) {
return std::min(__arg1, __arg2);
}
@@ -1267,6 +1270,7 @@
__host__ inline static int max(int __arg1, int __arg2) {
return std::max(__arg1, __arg2);
}
+#endif // __HIPCC_RTC__
#endif
#pragma pop_macro("__DEVICE__")
diff --git a/src/llvm-project/clang/lib/Headers/__clang_hip_runtime_wrapper.h b/src/llvm-project/clang/lib/Headers/__clang_hip_runtime_wrapper.h
index 81a16a2..73021d2 100644
--- a/src/llvm-project/clang/lib/Headers/__clang_hip_runtime_wrapper.h
+++ b/src/llvm-project/clang/lib/Headers/__clang_hip_runtime_wrapper.h
@@ -18,52 +18,107 @@
#if __HIP__
-#include <cmath>
-#include <cstdlib>
-#include <stdlib.h>
-
#define __host__ __attribute__((host))
#define __device__ __attribute__((device))
#define __global__ __attribute__((global))
#define __shared__ __attribute__((shared))
#define __constant__ __attribute__((constant))
+#define __managed__ __attribute__((managed))
#if !defined(__cplusplus) || __cplusplus < 201103L
#define nullptr NULL;
#endif
+#ifdef __cplusplus
+extern "C" {
+ __attribute__((__visibility__("default")))
+ __attribute__((weak))
+ __attribute__((noreturn))
+ __device__ void __cxa_pure_virtual(void) {
+ __builtin_trap();
+ }
+ __attribute__((__visibility__("default")))
+ __attribute__((weak))
+ __attribute__((noreturn))
+ __device__ void __cxa_deleted_virtual(void) {
+ __builtin_trap();
+ }
+}
+#endif //__cplusplus
+
+#if !defined(__HIPCC_RTC__)
+#include <cmath>
+#include <cstdlib>
+#include <stdlib.h>
+#else
+typedef __SIZE_TYPE__ size_t;
+// Define macros which are needed to declare HIP device API's without standard
+// C/C++ headers. This is for readability so that these API's can be written
+// the same way as non-hipRTC use case. These macros need to be popped so that
+// they do not pollute users' name space.
+#pragma push_macro("NULL")
+#pragma push_macro("uint32_t")
+#pragma push_macro("uint64_t")
+#pragma push_macro("CHAR_BIT")
+#pragma push_macro("INT_MAX")
+#define NULL (void *)0
+#define uint32_t __UINT32_TYPE__
+#define uint64_t __UINT64_TYPE__
+#define CHAR_BIT __CHAR_BIT__
+#define INT_MAX __INTMAX_MAX__
+#endif // __HIPCC_RTC__
+
+typedef __SIZE_TYPE__ __hip_size_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
#if __HIP_ENABLE_DEVICE_MALLOC__
-extern "C" __device__ void *__hip_malloc(size_t __size);
-extern "C" __device__ void *__hip_free(void *__ptr);
-static inline __device__ void *malloc(size_t __size) {
+__device__ void *__hip_malloc(__hip_size_t __size);
+__device__ void *__hip_free(void *__ptr);
+__attribute__((weak)) inline __device__ void *malloc(__hip_size_t __size) {
return __hip_malloc(__size);
}
-static inline __device__ void *free(void *__ptr) { return __hip_free(__ptr); }
-#else
-static inline __device__ void *malloc(size_t __size) {
- __builtin_trap();
- return nullptr;
+__attribute__((weak)) inline __device__ void *free(void *__ptr) {
+ return __hip_free(__ptr);
}
-static inline __device__ void *free(void *__ptr) {
+#else
+__attribute__((weak)) inline __device__ void *malloc(__hip_size_t __size) {
__builtin_trap();
- return nullptr;
+ return (void *)0;
+}
+__attribute__((weak)) inline __device__ void *free(void *__ptr) {
+ __builtin_trap();
+ return (void *)0;
}
#endif
+#ifdef __cplusplus
+} // extern "C"
+#endif //__cplusplus
+
#include <__clang_hip_libdevice_declares.h>
#include <__clang_hip_math.h>
-#if !_OPENMP || __HIP_ENABLE_CUDA_WRAPPER_FOR_OPENMP__
+#if defined(__HIPCC_RTC__)
+#include <__clang_hip_cmath.h>
+#else
#include <__clang_cuda_math_forward_declares.h>
#include <__clang_hip_cmath.h>
#include <__clang_cuda_complex_builtins.h>
-
#include <algorithm>
#include <complex>
#include <new>
-#endif // !_OPENMP || __HIP_ENABLE_CUDA_WRAPPER_FOR_OPENMP__
+#endif // __HIPCC_RTC__
#define __CLANG_HIP_RUNTIME_WRAPPER_INCLUDED__ 1
-
+#if defined(__HIPCC_RTC__)
+#pragma pop_macro("NULL")
+#pragma pop_macro("uint32_t")
+#pragma pop_macro("uint64_t")
+#pragma pop_macro("CHAR_BIT")
+#pragma pop_macro("INT_MAX")
+#endif // __HIPCC_RTC__
#endif // __HIP__
#endif // __CLANG_HIP_RUNTIME_WRAPPER_H__
diff --git a/src/llvm-project/clang/lib/Headers/altivec.h b/src/llvm-project/clang/lib/Headers/altivec.h
index 4d50d47..0dd8c85 100644
--- a/src/llvm-project/clang/lib/Headers/altivec.h
+++ b/src/llvm-project/clang/lib/Headers/altivec.h
@@ -41,9 +41,7 @@
#define __ATTRS_o_ai __attribute__((__overloadable__, __always_inline__))
-#ifdef __POWER9_VECTOR__
#include <stddef.h>
-#endif
static __inline__ vector signed char __ATTRS_o_ai vec_perm(
vector signed char __a, vector signed char __b, vector unsigned char __c);
@@ -126,7 +124,7 @@
return __builtin_altivec_vmaxsw(__a, -__a);
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __POWER8_VECTOR__
static __inline__ vector signed long long __ATTRS_o_ai
vec_abs(vector signed long long __a) {
return __builtin_altivec_vmaxsd(__a, -__a);
@@ -284,7 +282,7 @@
return __a + (vector unsigned int)__b;
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __POWER8_VECTOR__
static __inline__ vector signed long long __ATTRS_o_ai
vec_add(vector signed long long __a, vector signed long long __b) {
return __a + __b;
@@ -295,6 +293,7 @@
return __a + __b;
}
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_add(vector signed __int128 __a, vector signed __int128 __b) {
return __a + __b;
@@ -304,7 +303,37 @@
vec_add(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __a + __b;
}
-#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#endif
+
+static __inline__ vector unsigned char __attribute__((__always_inline__))
+vec_add_u128(vector unsigned char __a, vector unsigned char __b) {
+ return __builtin_altivec_vadduqm(__a, __b);
+}
+#elif defined(__VSX__)
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_add(vector signed long long __a, vector signed long long __b) {
+#ifdef __LITTLE_ENDIAN__
+ // Little endian systems on CPU's prior to Power8 don't really exist
+ // so scalarizing is fine.
+ return __a + __b;
+#else
+ vector unsigned int __res =
+ (vector unsigned int)__a + (vector unsigned int)__b;
+ vector unsigned int __carry = __builtin_altivec_vaddcuw(
+ (vector unsigned int)__a, (vector unsigned int)__b);
+ __carry = __builtin_shufflevector((vector unsigned char)__carry,
+ (vector unsigned char)__carry, 0, 0, 0, 7,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0);
+ return (vector signed long long)(__res + __carry);
+#endif
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_add(vector unsigned long long __a, vector unsigned long long __b) {
+ return (vector unsigned long long)vec_add((vector signed long long)__a,
+ (vector signed long long)__b);
+}
+#endif // __POWER8_VECTOR__
static __inline__ vector float __ATTRS_o_ai vec_add(vector float __a,
vector float __b) {
@@ -320,7 +349,8 @@
/* vec_adde */
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __POWER8_VECTOR__
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_adde(vector signed __int128 __a, vector signed __int128 __b,
vector signed __int128 __c) {
@@ -334,6 +364,13 @@
}
#endif
+static __inline__ vector unsigned char __attribute__((__always_inline__))
+vec_adde_u128(vector unsigned char __a, vector unsigned char __b,
+ vector unsigned char __c) {
+ return (vector unsigned char)__builtin_altivec_vaddeuqm(__a, __b, __c);
+}
+#endif
+
static __inline__ vector signed int __ATTRS_o_ai
vec_adde(vector signed int __a, vector signed int __b,
vector signed int __c) {
@@ -352,7 +389,8 @@
/* vec_addec */
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __POWER8_VECTOR__
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_addec(vector signed __int128 __a, vector signed __int128 __b,
vector signed __int128 __c) {
@@ -364,7 +402,15 @@
vector unsigned __int128 __c) {
return __builtin_altivec_vaddecuq(__a, __b, __c);
}
+#endif
+static __inline__ vector unsigned char __attribute__((__always_inline__))
+vec_addec_u128(vector unsigned char __a, vector unsigned char __b,
+ vector unsigned char __c) {
+ return (vector unsigned char)__builtin_altivec_vaddecuq(__a, __b, __c);
+}
+
+#ifdef __powerpc64__
static __inline__ vector signed int __ATTRS_o_ai
vec_addec(vector signed int __a, vector signed int __b,
vector signed int __c) {
@@ -407,8 +453,8 @@
vector unsigned int ret = { __result[0], __result[1], __result[2], __result[3] };
return ret;
}
-
-#endif
+#endif // __powerpc64__
+#endif // __POWER8_VECTOR__
/* vec_vaddubm */
@@ -534,7 +580,8 @@
return __builtin_altivec_vaddcuw(__a, __b);
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __POWER8_VECTOR__
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_addc(vector signed __int128 __a, vector signed __int128 __b) {
return (vector signed __int128)__builtin_altivec_vaddcuq(
@@ -545,6 +592,12 @@
vec_addc(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __builtin_altivec_vaddcuq(__a, __b);
}
+#endif
+
+static __inline__ vector unsigned char __attribute__((__always_inline__))
+vec_addc_u128(vector unsigned char __a, vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vaddcuq(__a, __b);
+}
#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
/* vec_vaddcuw */
@@ -748,7 +801,8 @@
return __builtin_altivec_vadduws(__a, (vector unsigned int)__b);
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) && \
+ defined(__SIZEOF_INT128__)
/* vec_vadduqm */
static __inline__ vector signed __int128 __ATTRS_o_ai
@@ -1598,6 +1652,17 @@
}
#endif
+/* vec_roundp */
+static __inline__ vector float __ATTRS_o_ai vec_roundp(vector float __a) {
+ return vec_ceil(__a);
+}
+
+#ifdef __VSX__
+static __inline__ vector double __ATTRS_o_ai vec_roundp(vector double __a) {
+ return vec_ceil(__a);
+}
+#endif
+
/* vec_vrfip */
static __inline__ vector float __attribute__((__always_inline__))
@@ -1690,7 +1755,31 @@
return (vector bool long long)__builtin_altivec_vcmpequd(
(vector long long)__a, (vector long long)__b);
}
+#elif defined(__VSX__)
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpeq(vector signed long long __a, vector signed long long __b) {
+ vector bool int __wordcmp =
+ vec_cmpeq((vector signed int)__a, (vector signed int)__b);
+#ifdef __LITTLE_ENDIAN__
+ __wordcmp &= __builtin_shufflevector(__wordcmp, __wordcmp, 3, 0, 1, 2);
+ return (vector bool long long)__builtin_shufflevector(__wordcmp, __wordcmp, 1,
+ 1, 3, 3);
+#else
+ __wordcmp &= __builtin_shufflevector(__wordcmp, __wordcmp, 1, 2, 3, 0);
+ return (vector bool long long)__builtin_shufflevector(__wordcmp, __wordcmp, 0,
+ 0, 2, 2);
+#endif
+}
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpeq(vector unsigned long long __a, vector unsigned long long __b) {
+ return vec_cmpeq((vector signed long long)__a, (vector signed long long)__b);
+}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpeq(vector bool long long __a, vector bool long long __b) {
+ return vec_cmpeq((vector signed long long)__a, (vector signed long long)__b);
+}
#endif
static __inline__ vector bool int __ATTRS_o_ai vec_cmpeq(vector float __a,
@@ -1709,7 +1798,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector bool __int128 __ATTRS_o_ai
vec_cmpeq(vector signed __int128 __a, vector signed __int128 __b) {
return (vector bool __int128)__builtin_altivec_vcmpequq(
@@ -1786,7 +1875,7 @@
(vector int)__b);
}
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector bool __int128 __ATTRS_o_ai
vec_cmpne(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return (vector bool __int128) ~(__builtin_altivec_vcmpequq(
@@ -1884,6 +1973,7 @@
return __builtin_altivec_vprtybw(__a);
}
+#ifdef __SIZEOF_INT128__
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_parity_lsbb(vector unsigned __int128 __a) {
return __builtin_altivec_vprtybq(__a);
@@ -1893,6 +1983,7 @@
vec_parity_lsbb(vector signed __int128 __a) {
return __builtin_altivec_vprtybq(__a);
}
+#endif
static __inline__ vector unsigned long long __ATTRS_o_ai
vec_parity_lsbb(vector unsigned long long __a) {
@@ -1976,6 +2067,24 @@
return (vector bool long long)
~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b));
}
+#elif defined(__VSX__)
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpne(vector bool long long __a, vector bool long long __b) {
+ return (vector bool long long)~(
+ vec_cmpeq((vector signed long long)__a, (vector signed long long)__b));
+}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpne(vector signed long long __a, vector signed long long __b) {
+ return (vector bool long long)~(
+ vec_cmpeq((vector signed long long)__a, (vector signed long long)__b));
+}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpne(vector unsigned long long __a, vector unsigned long long __b) {
+ return (vector bool long long)~(
+ vec_cmpeq((vector signed long long)__a, (vector signed long long)__b));
+}
#endif
#ifdef __VSX__
@@ -2028,6 +2137,46 @@
vec_cmpgt(vector unsigned long long __a, vector unsigned long long __b) {
return (vector bool long long)__builtin_altivec_vcmpgtud(__a, __b);
}
+#elif defined(__VSX__)
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpgt(vector signed long long __a, vector signed long long __b) {
+ vector signed int __sgtw = (vector signed int)vec_cmpgt(
+ (vector signed int)__a, (vector signed int)__b);
+ vector unsigned int __ugtw = (vector unsigned int)vec_cmpgt(
+ (vector unsigned int)__a, (vector unsigned int)__b);
+ vector unsigned int __eqw = (vector unsigned int)vec_cmpeq(
+ (vector signed int)__a, (vector signed int)__b);
+#ifdef __LITTLE_ENDIAN__
+ __ugtw = __builtin_shufflevector(__ugtw, __ugtw, 3, 0, 1, 2) & __eqw;
+ __sgtw |= (vector signed int)__ugtw;
+ return (vector bool long long)__builtin_shufflevector(__sgtw, __sgtw, 1, 1, 3,
+ 3);
+#else
+ __ugtw = __builtin_shufflevector(__ugtw, __ugtw, 1, 2, 3, 0) & __eqw;
+ __sgtw |= (vector signed int)__ugtw;
+ return (vector bool long long)__builtin_shufflevector(__sgtw, __sgtw, 0, 0, 2,
+ 2);
+#endif
+}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpgt(vector unsigned long long __a, vector unsigned long long __b) {
+ vector unsigned int __ugtw = (vector unsigned int)vec_cmpgt(
+ (vector unsigned int)__a, (vector unsigned int)__b);
+ vector unsigned int __eqw = (vector unsigned int)vec_cmpeq(
+ (vector signed int)__a, (vector signed int)__b);
+#ifdef __LITTLE_ENDIAN__
+ __eqw = __builtin_shufflevector(__ugtw, __ugtw, 3, 0, 1, 2) & __eqw;
+ __ugtw |= __eqw;
+ return (vector bool long long)__builtin_shufflevector(__ugtw, __ugtw, 1, 1, 3,
+ 3);
+#else
+ __eqw = __builtin_shufflevector(__ugtw, __ugtw, 1, 2, 3, 0) & __eqw;
+ __ugtw |= __eqw;
+ return (vector bool long long)__builtin_shufflevector(__ugtw, __ugtw, 0, 0, 2,
+ 2);
+#endif
+}
#endif
static __inline__ vector bool int __ATTRS_o_ai vec_cmpgt(vector float __a,
@@ -2046,7 +2195,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector bool __int128 __ATTRS_o_ai
vec_cmpgt(vector signed __int128 __a, vector signed __int128 __b) {
return (vector bool __int128)__builtin_altivec_vcmpgtsq(
@@ -2106,9 +2255,7 @@
vec_cmpge(vector double __a, vector double __b) {
return (vector bool long long)__builtin_vsx_xvcmpgedp(__a, __b);
}
-#endif
-#ifdef __POWER8_VECTOR__
static __inline__ vector bool long long __ATTRS_o_ai
vec_cmpge(vector signed long long __a, vector signed long long __b) {
return ~(vec_cmpgt(__b, __a));
@@ -2120,7 +2267,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector bool __int128 __ATTRS_o_ai
vec_cmpge(vector signed __int128 __a, vector signed __int128 __b) {
return ~(vec_cmpgt(__b, __a));
@@ -2230,9 +2377,7 @@
vec_cmple(vector double __a, vector double __b) {
return vec_cmpge(__b, __a);
}
-#endif
-#ifdef __POWER8_VECTOR__
static __inline__ vector bool long long __ATTRS_o_ai
vec_cmple(vector signed long long __a, vector signed long long __b) {
return vec_cmpge(__b, __a);
@@ -2244,7 +2389,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector bool __int128 __ATTRS_o_ai
vec_cmple(vector signed __int128 __a, vector signed __int128 __b) {
return vec_cmpge(__b, __a);
@@ -2300,7 +2445,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector bool __int128 __ATTRS_o_ai
vec_cmplt(vector signed __int128 __a, vector signed __int128 __b) {
return vec_cmpgt(__b, __a);
@@ -2312,7 +2457,7 @@
}
#endif
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ vector bool long long __ATTRS_o_ai
vec_cmplt(vector signed long long __a, vector signed long long __b) {
return vec_cmpgt(__b, __a);
@@ -2322,7 +2467,9 @@
vec_cmplt(vector unsigned long long __a, vector unsigned long long __b) {
return vec_cmpgt(__b, __a);
}
+#endif
+#ifdef __POWER8_VECTOR__
/* vec_popcnt */
static __inline__ vector signed char __ATTRS_o_ai
@@ -2358,6 +2505,7 @@
return __builtin_altivec_vpopcntd(__a);
}
+#define vec_vclz vec_cntlz
/* vec_cntlz */
static __inline__ vector signed char __ATTRS_o_ai
@@ -2870,6 +3018,7 @@
return (vector float)__builtin_vsx_lxvl(__a, (__b << 56));
}
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_xl_len(const signed __int128 *__a, size_t __b) {
return (vector signed __int128)__builtin_vsx_lxvl(__a, (__b << 56));
@@ -2879,6 +3028,7 @@
vec_xl_len(const unsigned __int128 *__a, size_t __b) {
return (vector unsigned __int128)__builtin_vsx_lxvl(__a, (__b << 56));
}
+#endif
static __inline__ vector signed long long __ATTRS_o_ai
vec_xl_len(const signed long long *__a, size_t __b) {
@@ -2946,6 +3096,7 @@
return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
}
+#ifdef __SIZEOF_INT128__
static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed __int128 __a,
signed __int128 *__b,
size_t __c) {
@@ -2957,6 +3108,7 @@
size_t __c) {
return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
}
+#endif
static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed long long __a,
signed long long *__b,
@@ -2991,6 +3143,15 @@
#endif
#endif
+#if defined(__POWER9_VECTOR__) && defined(__powerpc64__)
+#define __vec_ldrmb(PTR, CNT) vec_xl_len_r((const unsigned char *)(PTR), (CNT))
+#define __vec_strmb(PTR, CNT, VAL) \
+ vec_xst_len_r((VAL), (unsigned char *)(PTR), (CNT))
+#else
+#define __vec_ldrmb __builtin_vsx_ldrmb
+#define __vec_strmb __builtin_vsx_strmb
+#endif
+
/* vec_cpsgn */
#ifdef __VSX__
@@ -3008,6 +3169,23 @@
/* vec_ctf */
#ifdef __VSX__
+// There are some functions that have different signatures with the XL compiler
+// from those in Clang/GCC and documented in the PVIPR. This macro ensures that
+// the XL-compatible signatures are used for those functions.
+#ifdef __XL_COMPAT_ALTIVEC__
+#define vec_ctf(__a, __b) \
+ _Generic((__a), vector int \
+ : (vector float)__builtin_altivec_vcfsx((vector int)(__a), (__b)), \
+ vector unsigned int \
+ : (vector float)__builtin_altivec_vcfux((vector unsigned int)(__a), \
+ (__b)), \
+ vector unsigned long long \
+ : (__builtin_vsx_xvcvuxdsp((vector unsigned long long)(__a)) * \
+ (vector float)(vector unsigned)((0x7f - (__b)) << 23)), \
+ vector signed long long \
+ : (__builtin_vsx_xvcvsxdsp((vector signed long long)(__a)) * \
+ (vector float)(vector unsigned)((0x7f - (__b)) << 23)))
+#else // __XL_COMPAT_ALTIVEC__
#define vec_ctf(__a, __b) \
_Generic((__a), vector int \
: (vector float)__builtin_altivec_vcfsx((vector int)(__a), (__b)), \
@@ -3024,6 +3202,7 @@
vector double) * \
(vector double)(vector unsigned long long)((0x3ffULL - (__b)) \
<< 52)))
+#endif // __XL_COMPAT_ALTIVEC__
#else
#define vec_ctf(__a, __b) \
_Generic((__a), vector int \
@@ -3033,10 +3212,32 @@
(__b)))
#endif
+/* vec_ctd */
+#ifdef __VSX__
+#define vec_ctd(__a, __b) \
+ _Generic((__a), vector signed int \
+ : (vec_doublee((vector signed int)(__a)) * \
+ (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \
+ << 52)), \
+ vector unsigned int \
+ : (vec_doublee((vector unsigned int)(__a)) * \
+ (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \
+ << 52)), \
+ vector unsigned long long \
+ : (__builtin_convertvector((vector unsigned long long)(__a), \
+ vector double) * \
+ (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \
+ << 52)), \
+ vector signed long long \
+ : (__builtin_convertvector((vector signed long long)(__a), \
+ vector double) * \
+ (vector double)(vector unsigned long long)((0x3ffULL - (__b)) \
+ << 52)))
+#endif // __VSX__
+
/* vec_vcfsx */
#define vec_vcfux __builtin_altivec_vcfux
-
/* vec_vcfux */
#define vec_vcfsx(__a, __b) __builtin_altivec_vcfsx((vector int)(__a), (__b))
@@ -3044,6 +3245,19 @@
/* vec_cts */
#ifdef __VSX__
+#ifdef __XL_COMPAT_ALTIVEC__
+#define vec_cts(__a, __b) \
+ _Generic((__a), vector float \
+ : __builtin_altivec_vctsxs((vector float)(__a), (__b)), \
+ vector double \
+ : __extension__({ \
+ vector double __ret = \
+ (vector double)(__a) * \
+ (vector double)(vector unsigned long long)((0x3ffULL + (__b)) \
+ << 52); \
+ __builtin_vsx_xvcvdpsxws(__ret); \
+ }))
+#else // __XL_COMPAT_ALTIVEC__
#define vec_cts(__a, __b) \
_Generic((__a), vector float \
: __builtin_altivec_vctsxs((vector float)(__a), (__b)), \
@@ -3055,6 +3269,7 @@
<< 52); \
__builtin_convertvector(__ret, vector signed long long); \
}))
+#endif // __XL_COMPAT_ALTIVEC__
#else
#define vec_cts __builtin_altivec_vctsxs
#endif
@@ -3066,6 +3281,19 @@
/* vec_ctu */
#ifdef __VSX__
+#ifdef __XL_COMPAT_ALTIVEC__
+#define vec_ctu(__a, __b) \
+ _Generic((__a), vector float \
+ : __builtin_altivec_vctuxs((vector float)(__a), (__b)), \
+ vector double \
+ : __extension__({ \
+ vector double __ret = \
+ (vector double)(__a) * \
+ (vector double)(vector unsigned long long)((0x3ffULL + __b) \
+ << 52); \
+ __builtin_vsx_xvcvdpuxws(__ret); \
+ }))
+#else // __XL_COMPAT_ALTIVEC__
#define vec_ctu(__a, __b) \
_Generic((__a), vector float \
: __builtin_altivec_vctuxs((vector float)(__a), (__b)), \
@@ -3077,10 +3305,95 @@
<< 52); \
__builtin_convertvector(__ret, vector unsigned long long); \
}))
+#endif // __XL_COMPAT_ALTIVEC__
#else
#define vec_ctu __builtin_altivec_vctuxs
#endif
+#ifdef __LITTLE_ENDIAN__
+/* vec_ctsl */
+
+#ifdef __VSX__
+#define vec_ctsl(__a, __b) \
+ _Generic((__a), vector float \
+ : __extension__({ \
+ vector float __ret = \
+ (vector float)(__a) * \
+ (vector float)(vector unsigned)((0x7f + (__b)) << 23); \
+ __builtin_vsx_xvcvspsxds( \
+ __builtin_vsx_xxsldwi(__ret, __ret, 1)); \
+ }), \
+ vector double \
+ : __extension__({ \
+ vector double __ret = \
+ (vector double)(__a) * \
+ (vector double)(vector unsigned long long)((0x3ffULL + __b) \
+ << 52); \
+ __builtin_convertvector(__ret, vector signed long long); \
+ }))
+
+/* vec_ctul */
+
+#define vec_ctul(__a, __b) \
+ _Generic((__a), vector float \
+ : __extension__({ \
+ vector float __ret = \
+ (vector float)(__a) * \
+ (vector float)(vector unsigned)((0x7f + (__b)) << 23); \
+ __builtin_vsx_xvcvspuxds( \
+ __builtin_vsx_xxsldwi(__ret, __ret, 1)); \
+ }), \
+ vector double \
+ : __extension__({ \
+ vector double __ret = \
+ (vector double)(__a) * \
+ (vector double)(vector unsigned long long)((0x3ffULL + __b) \
+ << 52); \
+ __builtin_convertvector(__ret, vector unsigned long long); \
+ }))
+#endif
+#else // __LITTLE_ENDIAN__
+/* vec_ctsl */
+
+#ifdef __VSX__
+#define vec_ctsl(__a, __b) \
+ _Generic((__a), vector float \
+ : __extension__({ \
+ vector float __ret = \
+ (vector float)(__a) * \
+ (vector float)(vector unsigned)((0x7f + (__b)) << 23); \
+ __builtin_vsx_xvcvspsxds(__ret); \
+ }), \
+ vector double \
+ : __extension__({ \
+ vector double __ret = \
+ (vector double)(__a) * \
+ (vector double)(vector unsigned long long)((0x3ffULL + __b) \
+ << 52); \
+ __builtin_convertvector(__ret, vector signed long long); \
+ }))
+
+/* vec_ctul */
+
+#define vec_ctul(__a, __b) \
+ _Generic((__a), vector float \
+ : __extension__({ \
+ vector float __ret = \
+ (vector float)(__a) * \
+ (vector float)(vector unsigned)((0x7f + (__b)) << 23); \
+ __builtin_vsx_xvcvspuxds(__ret); \
+ }), \
+ vector double \
+ : __extension__({ \
+ vector double __ret = \
+ (vector double)(__a) * \
+ (vector double)(vector unsigned long long)((0x3ffULL + __b) \
+ << 52); \
+ __builtin_convertvector(__ret, vector unsigned long long); \
+ }))
+#endif
+#endif // __LITTLE_ENDIAN__
+
/* vec_vctuxs */
#define vec_vctuxs __builtin_altivec_vctuxs
@@ -3114,7 +3427,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_signextq(vector signed long long __a) {
return __builtin_altivec_vextsd2q(__a);
@@ -3399,6 +3712,15 @@
return __builtin_vsx_xvcvspdp(vec_sld(__a, __a, 4));
#endif
}
+
+/* vec_cvf */
+static __inline__ vector double __ATTRS_o_ai vec_cvf(vector float __a) {
+ return vec_doublee(__a);
+}
+
+static __inline__ vector float __ATTRS_o_ai vec_cvf(vector double __a) {
+ return vec_floate(__a);
+}
#endif
/* vec_div */
@@ -3481,6 +3803,7 @@
return __builtin_altivec_vdiveud(__a, __b);
}
+#ifdef __SIZEOF_INT128__
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_dive(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __builtin_altivec_vdiveuq(__a, __b);
@@ -3491,8 +3814,9 @@
return __builtin_altivec_vdivesq(__a, __b);
}
#endif
+#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_div(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __a / __b;
@@ -3661,6 +3985,17 @@
}
#endif
+/* vec_roundm */
+static __inline__ vector float __ATTRS_o_ai vec_roundm(vector float __a) {
+ return vec_floor(__a);
+}
+
+#ifdef __VSX__
+static __inline__ vector double __ATTRS_o_ai vec_roundm(vector double __a) {
+ return vec_floor(__a);
+}
+#endif
+
/* vec_vrfim */
static __inline__ vector float __attribute__((__always_inline__))
@@ -3671,251 +4006,251 @@
/* vec_ld */
static __inline__ vector signed char __ATTRS_o_ai
-vec_ld(int __a, const vector signed char *__b) {
+vec_ld(long __a, const vector signed char *__b) {
return (vector signed char)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector signed char __ATTRS_o_ai
-vec_ld(int __a, const signed char *__b) {
+vec_ld(long __a, const signed char *__b) {
return (vector signed char)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_ld(int __a, const vector unsigned char *__b) {
+vec_ld(long __a, const vector unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_ld(int __a, const unsigned char *__b) {
+vec_ld(long __a, const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector bool char __ATTRS_o_ai
-vec_ld(int __a, const vector bool char *__b) {
+vec_ld(long __a, const vector bool char *__b) {
return (vector bool char)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_ld(int __a,
+static __inline__ vector short __ATTRS_o_ai vec_ld(long __a,
const vector short *__b) {
return (vector short)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_ld(int __a, const short *__b) {
+static __inline__ vector short __ATTRS_o_ai vec_ld(long __a, const short *__b) {
return (vector short)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_ld(int __a, const vector unsigned short *__b) {
+vec_ld(long __a, const vector unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_ld(int __a, const unsigned short *__b) {
+vec_ld(long __a, const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector bool short __ATTRS_o_ai
-vec_ld(int __a, const vector bool short *__b) {
+vec_ld(long __a, const vector bool short *__b) {
return (vector bool short)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector pixel __ATTRS_o_ai vec_ld(int __a,
+static __inline__ vector pixel __ATTRS_o_ai vec_ld(long __a,
const vector pixel *__b) {
return (vector pixel)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_ld(int __a,
+static __inline__ vector int __ATTRS_o_ai vec_ld(long __a,
const vector int *__b) {
return (vector int)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_ld(int __a, const int *__b) {
+static __inline__ vector int __ATTRS_o_ai vec_ld(long __a, const int *__b) {
return (vector int)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_ld(int __a, const vector unsigned int *__b) {
+vec_ld(long __a, const vector unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_ld(int __a, const unsigned int *__b) {
+vec_ld(long __a, const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector bool int __ATTRS_o_ai
-vec_ld(int __a, const vector bool int *__b) {
+vec_ld(long __a, const vector bool int *__b) {
return (vector bool int)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_ld(int __a,
+static __inline__ vector float __ATTRS_o_ai vec_ld(long __a,
const vector float *__b) {
return (vector float)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_ld(int __a, const float *__b) {
+static __inline__ vector float __ATTRS_o_ai vec_ld(long __a, const float *__b) {
return (vector float)__builtin_altivec_lvx(__a, __b);
}
/* vec_lvx */
static __inline__ vector signed char __ATTRS_o_ai
-vec_lvx(int __a, const vector signed char *__b) {
+vec_lvx(long __a, const vector signed char *__b) {
return (vector signed char)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector signed char __ATTRS_o_ai
-vec_lvx(int __a, const signed char *__b) {
+vec_lvx(long __a, const signed char *__b) {
return (vector signed char)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_lvx(int __a, const vector unsigned char *__b) {
+vec_lvx(long __a, const vector unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_lvx(int __a, const unsigned char *__b) {
+vec_lvx(long __a, const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector bool char __ATTRS_o_ai
-vec_lvx(int __a, const vector bool char *__b) {
+vec_lvx(long __a, const vector bool char *__b) {
return (vector bool char)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_lvx(int __a,
+static __inline__ vector short __ATTRS_o_ai vec_lvx(long __a,
const vector short *__b) {
return (vector short)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_lvx(int __a, const short *__b) {
+static __inline__ vector short __ATTRS_o_ai vec_lvx(long __a, const short *__b) {
return (vector short)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_lvx(int __a, const vector unsigned short *__b) {
+vec_lvx(long __a, const vector unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_lvx(int __a, const unsigned short *__b) {
+vec_lvx(long __a, const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector bool short __ATTRS_o_ai
-vec_lvx(int __a, const vector bool short *__b) {
+vec_lvx(long __a, const vector bool short *__b) {
return (vector bool short)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector pixel __ATTRS_o_ai vec_lvx(int __a,
+static __inline__ vector pixel __ATTRS_o_ai vec_lvx(long __a,
const vector pixel *__b) {
return (vector pixel)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_lvx(int __a,
+static __inline__ vector int __ATTRS_o_ai vec_lvx(long __a,
const vector int *__b) {
return (vector int)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_lvx(int __a, const int *__b) {
+static __inline__ vector int __ATTRS_o_ai vec_lvx(long __a, const int *__b) {
return (vector int)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_lvx(int __a, const vector unsigned int *__b) {
+vec_lvx(long __a, const vector unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_lvx(int __a, const unsigned int *__b) {
+vec_lvx(long __a, const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvx(__a, __b);
}
static __inline__ vector bool int __ATTRS_o_ai
-vec_lvx(int __a, const vector bool int *__b) {
+vec_lvx(long __a, const vector bool int *__b) {
return (vector bool int)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_lvx(int __a,
+static __inline__ vector float __ATTRS_o_ai vec_lvx(long __a,
const vector float *__b) {
return (vector float)__builtin_altivec_lvx(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_lvx(int __a, const float *__b) {
+static __inline__ vector float __ATTRS_o_ai vec_lvx(long __a, const float *__b) {
return (vector float)__builtin_altivec_lvx(__a, __b);
}
/* vec_lde */
static __inline__ vector signed char __ATTRS_o_ai
-vec_lde(int __a, const signed char *__b) {
+vec_lde(long __a, const signed char *__b) {
return (vector signed char)__builtin_altivec_lvebx(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_lde(int __a, const unsigned char *__b) {
+vec_lde(long __a, const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvebx(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_lde(int __a, const short *__b) {
+static __inline__ vector short __ATTRS_o_ai vec_lde(long __a, const short *__b) {
return (vector short)__builtin_altivec_lvehx(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_lde(int __a, const unsigned short *__b) {
+vec_lde(long __a, const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvehx(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_lde(int __a, const int *__b) {
+static __inline__ vector int __ATTRS_o_ai vec_lde(long __a, const int *__b) {
return (vector int)__builtin_altivec_lvewx(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_lde(int __a, const unsigned int *__b) {
+vec_lde(long __a, const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvewx(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_lde(int __a, const float *__b) {
+static __inline__ vector float __ATTRS_o_ai vec_lde(long __a, const float *__b) {
return (vector float)__builtin_altivec_lvewx(__a, __b);
}
/* vec_lvebx */
static __inline__ vector signed char __ATTRS_o_ai
-vec_lvebx(int __a, const signed char *__b) {
+vec_lvebx(long __a, const signed char *__b) {
return (vector signed char)__builtin_altivec_lvebx(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_lvebx(int __a, const unsigned char *__b) {
+vec_lvebx(long __a, const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvebx(__a, __b);
}
/* vec_lvehx */
-static __inline__ vector short __ATTRS_o_ai vec_lvehx(int __a,
+static __inline__ vector short __ATTRS_o_ai vec_lvehx(long __a,
const short *__b) {
return (vector short)__builtin_altivec_lvehx(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_lvehx(int __a, const unsigned short *__b) {
+vec_lvehx(long __a, const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvehx(__a, __b);
}
/* vec_lvewx */
-static __inline__ vector int __ATTRS_o_ai vec_lvewx(int __a, const int *__b) {
+static __inline__ vector int __ATTRS_o_ai vec_lvewx(long __a, const int *__b) {
return (vector int)__builtin_altivec_lvewx(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_lvewx(int __a, const unsigned int *__b) {
+vec_lvewx(long __a, const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvewx(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_lvewx(int __a,
+static __inline__ vector float __ATTRS_o_ai vec_lvewx(long __a,
const float *__b) {
return (vector float)__builtin_altivec_lvewx(__a, __b);
}
@@ -3923,179 +4258,179 @@
/* vec_ldl */
static __inline__ vector signed char __ATTRS_o_ai
-vec_ldl(int __a, const vector signed char *__b) {
+vec_ldl(long __a, const vector signed char *__b) {
return (vector signed char)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector signed char __ATTRS_o_ai
-vec_ldl(int __a, const signed char *__b) {
+vec_ldl(long __a, const signed char *__b) {
return (vector signed char)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_ldl(int __a, const vector unsigned char *__b) {
+vec_ldl(long __a, const vector unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_ldl(int __a, const unsigned char *__b) {
+vec_ldl(long __a, const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector bool char __ATTRS_o_ai
-vec_ldl(int __a, const vector bool char *__b) {
+vec_ldl(long __a, const vector bool char *__b) {
return (vector bool char)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_ldl(int __a,
+static __inline__ vector short __ATTRS_o_ai vec_ldl(long __a,
const vector short *__b) {
return (vector short)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_ldl(int __a, const short *__b) {
+static __inline__ vector short __ATTRS_o_ai vec_ldl(long __a, const short *__b) {
return (vector short)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_ldl(int __a, const vector unsigned short *__b) {
+vec_ldl(long __a, const vector unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_ldl(int __a, const unsigned short *__b) {
+vec_ldl(long __a, const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector bool short __ATTRS_o_ai
-vec_ldl(int __a, const vector bool short *__b) {
+vec_ldl(long __a, const vector bool short *__b) {
return (vector bool short)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector pixel __ATTRS_o_ai vec_ldl(int __a,
+static __inline__ vector pixel __ATTRS_o_ai vec_ldl(long __a,
const vector pixel *__b) {
return (vector pixel short)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_ldl(int __a,
+static __inline__ vector int __ATTRS_o_ai vec_ldl(long __a,
const vector int *__b) {
return (vector int)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_ldl(int __a, const int *__b) {
+static __inline__ vector int __ATTRS_o_ai vec_ldl(long __a, const int *__b) {
return (vector int)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_ldl(int __a, const vector unsigned int *__b) {
+vec_ldl(long __a, const vector unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_ldl(int __a, const unsigned int *__b) {
+vec_ldl(long __a, const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector bool int __ATTRS_o_ai
-vec_ldl(int __a, const vector bool int *__b) {
+vec_ldl(long __a, const vector bool int *__b) {
return (vector bool int)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_ldl(int __a,
+static __inline__ vector float __ATTRS_o_ai vec_ldl(long __a,
const vector float *__b) {
return (vector float)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_ldl(int __a, const float *__b) {
+static __inline__ vector float __ATTRS_o_ai vec_ldl(long __a, const float *__b) {
return (vector float)__builtin_altivec_lvxl(__a, __b);
}
/* vec_lvxl */
static __inline__ vector signed char __ATTRS_o_ai
-vec_lvxl(int __a, const vector signed char *__b) {
+vec_lvxl(long __a, const vector signed char *__b) {
return (vector signed char)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector signed char __ATTRS_o_ai
-vec_lvxl(int __a, const signed char *__b) {
+vec_lvxl(long __a, const signed char *__b) {
return (vector signed char)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_lvxl(int __a, const vector unsigned char *__b) {
+vec_lvxl(long __a, const vector unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_lvxl(int __a, const unsigned char *__b) {
+vec_lvxl(long __a, const unsigned char *__b) {
return (vector unsigned char)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector bool char __ATTRS_o_ai
-vec_lvxl(int __a, const vector bool char *__b) {
+vec_lvxl(long __a, const vector bool char *__b) {
return (vector bool char)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_lvxl(int __a,
+static __inline__ vector short __ATTRS_o_ai vec_lvxl(long __a,
const vector short *__b) {
return (vector short)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector short __ATTRS_o_ai vec_lvxl(int __a,
+static __inline__ vector short __ATTRS_o_ai vec_lvxl(long __a,
const short *__b) {
return (vector short)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_lvxl(int __a, const vector unsigned short *__b) {
+vec_lvxl(long __a, const vector unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_lvxl(int __a, const unsigned short *__b) {
+vec_lvxl(long __a, const unsigned short *__b) {
return (vector unsigned short)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector bool short __ATTRS_o_ai
-vec_lvxl(int __a, const vector bool short *__b) {
+vec_lvxl(long __a, const vector bool short *__b) {
return (vector bool short)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector pixel __ATTRS_o_ai vec_lvxl(int __a,
+static __inline__ vector pixel __ATTRS_o_ai vec_lvxl(long __a,
const vector pixel *__b) {
return (vector pixel)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_lvxl(int __a,
+static __inline__ vector int __ATTRS_o_ai vec_lvxl(long __a,
const vector int *__b) {
return (vector int)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector int __ATTRS_o_ai vec_lvxl(int __a, const int *__b) {
+static __inline__ vector int __ATTRS_o_ai vec_lvxl(long __a, const int *__b) {
return (vector int)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_lvxl(int __a, const vector unsigned int *__b) {
+vec_lvxl(long __a, const vector unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector unsigned int __ATTRS_o_ai
-vec_lvxl(int __a, const unsigned int *__b) {
+vec_lvxl(long __a, const unsigned int *__b) {
return (vector unsigned int)__builtin_altivec_lvxl(__a, __b);
}
static __inline__ vector bool int __ATTRS_o_ai
-vec_lvxl(int __a, const vector bool int *__b) {
+vec_lvxl(long __a, const vector bool int *__b) {
return (vector bool int)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_lvxl(int __a,
+static __inline__ vector float __ATTRS_o_ai vec_lvxl(long __a,
const vector float *__b) {
return (vector float)__builtin_altivec_lvxl(__a, __b);
}
-static __inline__ vector float __ATTRS_o_ai vec_lvxl(int __a,
+static __inline__ vector float __ATTRS_o_ai vec_lvxl(long __a,
const float *__b) {
return (vector float)__builtin_altivec_lvxl(__a, __b);
}
@@ -5695,7 +6030,7 @@
/* vec_msumc */
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_msumc(vector unsigned long long __a, vector unsigned long long __b,
vector unsigned __int128 __c) {
@@ -5929,7 +6264,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_mule(vector signed long long __a, vector signed long long __b) {
#ifdef __LITTLE_ENDIAN__
@@ -6075,7 +6410,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_mulo(vector signed long long __a, vector signed long long __b) {
#ifdef __LITTLE_ENDIAN__
@@ -7927,7 +8262,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_rl(vector signed __int128 __a, vector unsigned __int128 __b) {
return (__b << __a)|(__b >> ((__CHAR_BIT__ * sizeof(vector signed __int128)) - __a));
@@ -7954,7 +8289,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_rlmi(vector unsigned __int128 __a, vector unsigned __int128 __b,
vector unsigned __int128 __c) {
@@ -7985,7 +8320,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_rlnm(vector unsigned __int128 __a, vector unsigned __int128 __b,
vector unsigned __int128 __c) {
@@ -8060,11 +8395,7 @@
/* vec_round */
static __inline__ vector float __ATTRS_o_ai vec_round(vector float __a) {
-#ifdef __VSX__
- return __builtin_vsx_xvrspi(__a);
-#else
return __builtin_altivec_vrfin(__a);
-#endif
}
#ifdef __VSX__
@@ -8082,6 +8413,16 @@
return __builtin_vsx_xvrdpic(__a);
}
+/* vec_roundc */
+
+static __inline__ vector float __ATTRS_o_ai vec_roundc(vector float __a) {
+ return __builtin_vsx_xvrspic(__a);
+}
+
+static __inline__ vector double __ATTRS_o_ai vec_roundc(vector double __a) {
+ return __builtin_vsx_xvrdpic(__a);
+}
+
/* vec_nearbyint */
static __inline__ vector float __ATTRS_o_ai vec_nearbyint(vector float __a) {
@@ -8128,6 +8469,16 @@
}
#endif
+static vector float __ATTRS_o_ai vec_rsqrt(vector float __a) {
+ return __builtin_ppc_rsqrtf(__a);
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_rsqrt(vector double __a) {
+ return __builtin_ppc_rsqrtd(__a);
+}
+#endif
+
/* vec_vrsqrtefp */
static __inline__ __vector float __attribute__((__always_inline__))
@@ -8488,6 +8839,52 @@
vec_sl(vector long long __a, vector unsigned long long __b) {
return (vector long long)vec_sl((vector unsigned long long)__a, __b);
}
+#else
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_vspltb(vector unsigned char __a, unsigned char __b);
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_sl(vector unsigned long long __a, vector unsigned long long __b) {
+ __b %= (vector unsigned long long)(sizeof(unsigned long long) * __CHAR_BIT__);
+
+ // Big endian element one (the right doubleword) can be left shifted as-is.
+ // The other element needs to be swapped into the right doubleword and
+ // shifted. Then the right doublewords of the two result vectors are merged.
+ vector signed long long __rightelt =
+ (vector signed long long)__builtin_altivec_vslo((vector signed int)__a,
+ (vector signed int)__b);
+#ifdef __LITTLE_ENDIAN__
+ __rightelt = (vector signed long long)__builtin_altivec_vsl(
+ (vector signed int)__rightelt,
+ (vector signed int)vec_vspltb((vector unsigned char)__b, 0));
+#else
+ __rightelt = (vector signed long long)__builtin_altivec_vsl(
+ (vector signed int)__rightelt,
+ (vector signed int)vec_vspltb((vector unsigned char)__b, 15));
+#endif
+ __a = __builtin_shufflevector(__a, __a, 1, 0);
+ __b = __builtin_shufflevector(__b, __b, 1, 0);
+ vector signed long long __leftelt =
+ (vector signed long long)__builtin_altivec_vslo((vector signed int)__a,
+ (vector signed int)__b);
+#ifdef __LITTLE_ENDIAN__
+ __leftelt = (vector signed long long)__builtin_altivec_vsl(
+ (vector signed int)__leftelt,
+ (vector signed int)vec_vspltb((vector unsigned char)__b, 0));
+ return (vector unsigned long long)__builtin_shufflevector(__rightelt,
+ __leftelt, 0, 2);
+#else
+ __leftelt = (vector signed long long)__builtin_altivec_vsl(
+ (vector signed int)__leftelt,
+ (vector signed int)vec_vspltb((vector unsigned char)__b, 15));
+ return (vector unsigned long long)__builtin_shufflevector(__leftelt,
+ __rightelt, 1, 3);
+#endif
+}
+
+static __inline__ vector long long __ATTRS_o_ai
+vec_sl(vector long long __a, vector unsigned long long __b) {
+ return (vector long long)vec_sl((vector unsigned long long)__a, __b);
+}
#endif
/* vec_vslb */
@@ -8850,6 +9247,11 @@
return vec_sld(__a, __b, ((__c << 2) & 0x0F));
}
+static __inline__ vector float __ATTRS_o_ai vec_sldw(
+ vector float __a, vector float __b, unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+
#ifdef __VSX__
static __inline__ vector signed long long __ATTRS_o_ai
vec_sldw(vector signed long long __a, vector signed long long __b,
@@ -8862,6 +9264,11 @@
unsigned const int __c) {
return vec_sld(__a, __b, ((__c << 2) & 0x0F));
}
+
+static __inline__ vector double __ATTRS_o_ai vec_sldw(
+ vector double __a, vector double __b, unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
#endif
#ifdef __POWER9_VECTOR__
@@ -9943,6 +10350,50 @@
vec_sr(vector long long __a, vector unsigned long long __b) {
return (vector long long)vec_sr((vector unsigned long long)__a, __b);
}
+#else
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_sr(vector unsigned long long __a, vector unsigned long long __b) {
+ __b %= (vector unsigned long long)(sizeof(unsigned long long) * __CHAR_BIT__);
+
+ // Big endian element zero (the left doubleword) can be right shifted as-is.
+ // However the shift amount must be in the right doubleword.
+ // The other element needs to be swapped into the left doubleword and
+ // shifted. Then the left doublewords of the two result vectors are merged.
+ vector unsigned long long __swapshift =
+ __builtin_shufflevector(__b, __b, 1, 0);
+ vector unsigned long long __leftelt =
+ (vector unsigned long long)__builtin_altivec_vsro(
+ (vector signed int)__a, (vector signed int)__swapshift);
+#ifdef __LITTLE_ENDIAN__
+ __leftelt = (vector unsigned long long)__builtin_altivec_vsr(
+ (vector signed int)__leftelt,
+ (vector signed int)vec_vspltb((vector unsigned char)__swapshift, 0));
+#else
+ __leftelt = (vector unsigned long long)__builtin_altivec_vsr(
+ (vector signed int)__leftelt,
+ (vector signed int)vec_vspltb((vector unsigned char)__swapshift, 15));
+#endif
+ __a = __builtin_shufflevector(__a, __a, 1, 0);
+ vector unsigned long long __rightelt =
+ (vector unsigned long long)__builtin_altivec_vsro((vector signed int)__a,
+ (vector signed int)__b);
+#ifdef __LITTLE_ENDIAN__
+ __rightelt = (vector unsigned long long)__builtin_altivec_vsr(
+ (vector signed int)__rightelt,
+ (vector signed int)vec_vspltb((vector unsigned char)__b, 0));
+ return __builtin_shufflevector(__rightelt, __leftelt, 1, 3);
+#else
+ __rightelt = (vector unsigned long long)__builtin_altivec_vsr(
+ (vector signed int)__rightelt,
+ (vector signed int)vec_vspltb((vector unsigned char)__b, 15));
+ return __builtin_shufflevector(__leftelt, __rightelt, 0, 2);
+#endif
+}
+
+static __inline__ vector long long __ATTRS_o_ai
+vec_sr(vector long long __a, vector unsigned long long __b) {
+ return (vector long long)vec_sr((vector unsigned long long)__a, __b);
+}
#endif
/* vec_vsrb */
@@ -10029,6 +10480,18 @@
vec_sra(vector unsigned long long __a, vector unsigned long long __b) {
return (vector unsigned long long)((vector signed long long)__a >> __b);
}
+#else
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_sra(vector signed long long __a, vector unsigned long long __b) {
+ __b %= (vector unsigned long long)(sizeof(unsigned long long) * __CHAR_BIT__);
+ return __a >> __b;
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_sra(vector unsigned long long __a, vector unsigned long long __b) {
+ __b %= (vector unsigned long long)(sizeof(unsigned long long) * __CHAR_BIT__);
+ return (vector unsigned long long)((vector signed long long)__a >> __b);
+}
#endif
/* vec_vsrab */
@@ -10635,420 +11098,420 @@
/* vec_st */
-static __inline__ void __ATTRS_o_ai vec_st(vector signed char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector signed char __a, long __b,
vector signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector signed char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector signed char __a, long __b,
signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector unsigned char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector unsigned char __a, long __b,
vector unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector unsigned char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector unsigned char __a, long __b,
unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, long __b,
signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, long __b,
unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool char __a, long __b,
vector bool char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector short __a, long __b,
vector short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector short __a, long __b,
short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector unsigned short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector unsigned short __a, long __b,
vector unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector unsigned short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector unsigned short __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, long __b,
short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool short __a, long __b,
vector bool short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, long __b,
short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector pixel __a, long __b,
vector pixel *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector int __a, long __b,
vector int *__c) {
__builtin_altivec_stvx(__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector int __a, int __b, int *__c) {
+static __inline__ void __ATTRS_o_ai vec_st(vector int __a, long __b, int *__c) {
__builtin_altivec_stvx(__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector unsigned int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector unsigned int __a, long __b,
vector unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector unsigned int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector unsigned int __a, long __b,
unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, long __b,
int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, long __b,
unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector bool int __a, long __b,
vector bool int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector float __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector float __a, long __b,
vector float *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_st(vector float __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_st(vector float __a, long __b,
float *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
/* vec_stvx */
-static __inline__ void __ATTRS_o_ai vec_stvx(vector signed char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector signed char __a, long __b,
vector signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector signed char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector signed char __a, long __b,
signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned char __a, long __b,
vector unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned char __a, long __b,
unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, long __b,
signed char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, long __b,
unsigned char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool char __a, long __b,
vector bool char *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector short __a, long __b,
vector short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector short __a, long __b,
short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned short __a, long __b,
vector unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned short __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, long __b,
short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool short __a, long __b,
vector bool short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, long __b,
short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector pixel __a, long __b,
vector pixel *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector int __a, long __b,
vector int *__c) {
__builtin_altivec_stvx(__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector int __a, long __b,
int *__c) {
__builtin_altivec_stvx(__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned int __a, long __b,
vector unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector unsigned int __a, long __b,
unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, long __b,
int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, long __b,
unsigned int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector bool int __a, long __b,
vector bool int *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector float __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector float __a, long __b,
vector float *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvx(vector float __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvx(vector float __a, long __b,
float *__c) {
__builtin_altivec_stvx((vector int)__a, __b, __c);
}
/* vec_ste */
-static __inline__ void __ATTRS_o_ai vec_ste(vector signed char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector signed char __a, long __b,
signed char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned char __a, long __b,
unsigned char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector bool char __a, long __b,
signed char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector bool char __a, long __b,
unsigned char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector short __a, long __b,
short *__c) {
__builtin_altivec_stvehx(__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned short __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector bool short __a, long __b,
short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector bool short __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector pixel __a, long __b,
short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector pixel __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector int __a, int __b, int *__c) {
+static __inline__ void __ATTRS_o_ai vec_ste(vector int __a, long __b, int *__c) {
__builtin_altivec_stvewx(__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector unsigned int __a, long __b,
unsigned int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector bool int __a, long __b,
int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector bool int __a, long __b,
unsigned int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_ste(vector float __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_ste(vector float __a, long __b,
float *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
/* vec_stvebx */
-static __inline__ void __ATTRS_o_ai vec_stvebx(vector signed char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvebx(vector signed char __a, long __b,
signed char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
static __inline__ void __ATTRS_o_ai vec_stvebx(vector unsigned char __a,
- int __b, unsigned char *__c) {
+ long __b, unsigned char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvebx(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvebx(vector bool char __a, long __b,
signed char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvebx(vector bool char __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvebx(vector bool char __a, long __b,
unsigned char *__c) {
__builtin_altivec_stvebx((vector char)__a, __b, __c);
}
/* vec_stvehx */
-static __inline__ void __ATTRS_o_ai vec_stvehx(vector short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvehx(vector short __a, long __b,
short *__c) {
__builtin_altivec_stvehx(__a, __b, __c);
}
static __inline__ void __ATTRS_o_ai vec_stvehx(vector unsigned short __a,
- int __b, unsigned short *__c) {
+ long __b, unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvehx(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvehx(vector bool short __a, long __b,
short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvehx(vector bool short __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvehx(vector bool short __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvehx(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvehx(vector pixel __a, long __b,
short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvehx(vector pixel __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvehx(vector pixel __a, long __b,
unsigned short *__c) {
__builtin_altivec_stvehx((vector short)__a, __b, __c);
}
/* vec_stvewx */
-static __inline__ void __ATTRS_o_ai vec_stvewx(vector int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvewx(vector int __a, long __b,
int *__c) {
__builtin_altivec_stvewx(__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvewx(vector unsigned int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvewx(vector unsigned int __a, long __b,
unsigned int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvewx(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvewx(vector bool int __a, long __b,
int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvewx(vector bool int __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvewx(vector bool int __a, long __b,
unsigned int *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
-static __inline__ void __ATTRS_o_ai vec_stvewx(vector float __a, int __b,
+static __inline__ void __ATTRS_o_ai vec_stvewx(vector float __a, long __b,
float *__c) {
__builtin_altivec_stvewx((vector int)__a, __b, __c);
}
@@ -11409,7 +11872,8 @@
return __a - (vector unsigned int)__b;
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) && \
+ defined(__SIZEOF_INT128__)
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_sub(vector signed __int128 __a, vector signed __int128 __b) {
return __a - __b;
@@ -11419,7 +11883,8 @@
vec_sub(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __a - __b;
}
-#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__) &&
+ // defined(__SIZEOF_INT128__)
#ifdef __VSX__
static __inline__ vector signed long long __ATTRS_o_ai
@@ -11567,7 +12032,8 @@
return __builtin_altivec_vsubcuw(__a, __b);
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __POWER8_VECTOR__
+#ifdef __SIZEOF_INT128__
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_subc(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __builtin_altivec_vsubcuq(__a, __b);
@@ -11577,7 +12043,13 @@
vec_subc(vector signed __int128 __a, vector signed __int128 __b) {
return __builtin_altivec_vsubcuq(__a, __b);
}
-#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#endif
+
+static __inline__ vector unsigned char __attribute__((__always_inline__))
+vec_subc_u128(vector unsigned char __a, vector unsigned char __b) {
+ return (vector unsigned char)__builtin_altivec_vsubcuq(__a, __b);
+}
+#endif // __POWER8_VECTOR__
/* vec_vsubcuw */
@@ -11780,9 +12252,10 @@
return __builtin_altivec_vsubuws(__a, (vector unsigned int)__b);
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __POWER8_VECTOR__
/* vec_vsubuqm */
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_vsubuqm(vector signed __int128 __a, vector signed __int128 __b) {
return __a - __b;
@@ -11792,10 +12265,16 @@
vec_vsubuqm(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __a - __b;
}
+#endif
+
+static __inline__ vector unsigned char __attribute__((__always_inline__))
+vec_sub_u128(vector unsigned char __a, vector unsigned char __b) {
+ return __builtin_altivec_vsubuqm(__a, __b);
+}
/* vec_vsubeuqm */
-
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_vsubeuqm(vector signed __int128 __a, vector signed __int128 __b,
vector signed __int128 __c) {
@@ -11819,9 +12298,17 @@
vector unsigned __int128 __c) {
return __builtin_altivec_vsubeuqm(__a, __b, __c);
}
+#endif
+
+static __inline__ vector unsigned char __attribute__((__always_inline__))
+vec_sube_u128(vector unsigned char __a, vector unsigned char __b,
+ vector unsigned char __c) {
+ return (vector unsigned char)__builtin_altivec_vsubeuqm(__a, __b, __c);
+}
/* vec_vsubcuq */
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_vsubcuq(vector signed __int128 __a, vector signed __int128 __b) {
return __builtin_altivec_vsubcuq(__a, __b);
@@ -11845,7 +12332,9 @@
vector unsigned __int128 __c) {
return __builtin_altivec_vsubecuq(__a, __b, __c);
}
+#endif
+#ifdef __powerpc64__
static __inline__ vector signed int __ATTRS_o_ai
vec_subec(vector signed int __a, vector signed int __b,
vector signed int __c) {
@@ -11857,7 +12346,9 @@
vector unsigned int __c) {
return vec_addec(__a, ~__b, __c);
}
+#endif
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_subec(vector signed __int128 __a, vector signed __int128 __b,
vector signed __int128 __c) {
@@ -11869,7 +12360,14 @@
vector unsigned __int128 __c) {
return __builtin_altivec_vsubecuq(__a, __b, __c);
}
-#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#endif
+
+static __inline__ vector unsigned char __attribute__((__always_inline__))
+vec_subec_u128(vector unsigned char __a, vector unsigned char __b,
+ vector unsigned char __c) {
+ return (vector unsigned char)__builtin_altivec_vsubecuq(__a, __b, __c);
+}
+#endif // __POWER8_VECTOR__
static __inline__ vector signed int __ATTRS_o_ai
vec_sube(vector signed int __a, vector signed int __b,
@@ -12012,6 +12510,17 @@
}
#endif
+/* vec_roundz */
+static __inline__ vector float __ATTRS_o_ai vec_roundz(vector float __a) {
+ return vec_trunc(__a);
+}
+
+#ifdef __VSX__
+static __inline__ vector double __ATTRS_o_ai vec_roundz(vector double __a) {
+ return vec_trunc(__a);
+}
+#endif
+
/* vec_vrfiz */
static __inline__ vector float __attribute__((__always_inline__))
@@ -12023,6 +12532,13 @@
/* The vector unpack instructions all have a big-endian bias, so for
little endian we must reverse the meanings of "high" and "low." */
+#ifdef __LITTLE_ENDIAN__
+#define vec_vupkhpx(__a) __builtin_altivec_vupklpx((vector short)(__a))
+#define vec_vupklpx(__a) __builtin_altivec_vupkhpx((vector short)(__a))
+#else
+#define vec_vupkhpx(__a) __builtin_altivec_vupkhpx((vector short)(__a))
+#define vec_vupklpx(__a) __builtin_altivec_vupklpx((vector short)(__a))
+#endif
static __inline__ vector short __ATTRS_o_ai
vec_unpackh(vector signed char __a) {
@@ -12558,6 +13074,16 @@
#ifdef __VSX__
#define vec_xxpermdi __builtin_vsx_xxpermdi
#define vec_xxsldwi __builtin_vsx_xxsldwi
+#define vec_permi(__a, __b, __c) \
+ _Generic((__a), vector signed long long \
+ : __builtin_shufflevector((__a), (__b), (((__c) >> 1) & 0x1), \
+ (((__c)&0x1) + 2)), \
+ vector unsigned long long \
+ : __builtin_shufflevector((__a), (__b), (((__c) >> 1) & 0x1), \
+ (((__c)&0x1) + 2)), \
+ vector double \
+ : __builtin_shufflevector((__a), (__b), (((__c) >> 1) & 0x1), \
+ (((__c)&0x1) + 2)))
#endif
/* vec_xor */
@@ -12915,73 +13441,75 @@
/* vec_extract */
static __inline__ signed char __ATTRS_o_ai vec_extract(vector signed char __a,
- int __b) {
- return __a[__b];
+ unsigned int __b) {
+ return __a[__b & 0xf];
}
static __inline__ unsigned char __ATTRS_o_ai
-vec_extract(vector unsigned char __a, int __b) {
- return __a[__b];
+vec_extract(vector unsigned char __a, unsigned int __b) {
+ return __a[__b & 0xf];
}
static __inline__ unsigned char __ATTRS_o_ai vec_extract(vector bool char __a,
- int __b) {
- return __a[__b];
+ unsigned int __b) {
+ return __a[__b & 0xf];
}
static __inline__ signed short __ATTRS_o_ai vec_extract(vector signed short __a,
- int __b) {
- return __a[__b];
+ unsigned int __b) {
+ return __a[__b & 0x7];
}
static __inline__ unsigned short __ATTRS_o_ai
-vec_extract(vector unsigned short __a, int __b) {
- return __a[__b];
+vec_extract(vector unsigned short __a, unsigned int __b) {
+ return __a[__b & 0x7];
}
static __inline__ unsigned short __ATTRS_o_ai vec_extract(vector bool short __a,
- int __b) {
- return __a[__b];
+ unsigned int __b) {
+ return __a[__b & 0x7];
}
static __inline__ signed int __ATTRS_o_ai vec_extract(vector signed int __a,
- int __b) {
- return __a[__b];
+ unsigned int __b) {
+ return __a[__b & 0x3];
}
static __inline__ unsigned int __ATTRS_o_ai vec_extract(vector unsigned int __a,
- int __b) {
- return __a[__b];
+ unsigned int __b) {
+ return __a[__b & 0x3];
}
static __inline__ unsigned int __ATTRS_o_ai vec_extract(vector bool int __a,
- int __b) {
- return __a[__b];
+ unsigned int __b) {
+ return __a[__b & 0x3];
}
#ifdef __VSX__
static __inline__ signed long long __ATTRS_o_ai
-vec_extract(vector signed long long __a, int __b) {
- return __a[__b];
+vec_extract(vector signed long long __a, unsigned int __b) {
+ return __a[__b & 0x1];
}
static __inline__ unsigned long long __ATTRS_o_ai
-vec_extract(vector unsigned long long __a, int __b) {
- return __a[__b];
+vec_extract(vector unsigned long long __a, unsigned int __b) {
+ return __a[__b & 0x1];
}
static __inline__ unsigned long long __ATTRS_o_ai
-vec_extract(vector bool long long __a, int __b) {
- return __a[__b];
+vec_extract(vector bool long long __a, unsigned int __b) {
+ return __a[__b & 0x1];
}
-static __inline__ double __ATTRS_o_ai vec_extract(vector double __a, int __b) {
- return __a[__b];
+static __inline__ double __ATTRS_o_ai vec_extract(vector double __a,
+ unsigned int __b) {
+ return __a[__b & 0x1];
}
#endif
-static __inline__ float __ATTRS_o_ai vec_extract(vector float __a, int __b) {
- return __a[__b];
+static __inline__ float __ATTRS_o_ai vec_extract(vector float __a,
+ unsigned int __b) {
+ return __a[__b & 0x3];
}
#ifdef __POWER9_VECTOR__
@@ -14022,49 +14550,71 @@
static __inline__ vector signed char __ATTRS_o_ai vec_promote(signed char __a,
int __b) {
vector signed char __res = (vector signed char)(0);
- __res[__b] = __a;
+ __res[__b & 0x7] = __a;
return __res;
}
static __inline__ vector unsigned char __ATTRS_o_ai
vec_promote(unsigned char __a, int __b) {
vector unsigned char __res = (vector unsigned char)(0);
- __res[__b] = __a;
+ __res[__b & 0x7] = __a;
return __res;
}
static __inline__ vector short __ATTRS_o_ai vec_promote(short __a, int __b) {
vector short __res = (vector short)(0);
- __res[__b] = __a;
+ __res[__b & 0x7] = __a;
return __res;
}
static __inline__ vector unsigned short __ATTRS_o_ai
vec_promote(unsigned short __a, int __b) {
vector unsigned short __res = (vector unsigned short)(0);
- __res[__b] = __a;
+ __res[__b & 0x7] = __a;
return __res;
}
static __inline__ vector int __ATTRS_o_ai vec_promote(int __a, int __b) {
vector int __res = (vector int)(0);
- __res[__b] = __a;
+ __res[__b & 0x3] = __a;
return __res;
}
static __inline__ vector unsigned int __ATTRS_o_ai vec_promote(unsigned int __a,
int __b) {
vector unsigned int __res = (vector unsigned int)(0);
- __res[__b] = __a;
+ __res[__b & 0x3] = __a;
return __res;
}
static __inline__ vector float __ATTRS_o_ai vec_promote(float __a, int __b) {
vector float __res = (vector float)(0);
- __res[__b] = __a;
+ __res[__b & 0x3] = __a;
return __res;
}
+#ifdef __VSX__
+static __inline__ vector double __ATTRS_o_ai vec_promote(double __a, int __b) {
+ vector double __res = (vector double)(0);
+ __res[__b & 0x1] = __a;
+ return __res;
+}
+
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_promote(signed long long __a, int __b) {
+ vector signed long long __res = (vector signed long long)(0);
+ __res[__b & 0x1] = __a;
+ return __res;
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_promote(unsigned long long __a, int __b) {
+ vector unsigned long long __res = (vector unsigned long long)(0);
+ __res[__b & 0x1] = __a;
+ return __res;
+}
+#endif
+
/* vec_splats */
static __inline__ vector signed char __ATTRS_o_ai vec_splats(signed char __a) {
@@ -14105,7 +14655,8 @@
return (vector unsigned long long)(__a);
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) && \
+ defined(__SIZEOF_INT128__)
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_splats(signed __int128 __a) {
return (vector signed __int128)(__a);
@@ -14258,7 +14809,7 @@
(vector int)__b);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_all_eq(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpequd_p(__CR6_LT, __a, __b);
@@ -14316,7 +14867,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_all_eq(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpequq_p(__CR6_LT, __a, __b);
@@ -14352,8 +14903,7 @@
static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool char __a,
vector signed char __b) {
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__b,
- (vector unsigned char)__a);
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, __b, (vector signed char)__a);
}
static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool char __a,
@@ -14390,8 +14940,7 @@
static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool short __a,
vector short __b) {
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__b,
- (vector unsigned short)__a);
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, __b, (vector signed short)__a);
}
static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool short __a,
@@ -14427,8 +14976,7 @@
static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool int __a,
vector int __b) {
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__b,
- (vector unsigned int)__a);
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, __b, (vector signed int)__a);
}
static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool int __a,
@@ -14442,7 +14990,7 @@
(vector unsigned int)__a);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_all_ge(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __b, __a);
@@ -14466,8 +15014,8 @@
static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool long long __a,
vector signed long long __b) {
- return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__b,
- (vector unsigned long long)__a);
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __b,
+ (vector signed long long)__a);
}
static __inline__ int __ATTRS_o_ai vec_all_ge(vector bool long long __a,
@@ -14499,7 +15047,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_all_ge(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpgtsq_p(__CR6_EQ, __b, __a);
@@ -14535,8 +15083,7 @@
static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool char __a,
vector signed char __b) {
- return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__a,
- (vector unsigned char)__b);
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT, (vector signed char)__a, __b);
}
static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool char __a,
@@ -14573,8 +15120,7 @@
static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool short __a,
vector short __b) {
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__a,
- (vector unsigned short)__b);
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT, (vector signed short)__a, __b);
}
static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool short __a,
@@ -14610,8 +15156,7 @@
static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool int __a,
vector int __b) {
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__a,
- (vector unsigned int)__b);
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT, (vector signed int)__a, __b);
}
static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool int __a,
@@ -14625,7 +15170,7 @@
(vector unsigned int)__b);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_all_gt(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __a, __b);
@@ -14649,8 +15194,8 @@
static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool long long __a,
vector signed long long __b) {
- return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__a,
- (vector unsigned long long)__b);
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT, (vector signed long long)__a,
+ __b);
}
static __inline__ int __ATTRS_o_ai vec_all_gt(vector bool long long __a,
@@ -14682,7 +15227,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_all_gt(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpgtsq_p(__CR6_LT, __a, __b);
@@ -14725,8 +15270,7 @@
static __inline__ int __ATTRS_o_ai vec_all_le(vector bool char __a,
vector signed char __b) {
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)__a,
- (vector unsigned char)__b);
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, (vector signed char)__a, __b);
}
static __inline__ int __ATTRS_o_ai vec_all_le(vector bool char __a,
@@ -14763,8 +15307,7 @@
static __inline__ int __ATTRS_o_ai vec_all_le(vector bool short __a,
vector short __b) {
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)__a,
- (vector unsigned short)__b);
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, (vector signed short)__a, __b);
}
static __inline__ int __ATTRS_o_ai vec_all_le(vector bool short __a,
@@ -14800,8 +15343,7 @@
static __inline__ int __ATTRS_o_ai vec_all_le(vector bool int __a,
vector int __b) {
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)__a,
- (vector unsigned int)__b);
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, (vector signed int)__a, __b);
}
static __inline__ int __ATTRS_o_ai vec_all_le(vector bool int __a,
@@ -14815,7 +15357,7 @@
(vector unsigned int)__b);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_all_le(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, __a, __b);
@@ -14840,8 +15382,8 @@
static __inline__ int __ATTRS_o_ai vec_all_le(vector bool long long __a,
vector signed long long __b) {
- return __builtin_altivec_vcmpgtud_p(__CR6_EQ, (vector unsigned long long)__a,
- (vector unsigned long long)__b);
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ, (vector signed long long)__a,
+ __b);
}
static __inline__ int __ATTRS_o_ai vec_all_le(vector bool long long __a,
@@ -14873,7 +15415,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_all_le(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpgtsq_p(__CR6_EQ, __a, __b);
@@ -14909,8 +15451,7 @@
static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool char __a,
vector signed char __b) {
- return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)__b,
- (vector unsigned char)__a);
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT, __b, (vector signed char)__a);
}
static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool char __a,
@@ -14947,8 +15488,7 @@
static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool short __a,
vector short __b) {
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)__b,
- (vector unsigned short)__a);
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT, __b, (vector signed short)__a);
}
static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool short __a,
@@ -14984,8 +15524,7 @@
static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool int __a,
vector int __b) {
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)__b,
- (vector unsigned int)__a);
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT, __b, (vector signed int)__a);
}
static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool int __a,
@@ -14999,7 +15538,7 @@
(vector unsigned int)__a);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_all_lt(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __b, __a);
@@ -15024,8 +15563,8 @@
static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool long long __a,
vector signed long long __b) {
- return __builtin_altivec_vcmpgtud_p(__CR6_LT, (vector unsigned long long)__b,
- (vector unsigned long long)__a);
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT, __b,
+ (vector signed long long)__a);
}
static __inline__ int __ATTRS_o_ai vec_all_lt(vector bool long long __a,
@@ -15057,7 +15596,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_all_lt(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpgtsq_p(__CR6_LT, __b, __a);
@@ -15214,7 +15753,7 @@
(vector int)__b);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_all_ne(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpequd_p(__CR6_EQ, __a, __b);
@@ -15273,7 +15812,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_all_ne(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpequq_p(__CR6_EQ, __a, __b);
@@ -15323,25 +15862,57 @@
/* vec_all_nle */
-static __inline__ int __attribute__((__always_inline__))
+static __inline__ int __ATTRS_o_ai
vec_all_nle(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgesp_p(__CR6_EQ, __b, __a);
+#else
return __builtin_altivec_vcmpgefp_p(__CR6_EQ, __b, __a);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_all_nle(vector double __a,
+ vector double __b) {
+ return __builtin_vsx_xvcmpgedp_p(__CR6_EQ, __b, __a);
+}
+#endif
+
/* vec_all_nlt */
-static __inline__ int __attribute__((__always_inline__))
+static __inline__ int __ATTRS_o_ai
vec_all_nlt(vector float __a, vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgtsp_p(__CR6_EQ, __b, __a);
+#else
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ, __b, __a);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_all_nlt(vector double __a,
+ vector double __b) {
+ return __builtin_vsx_xvcmpgtdp_p(__CR6_EQ, __b, __a);
+}
+#endif
+
/* vec_all_numeric */
-static __inline__ int __attribute__((__always_inline__))
+static __inline__ int __ATTRS_o_ai
vec_all_numeric(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpeqsp_p(__CR6_LT, __a, __a);
+#else
return __builtin_altivec_vcmpeqfp_p(__CR6_LT, __a, __a);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_all_numeric(vector double __a) {
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_LT, __a, __a);
+}
+#endif
+
/* vec_any_eq */
static __inline__ int __ATTRS_o_ai vec_any_eq(vector signed char __a,
@@ -15471,7 +16042,7 @@
(vector int)__b);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_any_eq(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpequd_p(__CR6_EQ_REV, __a, __b);
@@ -15530,7 +16101,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_any_eq(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpequq_p(__CR6_EQ_REV, __a, __b);
@@ -15568,8 +16139,8 @@
static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool char __a,
vector signed char __b) {
- return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__b,
- (vector unsigned char)__a);
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, __b,
+ (vector signed char)__a);
}
static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool char __a,
@@ -15607,8 +16178,8 @@
static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool short __a,
vector short __b) {
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__b,
- (vector unsigned short)__a);
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, __b,
+ (vector signed short)__a);
}
static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool short __a,
@@ -15645,8 +16216,8 @@
static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool int __a,
vector int __b) {
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__b,
- (vector unsigned int)__a);
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, __b,
+ (vector signed int)__a);
}
static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool int __a,
@@ -15661,7 +16232,7 @@
(vector unsigned int)__a);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_any_ge(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __b, __a);
@@ -15686,9 +16257,8 @@
static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool long long __a,
vector signed long long __b) {
- return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV,
- (vector unsigned long long)__b,
- (vector unsigned long long)__a);
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __b,
+ (vector signed long long)__a);
}
static __inline__ int __ATTRS_o_ai vec_any_ge(vector bool long long __a,
@@ -15721,7 +16291,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_any_ge(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpgtsq_p(__CR6_LT_REV, __b, __a);
@@ -15759,8 +16329,8 @@
static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool char __a,
vector signed char __b) {
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__a,
- (vector unsigned char)__b);
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, (vector signed char)__a,
+ __b);
}
static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool char __a,
@@ -15798,8 +16368,8 @@
static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool short __a,
vector short __b) {
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__a,
- (vector unsigned short)__b);
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, (vector signed short)__a,
+ __b);
}
static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool short __a,
@@ -15836,8 +16406,8 @@
static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool int __a,
vector int __b) {
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__a,
- (vector unsigned int)__b);
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, (vector signed int)__a,
+ __b);
}
static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool int __a,
@@ -15852,7 +16422,7 @@
(vector unsigned int)__b);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_any_gt(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __a, __b);
@@ -15877,9 +16447,8 @@
static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool long long __a,
vector signed long long __b) {
- return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV,
- (vector unsigned long long)__a,
- (vector unsigned long long)__b);
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV,
+ (vector signed long long)__a, __b);
}
static __inline__ int __ATTRS_o_ai vec_any_gt(vector bool long long __a,
@@ -15912,7 +16481,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_any_gt(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpgtsq_p(__CR6_EQ_REV, __a, __b);
@@ -15950,8 +16519,8 @@
static __inline__ int __ATTRS_o_ai vec_any_le(vector bool char __a,
vector signed char __b) {
- return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)__a,
- (vector unsigned char)__b);
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, (vector signed char)__a,
+ __b);
}
static __inline__ int __ATTRS_o_ai vec_any_le(vector bool char __a,
@@ -15989,8 +16558,8 @@
static __inline__ int __ATTRS_o_ai vec_any_le(vector bool short __a,
vector short __b) {
- return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)__a,
- (vector unsigned short)__b);
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, (vector signed short)__a,
+ __b);
}
static __inline__ int __ATTRS_o_ai vec_any_le(vector bool short __a,
@@ -16027,8 +16596,8 @@
static __inline__ int __ATTRS_o_ai vec_any_le(vector bool int __a,
vector int __b) {
- return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)__a,
- (vector unsigned int)__b);
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, (vector signed int)__a,
+ __b);
}
static __inline__ int __ATTRS_o_ai vec_any_le(vector bool int __a,
@@ -16043,7 +16612,7 @@
(vector unsigned int)__b);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_any_le(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV, __a, __b);
@@ -16068,9 +16637,8 @@
static __inline__ int __ATTRS_o_ai vec_any_le(vector bool long long __a,
vector signed long long __b) {
- return __builtin_altivec_vcmpgtud_p(__CR6_LT_REV,
- (vector unsigned long long)__a,
- (vector unsigned long long)__b);
+ return __builtin_altivec_vcmpgtsd_p(__CR6_LT_REV,
+ (vector signed long long)__a, __b);
}
static __inline__ int __ATTRS_o_ai vec_any_le(vector bool long long __a,
@@ -16103,7 +16671,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_any_le(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpgtsq_p(__CR6_LT_REV, __a, __b);
@@ -16141,8 +16709,8 @@
static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool char __a,
vector signed char __b) {
- return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)__b,
- (vector unsigned char)__a);
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, __b,
+ (vector signed char)__a);
}
static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool char __a,
@@ -16180,8 +16748,8 @@
static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool short __a,
vector short __b) {
- return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)__b,
- (vector unsigned short)__a);
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, __b,
+ (vector signed short)__a);
}
static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool short __a,
@@ -16218,8 +16786,8 @@
static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool int __a,
vector int __b) {
- return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)__b,
- (vector unsigned int)__a);
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, __b,
+ (vector signed int)__a);
}
static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool int __a,
@@ -16234,7 +16802,7 @@
(vector unsigned int)__a);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_any_lt(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __b, __a);
@@ -16259,9 +16827,8 @@
static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool long long __a,
vector signed long long __b) {
- return __builtin_altivec_vcmpgtud_p(__CR6_EQ_REV,
- (vector unsigned long long)__b,
- (vector unsigned long long)__a);
+ return __builtin_altivec_vcmpgtsd_p(__CR6_EQ_REV, __b,
+ (vector signed long long)__a);
}
static __inline__ int __ATTRS_o_ai vec_any_lt(vector bool long long __a,
@@ -16294,7 +16861,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_any_lt(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpgtsq_p(__CR6_EQ_REV, __b, __a);
@@ -16308,10 +16875,18 @@
/* vec_any_nan */
-static __inline__ int __attribute__((__always_inline__))
-vec_any_nan(vector float __a) {
+static __inline__ int __ATTRS_o_ai vec_any_nan(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpeqsp_p(__CR6_LT_REV, __a, __a);
+#else
return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, __a, __a);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_any_nan(vector double __a) {
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_LT_REV, __a, __a);
+}
+#endif
/* vec_any_ne */
@@ -16442,7 +17017,7 @@
(vector int)__b);
}
-#ifdef __POWER8_VECTOR__
+#ifdef __VSX__
static __inline__ int __ATTRS_o_ai vec_any_ne(vector signed long long __a,
vector signed long long __b) {
return __builtin_altivec_vcmpequd_p(__CR6_LT_REV, __a, __b);
@@ -16501,7 +17076,7 @@
}
#endif
-#ifdef __POWER10_VECTOR__
+#if defined(__POWER10_VECTOR__) && defined(__SIZEOF_INT128__)
static __inline__ int __ATTRS_o_ai vec_any_ne(vector signed __int128 __a,
vector signed __int128 __b) {
return __builtin_altivec_vcmpequq_p(__CR6_LT_REV, __a, __b);
@@ -16515,39 +17090,92 @@
/* vec_any_nge */
-static __inline__ int __attribute__((__always_inline__))
-vec_any_nge(vector float __a, vector float __b) {
+static __inline__ int __ATTRS_o_ai vec_any_nge(vector float __a,
+ vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgesp_p(__CR6_LT_REV, __a, __b);
+#else
return __builtin_altivec_vcmpgefp_p(__CR6_LT_REV, __a, __b);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_any_nge(vector double __a,
+ vector double __b) {
+ return __builtin_vsx_xvcmpgedp_p(__CR6_LT_REV, __a, __b);
+}
+#endif
+
/* vec_any_ngt */
-static __inline__ int __attribute__((__always_inline__))
-vec_any_ngt(vector float __a, vector float __b) {
+static __inline__ int __ATTRS_o_ai vec_any_ngt(vector float __a,
+ vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgtsp_p(__CR6_LT_REV, __a, __b);
+#else
return __builtin_altivec_vcmpgtfp_p(__CR6_LT_REV, __a, __b);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_any_ngt(vector double __a,
+ vector double __b) {
+ return __builtin_vsx_xvcmpgtdp_p(__CR6_LT_REV, __a, __b);
+}
+#endif
+
/* vec_any_nle */
-static __inline__ int __attribute__((__always_inline__))
-vec_any_nle(vector float __a, vector float __b) {
+static __inline__ int __ATTRS_o_ai vec_any_nle(vector float __a,
+ vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgesp_p(__CR6_LT_REV, __b, __a);
+#else
return __builtin_altivec_vcmpgefp_p(__CR6_LT_REV, __b, __a);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_any_nle(vector double __a,
+ vector double __b) {
+ return __builtin_vsx_xvcmpgedp_p(__CR6_LT_REV, __b, __a);
+}
+#endif
+
/* vec_any_nlt */
-static __inline__ int __attribute__((__always_inline__))
-vec_any_nlt(vector float __a, vector float __b) {
+static __inline__ int __ATTRS_o_ai vec_any_nlt(vector float __a,
+ vector float __b) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpgtsp_p(__CR6_LT_REV, __b, __a);
+#else
return __builtin_altivec_vcmpgtfp_p(__CR6_LT_REV, __b, __a);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_any_nlt(vector double __a,
+ vector double __b) {
+ return __builtin_vsx_xvcmpgtdp_p(__CR6_LT_REV, __b, __a);
+}
+#endif
+
/* vec_any_numeric */
-static __inline__ int __attribute__((__always_inline__))
-vec_any_numeric(vector float __a) {
+static __inline__ int __ATTRS_o_ai vec_any_numeric(vector float __a) {
+#ifdef __VSX__
+ return __builtin_vsx_xvcmpeqsp_p(__CR6_EQ_REV, __a, __a);
+#else
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, __a, __a);
+#endif
}
+#ifdef __VSX__
+static __inline__ int __ATTRS_o_ai vec_any_numeric(vector double __a) {
+ return __builtin_vsx_xvcmpeqdp_p(__CR6_EQ_REV, __a, __a);
+}
+#endif
+
/* vec_any_out */
static __inline__ int __attribute__((__always_inline__))
@@ -16696,6 +17324,16 @@
return __builtin_altivec_vgbbd(__a);
}
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_gbb(vector signed long long __a) {
+ return __builtin_altivec_vgbbd((vector unsigned char)__a);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_gbb(vector unsigned long long __a) {
+ return __builtin_altivec_vgbbd((vector unsigned char)__a);
+}
+
static __inline__ vector long long __ATTRS_o_ai
vec_vbpermq(vector signed char __a, vector signed char __b) {
return __builtin_altivec_vbpermq((vector unsigned char)__a,
@@ -16707,7 +17345,7 @@
return __builtin_altivec_vbpermq(__a, __b);
}
-#ifdef __powerpc64__
+#if defined(__powerpc64__) && defined(__SIZEOF_INT128__)
static __inline__ vector unsigned long long __attribute__((__always_inline__))
vec_bperm(vector unsigned __int128 __a, vector unsigned char __b) {
return __builtin_altivec_vbpermq((vector unsigned char)__a,
@@ -16882,7 +17520,8 @@
}
#endif /* End __VSX__ */
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) && \
+ defined(__SIZEOF_INT128__)
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_revb(vector signed __int128 __a) {
vector unsigned char __indices =
@@ -16904,6 +17543,8 @@
/* vec_xl */
+#define vec_xld2 vec_xl
+#define vec_xlw4 vec_xl
typedef vector signed char unaligned_vec_schar __attribute__((aligned(1)));
typedef vector unsigned char unaligned_vec_uchar __attribute__((aligned(1)));
typedef vector signed short unaligned_vec_sshort __attribute__((aligned(1)));
@@ -16912,41 +17553,41 @@
typedef vector unsigned int unaligned_vec_uint __attribute__((aligned(1)));
typedef vector float unaligned_vec_float __attribute__((aligned(1)));
-static inline __ATTRS_o_ai vector signed char vec_xl(signed long long __offset,
+static inline __ATTRS_o_ai vector signed char vec_xl(ptrdiff_t __offset,
const signed char *__ptr) {
return *(unaligned_vec_schar *)(__ptr + __offset);
}
static inline __ATTRS_o_ai vector unsigned char
-vec_xl(signed long long __offset, const unsigned char *__ptr) {
+vec_xl(ptrdiff_t __offset, const unsigned char *__ptr) {
return *(unaligned_vec_uchar*)(__ptr + __offset);
}
-static inline __ATTRS_o_ai vector signed short vec_xl(signed long long __offset,
- const signed short *__ptr) {
+static inline __ATTRS_o_ai vector signed short
+vec_xl(ptrdiff_t __offset, const signed short *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_sshort *)__addr;
}
static inline __ATTRS_o_ai vector unsigned short
-vec_xl(signed long long __offset, const unsigned short *__ptr) {
+vec_xl(ptrdiff_t __offset, const unsigned short *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_ushort *)__addr;
}
-static inline __ATTRS_o_ai vector signed int vec_xl(signed long long __offset,
+static inline __ATTRS_o_ai vector signed int vec_xl(ptrdiff_t __offset,
const signed int *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_sint *)__addr;
}
-static inline __ATTRS_o_ai vector unsigned int vec_xl(signed long long __offset,
- const unsigned int *__ptr) {
+static inline __ATTRS_o_ai vector unsigned int
+vec_xl(ptrdiff_t __offset, const unsigned int *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_uint *)__addr;
}
-static inline __ATTRS_o_ai vector float vec_xl(signed long long __offset,
+static inline __ATTRS_o_ai vector float vec_xl(ptrdiff_t __offset,
const float *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_float *)__addr;
@@ -16958,36 +17599,37 @@
typedef vector double unaligned_vec_double __attribute__((aligned(1)));
static inline __ATTRS_o_ai vector signed long long
-vec_xl(signed long long __offset, const signed long long *__ptr) {
+vec_xl(ptrdiff_t __offset, const signed long long *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_sll *)__addr;
}
static inline __ATTRS_o_ai vector unsigned long long
-vec_xl(signed long long __offset, const unsigned long long *__ptr) {
+vec_xl(ptrdiff_t __offset, const unsigned long long *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_ull *)__addr;
}
-static inline __ATTRS_o_ai vector double vec_xl(signed long long __offset,
+static inline __ATTRS_o_ai vector double vec_xl(ptrdiff_t __offset,
const double *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_double *)__addr;
}
#endif
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) && \
+ defined(__SIZEOF_INT128__)
typedef vector signed __int128 unaligned_vec_si128 __attribute__((aligned(1)));
typedef vector unsigned __int128 unaligned_vec_ui128
__attribute__((aligned(1)));
static inline __ATTRS_o_ai vector signed __int128
-vec_xl(signed long long __offset, const signed __int128 *__ptr) {
+vec_xl(ptrdiff_t __offset, const signed __int128 *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_si128 *)__addr;
}
static inline __ATTRS_o_ai vector unsigned __int128
-vec_xl(signed long long __offset, const unsigned __int128 *__ptr) {
+vec_xl(ptrdiff_t __offset, const unsigned __int128 *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
return *(unaligned_vec_ui128 *)__addr;
}
@@ -16997,27 +17639,27 @@
#ifdef __LITTLE_ENDIAN__
static __inline__ vector signed char __ATTRS_o_ai
-vec_xl_be(signed long long __offset, const signed char *__ptr) {
+vec_xl_be(ptrdiff_t __offset, const signed char *__ptr) {
vector signed char __vec = (vector signed char)__builtin_vsx_lxvd2x_be(__offset, __ptr);
return __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
13, 12, 11, 10, 9, 8);
}
static __inline__ vector unsigned char __ATTRS_o_ai
-vec_xl_be(signed long long __offset, const unsigned char *__ptr) {
+vec_xl_be(ptrdiff_t __offset, const unsigned char *__ptr) {
vector unsigned char __vec = (vector unsigned char)__builtin_vsx_lxvd2x_be(__offset, __ptr);
return __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
13, 12, 11, 10, 9, 8);
}
-static __inline__ vector signed short __ATTRS_o_ai
-vec_xl_be(signed long long __offset, const signed short *__ptr) {
+static __inline__ vector signed short __ATTRS_o_ai
+vec_xl_be(ptrdiff_t __offset, const signed short *__ptr) {
vector signed short __vec = (vector signed short)__builtin_vsx_lxvd2x_be(__offset, __ptr);
return __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4);
}
static __inline__ vector unsigned short __ATTRS_o_ai
-vec_xl_be(signed long long __offset, const unsigned short *__ptr) {
+vec_xl_be(ptrdiff_t __offset, const unsigned short *__ptr) {
vector unsigned short __vec = (vector unsigned short)__builtin_vsx_lxvd2x_be(__offset, __ptr);
return __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4);
}
@@ -17054,7 +17696,8 @@
}
#endif
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) && \
+ defined(__SIZEOF_INT128__)
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_xl_be(signed long long __offset, const signed __int128 *__ptr) {
return vec_xl(__offset, __ptr);
@@ -17069,98 +17712,153 @@
#define vec_xl_be vec_xl
#endif
-#if defined(__POWER10_VECTOR__) && defined(__VSX__)
+#if defined(__POWER10_VECTOR__) && defined(__VSX__) && \
+ defined(__SIZEOF_INT128__)
/* vect_xl_sext */
static __inline__ vector unsigned __int128 __ATTRS_o_ai
-vec_xl_sext(signed long long __offset, const signed char *__pointer) {
+vec_xl_sext(ptrdiff_t __offset, const signed char *__pointer) {
return (vector unsigned __int128)*(__pointer + __offset);
}
static __inline__ vector unsigned __int128 __ATTRS_o_ai
-vec_xl_sext(signed long long __offset, const signed short *__pointer) {
+vec_xl_sext(ptrdiff_t __offset, const signed short *__pointer) {
return (vector unsigned __int128)*(__pointer + __offset);
}
static __inline__ vector unsigned __int128 __ATTRS_o_ai
-vec_xl_sext(signed long long __offset, const signed int *__pointer) {
+vec_xl_sext(ptrdiff_t __offset, const signed int *__pointer) {
return (vector unsigned __int128)*(__pointer + __offset);
}
static __inline__ vector unsigned __int128 __ATTRS_o_ai
-vec_xl_sext(signed long long __offset, const signed long long *__pointer) {
+vec_xl_sext(ptrdiff_t __offset, const signed long long *__pointer) {
return (vector unsigned __int128)*(__pointer + __offset);
}
/* vec_xl_zext */
static __inline__ vector unsigned __int128 __ATTRS_o_ai
-vec_xl_zext(signed long long __offset, const unsigned char *__pointer) {
+vec_xl_zext(ptrdiff_t __offset, const unsigned char *__pointer) {
return (vector unsigned __int128)*(__pointer + __offset);
}
static __inline__ vector unsigned __int128 __ATTRS_o_ai
-vec_xl_zext(signed long long __offset, const unsigned short *__pointer) {
+vec_xl_zext(ptrdiff_t __offset, const unsigned short *__pointer) {
return (vector unsigned __int128)*(__pointer + __offset);
}
static __inline__ vector unsigned __int128 __ATTRS_o_ai
-vec_xl_zext(signed long long __offset, const unsigned int *__pointer) {
+vec_xl_zext(ptrdiff_t __offset, const unsigned int *__pointer) {
return (vector unsigned __int128)*(__pointer + __offset);
}
static __inline__ vector unsigned __int128 __ATTRS_o_ai
-vec_xl_zext(signed long long __offset, const unsigned long long *__pointer) {
+vec_xl_zext(ptrdiff_t __offset, const unsigned long long *__pointer) {
return (vector unsigned __int128)*(__pointer + __offset);
}
#endif
+/* vec_xlds */
+#ifdef __VSX__
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_xlds(ptrdiff_t __offset, const signed long long *__ptr) {
+ signed long long *__addr = (signed long long*)((signed char *)__ptr + __offset);
+ return (vector signed long long) *__addr;
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_xlds(ptrdiff_t __offset, const unsigned long long *__ptr) {
+ unsigned long long *__addr = (unsigned long long *)((signed char *)__ptr + __offset);
+ return (unaligned_vec_ull) *__addr;
+}
+
+static __inline__ vector double __ATTRS_o_ai vec_xlds(ptrdiff_t __offset,
+ const double *__ptr) {
+ double *__addr = (double*)((signed char *)__ptr + __offset);
+ return (unaligned_vec_double) *__addr;
+}
+
+/* vec_load_splats */
+static __inline__ vector signed int __ATTRS_o_ai
+vec_load_splats(signed long long __offset, const signed int *__ptr) {
+ signed int *__addr = (signed int*)((signed char *)__ptr + __offset);
+ return (vector signed int)*__addr;
+}
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_load_splats(unsigned long long __offset, const signed int *__ptr) {
+ signed int *__addr = (signed int*)((signed char *)__ptr + __offset);
+ return (vector signed int)*__addr;
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_load_splats(signed long long __offset, const unsigned int *__ptr) {
+ unsigned int *__addr = (unsigned int*)((signed char *)__ptr + __offset);
+ return (vector unsigned int)*__addr;
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_load_splats(unsigned long long __offset, const unsigned int *__ptr) {
+ unsigned int *__addr = (unsigned int*)((signed char *)__ptr + __offset);
+ return (vector unsigned int)*__addr;
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_load_splats(signed long long __offset, const float *__ptr) {
+ float *__addr = (float*)((signed char *)__ptr + __offset);
+ return (vector float)*__addr;
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_load_splats(unsigned long long __offset, const float *__ptr) {
+ float *__addr = (float*)((signed char *)__ptr + __offset);
+ return (vector float)*__addr;
+}
+#endif
+
/* vec_xst */
-static inline __ATTRS_o_ai void vec_xst(vector signed char __vec,
- signed long long __offset,
- signed char *__ptr) {
+#define vec_xstd2 vec_xst
+#define vec_xstw4 vec_xst
+static inline __ATTRS_o_ai void
+vec_xst(vector signed char __vec, ptrdiff_t __offset, signed char *__ptr) {
*(unaligned_vec_schar *)(__ptr + __offset) = __vec;
}
-static inline __ATTRS_o_ai void vec_xst(vector unsigned char __vec,
- signed long long __offset,
- unsigned char *__ptr) {
+static inline __ATTRS_o_ai void
+vec_xst(vector unsigned char __vec, ptrdiff_t __offset, unsigned char *__ptr) {
*(unaligned_vec_uchar *)(__ptr + __offset) = __vec;
}
-static inline __ATTRS_o_ai void vec_xst(vector signed short __vec,
- signed long long __offset,
- signed short *__ptr) {
+static inline __ATTRS_o_ai void
+vec_xst(vector signed short __vec, ptrdiff_t __offset, signed short *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_sshort *)__addr = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector unsigned short __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
unsigned short *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_ushort *)__addr = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector signed int __vec,
- signed long long __offset,
- signed int *__ptr) {
+ ptrdiff_t __offset, signed int *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_sint *)__addr = __vec;
}
-static inline __ATTRS_o_ai void vec_xst(vector unsigned int __vec,
- signed long long __offset,
- unsigned int *__ptr) {
+static inline __ATTRS_o_ai void
+vec_xst(vector unsigned int __vec, ptrdiff_t __offset, unsigned int *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_uint *)__addr = __vec;
}
-static inline __ATTRS_o_ai void vec_xst(vector float __vec,
- signed long long __offset,
+static inline __ATTRS_o_ai void vec_xst(vector float __vec, ptrdiff_t __offset,
float *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_float *)__addr = __vec;
@@ -17168,37 +17866,37 @@
#ifdef __VSX__
static inline __ATTRS_o_ai void vec_xst(vector signed long long __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
signed long long *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_sll *)__addr = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector unsigned long long __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
unsigned long long *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_ull *)__addr = __vec;
}
-static inline __ATTRS_o_ai void vec_xst(vector double __vec,
- signed long long __offset,
+static inline __ATTRS_o_ai void vec_xst(vector double __vec, ptrdiff_t __offset,
double *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_double *)__addr = __vec;
}
#endif
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) && \
+ defined(__SIZEOF_INT128__)
static inline __ATTRS_o_ai void vec_xst(vector signed __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
signed __int128 *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_si128 *)__addr = __vec;
}
static inline __ATTRS_o_ai void vec_xst(vector unsigned __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
unsigned __int128 *__ptr) {
signed char *__addr = (signed char *)__ptr + __offset;
*(unaligned_vec_ui128 *)__addr = __vec;
@@ -17207,51 +17905,52 @@
/* vec_xst_trunc */
-#if defined(__POWER10_VECTOR__) && defined(__VSX__)
+#if defined(__POWER10_VECTOR__) && defined(__VSX__) && \
+ defined(__SIZEOF_INT128__)
static inline __ATTRS_o_ai void vec_xst_trunc(vector signed __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
signed char *__ptr) {
*(__ptr + __offset) = (signed char)__vec[0];
}
static inline __ATTRS_o_ai void vec_xst_trunc(vector unsigned __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
unsigned char *__ptr) {
*(__ptr + __offset) = (unsigned char)__vec[0];
}
static inline __ATTRS_o_ai void vec_xst_trunc(vector signed __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
signed short *__ptr) {
*(__ptr + __offset) = (signed short)__vec[0];
}
static inline __ATTRS_o_ai void vec_xst_trunc(vector unsigned __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
unsigned short *__ptr) {
*(__ptr + __offset) = (unsigned short)__vec[0];
}
static inline __ATTRS_o_ai void vec_xst_trunc(vector signed __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
signed int *__ptr) {
*(__ptr + __offset) = (signed int)__vec[0];
}
static inline __ATTRS_o_ai void vec_xst_trunc(vector unsigned __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
unsigned int *__ptr) {
*(__ptr + __offset) = (unsigned int)__vec[0];
}
static inline __ATTRS_o_ai void vec_xst_trunc(vector signed __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
signed long long *__ptr) {
*(__ptr + __offset) = (signed long long)__vec[0];
}
static inline __ATTRS_o_ai void vec_xst_trunc(vector unsigned __int128 __vec,
- signed long long __offset,
+ ptrdiff_t __offset,
unsigned long long *__ptr) {
*(__ptr + __offset) = (unsigned long long)__vec[0];
}
@@ -17336,7 +18035,8 @@
}
#endif
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__) && \
+ defined(__SIZEOF_INT128__)
static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed __int128 __vec,
signed long long __offset,
signed __int128 *__ptr) {
@@ -17375,7 +18075,7 @@
#endif
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __VSX__
static vector long long __ATTRS_o_ai vec_neg(vector long long __a) {
return -__a;
}
@@ -17404,7 +18104,7 @@
#endif
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __POWER8_VECTOR__
static vector long long __ATTRS_o_ai vec_nabs(vector long long __a) {
return __builtin_altivec_vminsd(__a, -__a);
}
@@ -17422,6 +18122,18 @@
return __builtin_altivec_vminsb(__a, -__a);
}
+static vector float __ATTRS_o_ai vec_recipdiv(vector float __a,
+ vector float __b) {
+ return __builtin_ppc_recipdivf(__a, __b);
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_recipdiv(vector double __a,
+ vector double __b) {
+ return __builtin_ppc_recipdivd(__a, __b);
+}
+#endif
+
#ifdef __POWER10_VECTOR__
/* vec_extractm */
@@ -17446,10 +18158,12 @@
return __builtin_altivec_vextractdm(__a);
}
+#ifdef __SIZEOF_INT128__
static __inline__ unsigned int __ATTRS_o_ai
vec_extractm(vector unsigned __int128 __a) {
return __builtin_altivec_vextractqm(__a);
}
+#endif
/* vec_expandm */
@@ -17473,10 +18187,12 @@
return __builtin_altivec_vexpanddm(__a);
}
+#ifdef __SIZEOF_INT128__
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_expandm(vector unsigned __int128 __a) {
return __builtin_altivec_vexpandqm(__a);
}
+#endif
/* vec_cntm */
@@ -17512,10 +18228,12 @@
return __builtin_altivec_mtvsrdm(__bm);
}
+#ifdef __SIZEOF_INT128__
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_genqm(unsigned long long __bm) {
return __builtin_altivec_mtvsrqm(__bm);
}
+#endif
/* vec_pdep */
@@ -17544,6 +18262,7 @@
/* vec_ternarylogic */
#ifdef __VSX__
+#ifdef __SIZEOF_INT128__
#define vec_ternarylogic(__a, __b, __c, __imm) \
_Generic((__a), vector unsigned char \
: __builtin_vsx_xxeval((vector unsigned long long)(__a), \
@@ -17565,6 +18284,25 @@
: __builtin_vsx_xxeval((vector unsigned long long)(__a), \
(vector unsigned long long)(__b), \
(vector unsigned long long)(__c), (__imm)))
+#else
+#define vec_ternarylogic(__a, __b, __c, __imm) \
+ _Generic((__a), vector unsigned char \
+ : __builtin_vsx_xxeval((vector unsigned long long)(__a), \
+ (vector unsigned long long)(__b), \
+ (vector unsigned long long)(__c), (__imm)), \
+ vector unsigned short \
+ : __builtin_vsx_xxeval((vector unsigned long long)(__a), \
+ (vector unsigned long long)(__b), \
+ (vector unsigned long long)(__c), (__imm)), \
+ vector unsigned int \
+ : __builtin_vsx_xxeval((vector unsigned long long)(__a), \
+ (vector unsigned long long)(__b), \
+ (vector unsigned long long)(__c), (__imm)), \
+ vector unsigned long long \
+ : __builtin_vsx_xxeval((vector unsigned long long)(__a), \
+ (vector unsigned long long)(__b), \
+ (vector unsigned long long)(__c), (__imm)))
+#endif /* __SIZEOF_INT128__ */
#endif /* __VSX__ */
/* vec_genpcvm */
@@ -17657,6 +18395,7 @@
return __a % __b;
}
+#ifdef __SIZEOF_INT128__
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_mod(vector signed __int128 __a, vector signed __int128 __b) {
return __a % __b;
@@ -17666,6 +18405,7 @@
vec_mod(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __a % __b;
}
+#endif
/* vec_sldbi */
@@ -18188,6 +18928,7 @@
/* vs[l | r | ra] */
+#ifdef __SIZEOF_INT128__
static __inline__ vector unsigned __int128 __ATTRS_o_ai
vec_sl(vector unsigned __int128 __a, vector unsigned __int128 __b) {
return __a << (__b % (vector unsigned __int128)(sizeof(unsigned __int128) *
@@ -18232,6 +18973,7 @@
__CHAR_BIT__));
}
+#endif /* __SIZEOF_INT128__ */
#endif /* __POWER10_VECTOR__ */
#undef __ATTRS_o_ai
diff --git a/src/llvm-project/clang/lib/Headers/amxintrin.h b/src/llvm-project/clang/lib/Headers/amxintrin.h
index 823c7ca..ec601a5 100644
--- a/src/llvm-project/clang/lib/Headers/amxintrin.h
+++ b/src/llvm-project/clang/lib/Headers/amxintrin.h
@@ -15,8 +15,13 @@
#define __AMXINTRIN_H
#ifdef __x86_64__
+/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS_TILE \
__attribute__((__always_inline__, __nodebug__, __target__("amx-tile")))
+#define __DEFAULT_FN_ATTRS_INT8 \
+ __attribute__((__always_inline__, __nodebug__, __target__("amx-int8")))
+#define __DEFAULT_FN_ATTRS_BF16 \
+ __attribute__((__always_inline__, __nodebug__, __target__("amx-bf16")))
/// Load tile configuration from a 64-byte memory location specified by
/// "mem_addr". The tile configuration includes the tile type palette, the
@@ -25,7 +30,7 @@
/// config and the tile data, and the tiles are zeroed. Any invalid
/// configurations will result in #GP fault.
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> LDTILECFG </c> instruction.
///
@@ -41,7 +46,7 @@
/// palette, the number of bytes per row, and the number of rows. If tiles
/// are not configured, all zeroes will be stored to memory.
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> STTILECFG </c> instruction.
///
@@ -55,7 +60,7 @@
/// Release the tile configuration to return to the init state, which
/// releases all storage it currently holds.
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TILERELEASE </c> instruction.
static __inline__ void __DEFAULT_FN_ATTRS_TILE _tile_release(void) {
@@ -66,7 +71,7 @@
/// destination tile "dst" using the tile configuration previously configured
/// via "_tile_loadconfig".
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TILELOADD </c> instruction.
///
@@ -86,7 +91,7 @@
/// that the data will likely not be reused in the near future and the data
/// caching can be optimized accordingly.
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TILELOADDT1 </c> instruction.
///
@@ -104,7 +109,7 @@
/// "stride" using the tile configuration previously configured via
/// "_tile_loadconfig".
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TILESTORED </c> instruction.
///
@@ -119,7 +124,7 @@
/// Zero the tile specified by "tdest".
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TILEZERO </c> instruction.
///
@@ -133,7 +138,7 @@
/// results. Sum these 4 results with the corresponding 32-bit integer in "dst",
/// and store the 32-bit result back to tile "dst".
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TDPBSSD </c> instruction.
///
@@ -152,7 +157,7 @@
/// 32-bit results. Sum these 4 results with the corresponding 32-bit integer
/// in "dst", and store the 32-bit result back to tile "dst".
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TDPBSUD </c> instruction.
///
@@ -171,7 +176,7 @@
/// results. Sum these 4 results with the corresponding 32-bit integer in "dst",
/// and store the 32-bit result back to tile "dst".
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TDPBUSD </c> instruction.
///
@@ -190,7 +195,7 @@
/// 32-bit results. Sum these 4 results with the corresponding 32-bit integer in
/// "dst", and store the 32-bit result back to tile "dst".
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TDPBUUD </c> instruction.
///
@@ -208,7 +213,7 @@
/// elements with elements in "dst", and store the 32-bit result back to tile
/// "dst".
///
-/// \headerfile <x86intrin.h>
+/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TDPBF16PS </c> instruction.
///
@@ -221,10 +226,12 @@
#define _tile_dpbf16ps(dst, src0, src1) \
__builtin_ia32_tdpbf16ps((dst), (src0), (src1))
-#define __DEFAULT_FN_ATTRS_INT8 \
- __attribute__((__always_inline__, __nodebug__, __target__("amx-int8")))
-
+/// AMX tile register size can be configured, the maximum size is 16x64=1024
+/// bytes. Since there is no 2D type in llvm IR, we use vector type to
+/// represent 2D tile and the fixed size is maximum amx tile register size.
typedef int _tile1024i __attribute__((__vector_size__(1024), __aligned__(64)));
+
+/// This is internal intrinsic. C/C++ user should avoid calling it directly.
static __inline__ _tile1024i __DEFAULT_FN_ATTRS_INT8
_tile_loadd_internal(unsigned short m, unsigned short n, const void *base,
__SIZE_TYPE__ stride) {
@@ -232,12 +239,43 @@
(__SIZE_TYPE__)(stride));
}
+/// This is internal intrinsic. C/C++ user should avoid calling it directly.
+static __inline__ _tile1024i __DEFAULT_FN_ATTRS_INT8
+_tile_loaddt1_internal(unsigned short m, unsigned short n, const void *base,
+ __SIZE_TYPE__ stride) {
+ return __builtin_ia32_tileloaddt164_internal(m, n, base,
+ (__SIZE_TYPE__)(stride));
+}
+
+/// This is internal intrinsic. C/C++ user should avoid calling it directly.
static __inline__ _tile1024i __DEFAULT_FN_ATTRS_INT8
_tile_dpbssd_internal(unsigned short m, unsigned short n, unsigned short k,
_tile1024i dst, _tile1024i src1, _tile1024i src2) {
return __builtin_ia32_tdpbssd_internal(m, n, k, dst, src1, src2);
}
+/// This is internal intrinsic. C/C++ user should avoid calling it directly.
+static __inline__ _tile1024i __DEFAULT_FN_ATTRS_INT8
+_tile_dpbsud_internal(unsigned short m, unsigned short n, unsigned short k,
+ _tile1024i dst, _tile1024i src1, _tile1024i src2) {
+ return __builtin_ia32_tdpbsud_internal(m, n, k, dst, src1, src2);
+}
+
+/// This is internal intrinsic. C/C++ user should avoid calling it directly.
+static __inline__ _tile1024i __DEFAULT_FN_ATTRS_INT8
+_tile_dpbusd_internal(unsigned short m, unsigned short n, unsigned short k,
+ _tile1024i dst, _tile1024i src1, _tile1024i src2) {
+ return __builtin_ia32_tdpbusd_internal(m, n, k, dst, src1, src2);
+}
+
+/// This is internal intrinsic. C/C++ user should avoid calling it directly.
+static __inline__ _tile1024i __DEFAULT_FN_ATTRS_INT8
+_tile_dpbuud_internal(unsigned short m, unsigned short n, unsigned short k,
+ _tile1024i dst, _tile1024i src1, _tile1024i src2) {
+ return __builtin_ia32_tdpbuud_internal(m, n, k, dst, src1, src2);
+}
+
+/// This is internal intrinsic. C/C++ user should avoid calling it directly.
static __inline__ void __DEFAULT_FN_ATTRS_INT8
_tile_stored_internal(unsigned short m, unsigned short n, void *base,
__SIZE_TYPE__ stride, _tile1024i tile) {
@@ -245,34 +283,211 @@
(__SIZE_TYPE__)(stride), tile);
}
+/// This is internal intrinsic. C/C++ user should avoid calling it directly.
+static __inline__ _tile1024i __DEFAULT_FN_ATTRS_BF16
+_tile_dpbf16ps_internal(unsigned short m, unsigned short n, unsigned short k,
+ _tile1024i dst, _tile1024i src1, _tile1024i src2) {
+ return __builtin_ia32_tdpbf16ps_internal(m, n, k, dst, src1, src2);
+}
+
+/// This struct pack the shape and tile data together for user. We suggest
+/// initializing the struct as early as possible, because compiler depends
+/// on the shape information to do configure. The constant value is preferred
+/// for optimization by compiler.
typedef struct __tile1024i_str {
const unsigned short row;
const unsigned short col;
_tile1024i tile;
} __tile1024i;
+/// Load tile rows from memory specifieid by "base" address and "stride" into
+/// destination tile "dst".
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TILELOADD </c> instruction.
+///
+/// \param dst
+/// A destination tile. Max size is 1024 Bytes.
+/// \param base
+/// A pointer to base address.
+/// \param stride
+/// The stride between the rows' data to be loaded in memory.
__DEFAULT_FN_ATTRS_TILE
static void __tile_loadd(__tile1024i *dst, const void *base,
__SIZE_TYPE__ stride) {
dst->tile = _tile_loadd_internal(dst->row, dst->col, base, stride);
}
-__DEFAULT_FN_ATTRS_INT8
-static void __tile_dpbssd(__tile1024i *dst, __tile1024i src1,
- __tile1024i src2) {
- dst->tile = _tile_dpbssd_internal(src1.row, src2.col, src1.col, dst->tile,
- src1.tile, src2.tile);
+/// Load tile rows from memory specifieid by "base" address and "stride" into
+/// destination tile "dst". This intrinsic provides a hint to the implementation
+/// that the data will likely not be reused in the near future and the data
+/// caching can be optimized accordingly.
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TILELOADDT1 </c> instruction.
+///
+/// \param dst
+/// A destination tile. Max size is 1024 Bytes.
+/// \param base
+/// A pointer to base address.
+/// \param stride
+/// The stride between the rows' data to be loaded in memory.
+__DEFAULT_FN_ATTRS_TILE
+static void __tile_stream_loadd(__tile1024i *dst, const void *base,
+ __SIZE_TYPE__ stride) {
+ dst->tile = _tile_loaddt1_internal(dst->row, dst->col, base, stride);
}
+/// Compute dot-product of bytes in tiles with a source/destination accumulator.
+/// Multiply groups of 4 adjacent pairs of signed 8-bit integers in src0 with
+/// corresponding signed 8-bit integers in src1, producing 4 intermediate 32-bit
+/// results. Sum these 4 results with the corresponding 32-bit integer in "dst",
+/// and store the 32-bit result back to tile "dst".
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TDPBSSD </c> instruction.
+///
+/// \param dst
+/// The destination tile. Max size is 1024 Bytes.
+/// \param src0
+/// The 1st source tile. Max size is 1024 Bytes.
+/// \param src1
+/// The 2nd source tile. Max size is 1024 Bytes.
+__DEFAULT_FN_ATTRS_INT8
+static void __tile_dpbssd(__tile1024i *dst, __tile1024i src0,
+ __tile1024i src1) {
+ dst->tile = _tile_dpbssd_internal(src0.row, src1.col, src0.col, dst->tile,
+ src0.tile, src1.tile);
+}
+
+/// Compute dot-product of bytes in tiles with a source/destination accumulator.
+/// Multiply groups of 4 adjacent pairs of signed 8-bit integers in src0 with
+/// corresponding unsigned 8-bit integers in src1, producing 4 intermediate
+/// 32-bit results. Sum these 4 results with the corresponding 32-bit integer
+/// in "dst", and store the 32-bit result back to tile "dst".
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TDPBSUD </c> instruction.
+///
+/// \param dst
+/// The destination tile. Max size is 1024 Bytes.
+/// \param src0
+/// The 1st source tile. Max size is 1024 Bytes.
+/// \param src1
+/// The 2nd source tile. Max size is 1024 Bytes.
+__DEFAULT_FN_ATTRS_INT8
+static void __tile_dpbsud(__tile1024i *dst, __tile1024i src0,
+ __tile1024i src1) {
+ dst->tile = _tile_dpbsud_internal(src0.row, src1.col, src0.col, dst->tile,
+ src0.tile, src1.tile);
+}
+
+/// Compute dot-product of bytes in tiles with a source/destination accumulator.
+/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in src0 with
+/// corresponding signed 8-bit integers in src1, producing 4 intermediate 32-bit
+/// results. Sum these 4 results with the corresponding 32-bit integer in "dst",
+/// and store the 32-bit result back to tile "dst".
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TDPBUSD </c> instruction.
+///
+/// \param dst
+/// The destination tile. Max size is 1024 Bytes.
+/// \param src0
+/// The 1st source tile. Max size is 1024 Bytes.
+/// \param src1
+/// The 2nd source tile. Max size is 1024 Bytes.
+__DEFAULT_FN_ATTRS_INT8
+static void __tile_dpbusd(__tile1024i *dst, __tile1024i src0,
+ __tile1024i src1) {
+ dst->tile = _tile_dpbusd_internal(src0.row, src1.col, src0.col, dst->tile,
+ src0.tile, src1.tile);
+}
+
+/// Compute dot-product of bytes in tiles with a source/destination accumulator.
+/// Multiply groups of 4 adjacent pairs of unsigned 8-bit integers in src0 with
+/// corresponding unsigned 8-bit integers in src1, producing 4 intermediate
+/// 32-bit results. Sum these 4 results with the corresponding 32-bit integer in
+/// "dst", and store the 32-bit result back to tile "dst".
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TDPBUUD </c> instruction.
+///
+/// \param dst
+/// The destination tile. Max size is 1024 Bytes.
+/// \param src0
+/// The 1st source tile. Max size is 1024 Bytes.
+/// \param src1
+/// The 2nd source tile. Max size is 1024 Bytes.
+__DEFAULT_FN_ATTRS_INT8
+static void __tile_dpbuud(__tile1024i *dst, __tile1024i src0,
+ __tile1024i src1) {
+ dst->tile = _tile_dpbuud_internal(src0.row, src1.col, src0.col, dst->tile,
+ src0.tile, src1.tile);
+}
+
+/// Store the tile specified by "src" to memory specifieid by "base" address and
+/// "stride".
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TILESTORED </c> instruction.
+///
+/// \param dst
+/// A destination tile. Max size is 1024 Bytes.
+/// \param base
+/// A pointer to base address.
+/// \param stride
+/// The stride between the rows' data to be stored in memory.
__DEFAULT_FN_ATTRS_TILE
static void __tile_stored(void *base, __SIZE_TYPE__ stride, __tile1024i src) {
_tile_stored_internal(src.row, src.col, base, stride, src.tile);
}
+/// Zero the tile specified by "dst".
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TILEZERO </c> instruction.
+///
+/// \param dst
+/// The destination tile to be zero. Max size is 1024 Bytes.
__DEFAULT_FN_ATTRS_TILE
static void __tile_zero(__tile1024i *dst) {
dst->tile = __builtin_ia32_tilezero_internal(dst->row, dst->col);
}
+/// Compute dot-product of BF16 (16-bit) floating-point pairs in tiles src0 and
+/// src1, accumulating the intermediate single-precision (32-bit) floating-point
+/// elements with elements in "dst", and store the 32-bit result back to tile
+/// "dst".
+///
+/// \headerfile <immintrin.h>
+///
+/// This intrinsic corresponds to the <c> TDPBF16PS </c> instruction.
+///
+/// \param dst
+/// The destination tile. Max size is 1024 Bytes.
+/// \param src0
+/// The 1st source tile. Max size is 1024 Bytes.
+/// \param src1
+/// The 2nd source tile. Max size is 1024 Bytes.
+__DEFAULT_FN_ATTRS_BF16
+static void __tile_dpbf16ps(__tile1024i *dst, __tile1024i src0,
+ __tile1024i src1) {
+ dst->tile = _tile_dpbf16ps_internal(src0.row, src1.col, src0.col, dst->tile,
+ src0.tile, src1.tile);
+}
+
+#undef __DEFAULT_FN_ATTRS_TILE
+#undef __DEFAULT_FN_ATTRS_INT8
+#undef __DEFAULT_FN_ATTRS_BF16
+
#endif /* __x86_64__ */
#endif /* __AMXINTRIN_H */
diff --git a/src/llvm-project/clang/lib/Headers/arm_acle.h b/src/llvm-project/clang/lib/Headers/arm_acle.h
index c156d89..45fac24 100644
--- a/src/llvm-project/clang/lib/Headers/arm_acle.h
+++ b/src/llvm-project/clang/lib/Headers/arm_acle.h
@@ -639,6 +639,49 @@
}
#endif
+/* Armv8.5-A FP rounding intrinsics */
+#if __ARM_64BIT_STATE && defined(__ARM_FEATURE_FRINT)
+static __inline__ float __attribute__((__always_inline__, __nodebug__))
+__frint32zf(float __a) {
+ return __builtin_arm_frint32zf(__a);
+}
+
+static __inline__ double __attribute__((__always_inline__, __nodebug__))
+__frint32z(double __a) {
+ return __builtin_arm_frint32z(__a);
+}
+
+static __inline__ float __attribute__((__always_inline__, __nodebug__))
+__frint64zf(float __a) {
+ return __builtin_arm_frint64zf(__a);
+}
+
+static __inline__ double __attribute__((__always_inline__, __nodebug__))
+__frint64z(double __a) {
+ return __builtin_arm_frint64z(__a);
+}
+
+static __inline__ float __attribute__((__always_inline__, __nodebug__))
+__frint32xf(float __a) {
+ return __builtin_arm_frint32xf(__a);
+}
+
+static __inline__ double __attribute__((__always_inline__, __nodebug__))
+__frint32x(double __a) {
+ return __builtin_arm_frint32x(__a);
+}
+
+static __inline__ float __attribute__((__always_inline__, __nodebug__))
+__frint64xf(float __a) {
+ return __builtin_arm_frint64xf(__a);
+}
+
+static __inline__ double __attribute__((__always_inline__, __nodebug__))
+__frint64x(double __a) {
+ return __builtin_arm_frint64x(__a);
+}
+#endif
+
/* Armv8.7-A load/store 64-byte intrinsics */
#if __ARM_64BIT_STATE && defined(__ARM_FEATURE_LS64)
typedef struct {
@@ -709,6 +752,18 @@
#endif /* __ARM_FEATURE_TME */
+/* Armv8.5-A Random number generation intrinsics */
+#if __ARM_64BIT_STATE && defined(__ARM_FEATURE_RNG)
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+__rndr(uint64_t *__p) {
+ return __builtin_arm_rndr(__p);
+}
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+__rndrrs(uint64_t *__p) {
+ return __builtin_arm_rndrrs(__p);
+}
+#endif
+
#if defined(__cplusplus)
}
#endif
diff --git a/src/llvm-project/clang/lib/Headers/avx512fintrin.h b/src/llvm-project/clang/lib/Headers/avx512fintrin.h
index f226382..010bcad 100644
--- a/src/llvm-project/clang/lib/Headers/avx512fintrin.h
+++ b/src/llvm-project/clang/lib/Headers/avx512fintrin.h
@@ -9300,8 +9300,11 @@
* computations. In vector-reduction arithmetic, the evaluation order is
* independent of the order of the input elements of V.
- * For floating point types, we always assume the elements are reassociable even
- * if -fast-math is off.
+ * For floating-point intrinsics:
+ * 1. When using fadd/fmul intrinsics, the order of operations within the
+ * vector is unspecified (associative math).
+ * 2. When using fmin/fmax intrinsics, NaN or -0.0 elements within the vector
+ * produce unspecified results.
* Used bisection method. At each step, we partition the vector with previous
* step in half, and the operation is performed on its two halves.
@@ -9524,75 +9527,49 @@
return __builtin_ia32_reduce_umin_d512((__v16si)__V);
}
-#define _mm512_mask_reduce_operator(op) \
- __m256d __t1 = _mm512_extractf64x4_pd(__V, 0); \
- __m256d __t2 = _mm512_extractf64x4_pd(__V, 1); \
- __m256d __t3 = _mm256_##op(__t1, __t2); \
- __m128d __t4 = _mm256_extractf128_pd(__t3, 0); \
- __m128d __t5 = _mm256_extractf128_pd(__t3, 1); \
- __m128d __t6 = _mm_##op(__t4, __t5); \
- __m128d __t7 = __builtin_shufflevector(__t6, __t6, 1, 0); \
- __m128d __t8 = _mm_##op(__t6, __t7); \
- return __t8[0]
-
static __inline__ double __DEFAULT_FN_ATTRS512
_mm512_reduce_max_pd(__m512d __V) {
- _mm512_mask_reduce_operator(max_pd);
+ return __builtin_ia32_reduce_fmax_pd512(__V);
}
static __inline__ double __DEFAULT_FN_ATTRS512
_mm512_reduce_min_pd(__m512d __V) {
- _mm512_mask_reduce_operator(min_pd);
+ return __builtin_ia32_reduce_fmin_pd512(__V);
}
static __inline__ double __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __V) {
__V = _mm512_mask_mov_pd(_mm512_set1_pd(-__builtin_inf()), __M, __V);
- _mm512_mask_reduce_operator(max_pd);
+ return __builtin_ia32_reduce_fmax_pd512(__V);
}
static __inline__ double __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __V) {
__V = _mm512_mask_mov_pd(_mm512_set1_pd(__builtin_inf()), __M, __V);
- _mm512_mask_reduce_operator(min_pd);
+ return __builtin_ia32_reduce_fmin_pd512(__V);
}
-#undef _mm512_mask_reduce_operator
-
-#define _mm512_mask_reduce_operator(op) \
- __m256 __t1 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 0); \
- __m256 __t2 = (__m256)_mm512_extractf64x4_pd((__m512d)__V, 1); \
- __m256 __t3 = _mm256_##op(__t1, __t2); \
- __m128 __t4 = _mm256_extractf128_ps(__t3, 0); \
- __m128 __t5 = _mm256_extractf128_ps(__t3, 1); \
- __m128 __t6 = _mm_##op(__t4, __t5); \
- __m128 __t7 = __builtin_shufflevector(__t6, __t6, 2, 3, 0, 1); \
- __m128 __t8 = _mm_##op(__t6, __t7); \
- __m128 __t9 = __builtin_shufflevector(__t8, __t8, 1, 0, 3, 2); \
- __m128 __t10 = _mm_##op(__t8, __t9); \
- return __t10[0]
static __inline__ float __DEFAULT_FN_ATTRS512
_mm512_reduce_max_ps(__m512 __V) {
- _mm512_mask_reduce_operator(max_ps);
+ return __builtin_ia32_reduce_fmax_ps512(__V);
}
static __inline__ float __DEFAULT_FN_ATTRS512
_mm512_reduce_min_ps(__m512 __V) {
- _mm512_mask_reduce_operator(min_ps);
+ return __builtin_ia32_reduce_fmin_ps512(__V);
}
static __inline__ float __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __V) {
__V = _mm512_mask_mov_ps(_mm512_set1_ps(-__builtin_inff()), __M, __V);
- _mm512_mask_reduce_operator(max_ps);
+ return __builtin_ia32_reduce_fmax_ps512(__V);
}
static __inline__ float __DEFAULT_FN_ATTRS512
_mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __V) {
__V = _mm512_mask_mov_ps(_mm512_set1_ps(__builtin_inff()), __M, __V);
- _mm512_mask_reduce_operator(min_ps);
+ return __builtin_ia32_reduce_fmin_ps512(__V);
}
-#undef _mm512_mask_reduce_operator
/// Moves the least significant 32 bits of a vector of [16 x i32] to a
/// 32-bit signed integer value.
@@ -9611,6 +9588,169 @@
return __b[0];
}
+/// Loads 8 double-precision (64-bit) floating-point elements stored at memory
+/// locations starting at location \a base_addr at packed 32-bit integer indices
+/// stored in the lower half of \a vindex scaled by \a scale them in dst.
+///
+/// This intrinsic corresponds to the <c> VGATHERDPD </c> instructions.
+///
+/// \operation
+/// FOR j := 0 to 7
+/// i := j*64
+/// m := j*32
+/// addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
+/// dst[i+63:i] := MEM[addr+63:addr]
+/// ENDFOR
+/// dst[MAX:512] := 0
+/// \endoperation
+#define _mm512_i32logather_pd(vindex, base_addr, scale) \
+ _mm512_i32gather_pd(_mm512_castsi512_si256(vindex), (base_addr), (scale))
+
+/// Loads 8 double-precision (64-bit) floating-point elements from memory
+/// starting at location \a base_addr at packed 32-bit integer indices stored in
+/// the lower half of \a vindex scaled by \a scale into dst using writemask
+/// \a mask (elements are copied from \a src when the corresponding mask bit is
+/// not set).
+///
+/// This intrinsic corresponds to the <c> VGATHERDPD </c> instructions.
+///
+/// \operation
+/// FOR j := 0 to 7
+/// i := j*64
+/// m := j*32
+/// IF mask[j]
+/// addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
+/// dst[i+63:i] := MEM[addr+63:addr]
+/// ELSE
+/// dst[i+63:i] := src[i+63:i]
+/// FI
+/// ENDFOR
+/// dst[MAX:512] := 0
+/// \endoperation
+#define _mm512_mask_i32logather_pd(src, mask, vindex, base_addr, scale) \
+ _mm512_mask_i32gather_pd((src), (mask), _mm512_castsi512_si256(vindex), \
+ (base_addr), (scale))
+
+/// Loads 8 64-bit integer elements from memory starting at location \a base_addr
+/// at packed 32-bit integer indices stored in the lower half of \a vindex
+/// scaled by \a scale and stores them in dst.
+///
+/// This intrinsic corresponds to the <c> VPGATHERDQ </c> instructions.
+///
+/// \operation
+/// FOR j := 0 to 7
+/// i := j*64
+/// m := j*32
+/// addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
+/// dst[i+63:i] := MEM[addr+63:addr]
+/// ENDFOR
+/// dst[MAX:512] := 0
+/// \endoperation
+#define _mm512_i32logather_epi64(vindex, base_addr, scale) \
+ _mm512_i32gather_epi64(_mm512_castsi512_si256(vindex), (base_addr), (scale))
+
+/// Loads 8 64-bit integer elements from memory starting at location \a base_addr
+/// at packed 32-bit integer indices stored in the lower half of \a vindex
+/// scaled by \a scale and stores them in dst using writemask \a mask (elements
+/// are copied from \a src when the corresponding mask bit is not set).
+///
+/// This intrinsic corresponds to the <c> VPGATHERDQ </c> instructions.
+///
+/// \operation
+/// FOR j := 0 to 7
+/// i := j*64
+/// m := j*32
+/// IF mask[j]
+/// addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
+/// dst[i+63:i] := MEM[addr+63:addr]
+/// ELSE
+/// dst[i+63:i] := src[i+63:i]
+/// FI
+/// ENDFOR
+/// dst[MAX:512] := 0
+/// \endoperation
+#define _mm512_mask_i32logather_epi64(src, mask, vindex, base_addr, scale) \
+ _mm512_mask_i32gather_epi64((src), (mask), _mm512_castsi512_si256(vindex), \
+ (base_addr), (scale))
+
+/// Stores 8 packed double-precision (64-bit) floating-point elements in \a v1
+/// and to memory locations starting at location \a base_addr at packed 32-bit
+/// integer indices stored in \a vindex scaled by \a scale.
+///
+/// This intrinsic corresponds to the <c> VSCATTERDPD </c> instructions.
+///
+/// \operation
+/// FOR j := 0 to 7
+/// i := j*64
+/// m := j*32
+/// addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
+/// MEM[addr+63:addr] := v1[i+63:i]
+/// ENDFOR
+/// \endoperation
+#define _mm512_i32loscatter_pd(base_addr, vindex, v1, scale) \
+ _mm512_i32scatter_pd((base_addr), _mm512_castsi512_si256(vindex), (v1), (scale))
+
+/// Stores 8 packed double-precision (64-bit) floating-point elements in \a v1
+/// to memory locations starting at location \a base_addr at packed 32-bit
+/// integer indices stored in \a vindex scaled by \a scale. Only those elements
+/// whose corresponding mask bit is set in writemask \a mask are written to
+/// memory.
+///
+/// This intrinsic corresponds to the <c> VSCATTERDPD </c> instructions.
+///
+/// \operation
+/// FOR j := 0 to 7
+/// i := j*64
+/// m := j*32
+/// IF mask[j]
+/// addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
+/// MEM[addr+63:addr] := a[i+63:i]
+/// FI
+/// ENDFOR
+/// \endoperation
+#define _mm512_mask_i32loscatter_pd(base_addr, mask, vindex, v1, scale) \
+ _mm512_mask_i32scatter_pd((base_addr), (mask), \
+ _mm512_castsi512_si256(vindex), (v1), (scale))
+
+/// Stores 8 packed 64-bit integer elements located in \a v1 and stores them in
+/// memory locations starting at location \a base_addr at packed 32-bit integer
+/// indices stored in \a vindex scaled by \a scale.
+///
+/// This intrinsic corresponds to the <c> VPSCATTERDQ </c> instructions.
+///
+/// \operation
+/// FOR j := 0 to 7
+/// i := j*64
+/// m := j*32
+/// addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
+/// MEM[addr+63:addr] := a[i+63:i]
+/// ENDFOR
+/// \endoperation
+#define _mm512_i32loscatter_epi64(base_addr, vindex, v1, scale) \
+ _mm512_i32scatter_epi64((base_addr), \
+ _mm512_castsi512_si256(vindex), (v1), (scale))
+
+/// Stores 8 packed 64-bit integer elements located in a and stores them in
+/// memory locations starting at location \a base_addr at packed 32-bit integer
+/// indices stored in \a vindex scaled by scale using writemask \a mask (elements
+/// whose corresponding mask bit is not set are not written to memory).
+///
+/// This intrinsic corresponds to the <c> VPSCATTERDQ </c> instructions.
+///
+/// \operation
+/// FOR j := 0 to 7
+/// i := j*64
+/// m := j*32
+/// IF mask[j]
+/// addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8
+/// MEM[addr+63:addr] := a[i+63:i]
+/// FI
+/// ENDFOR
+/// \endoperation
+#define _mm512_mask_i32loscatter_epi64(base_addr, mask, vindex, v1, scale) \
+ _mm512_mask_i32scatter_epi64((base_addr), (mask), \
+ _mm512_castsi512_si256(vindex), (v1), (scale))
+
#undef __DEFAULT_FN_ATTRS512
#undef __DEFAULT_FN_ATTRS128
#undef __DEFAULT_FN_ATTRS
diff --git a/src/llvm-project/clang/lib/Headers/builtins.h b/src/llvm-project/clang/lib/Headers/builtins.h
new file mode 100644
index 0000000..6509586
--- /dev/null
+++ b/src/llvm-project/clang/lib/Headers/builtins.h
@@ -0,0 +1,16 @@
+/*===---- builtins.h - Standard header for extra builtins -----------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+/// Some legacy compilers have builtin definitions in a file named builtins.h.
+/// This header file has been added to allow compatibility with code that was
+/// written for those compilers. Code may have an include line for this file
+/// and to avoid an error an empty file with this name is provided.
+#ifndef __BUILTINS_H
+#define __BUILTINS_H
+
+#endif /* __BUILTINS_H */
diff --git a/src/llvm-project/clang/lib/Headers/cuda_wrappers/complex b/src/llvm-project/clang/lib/Headers/cuda_wrappers/complex
index 11d40a8..e6805b6 100644
--- a/src/llvm-project/clang/lib/Headers/cuda_wrappers/complex
+++ b/src/llvm-project/clang/lib/Headers/cuda_wrappers/complex
@@ -72,8 +72,16 @@
#define _GLIBCXX_USE_C99_COMPLEX 0
#define _GLIBCXX_USE_C99_COMPLEX_TR1 0
+// Work around a compatibility issue with libstdc++ 11.1.0
+// https://bugs.llvm.org/show_bug.cgi?id=50383
+#pragma push_macro("__failed_assertion")
+#if _GLIBCXX_RELEASE == 11
+#define __failed_assertion __cuda_failed_assertion
+#endif
+
#include_next <complex>
+#pragma pop_macro("__failed_assertion")
#pragma pop_macro("_GLIBCXX_USE_C99_COMPLEX_TR1")
#pragma pop_macro("_GLIBCXX_USE_C99_COMPLEX")
diff --git a/src/llvm-project/clang/lib/Headers/hexagon_circ_brev_intrinsics.h b/src/llvm-project/clang/lib/Headers/hexagon_circ_brev_intrinsics.h
new file mode 100644
index 0000000..c53786d
--- /dev/null
+++ b/src/llvm-project/clang/lib/Headers/hexagon_circ_brev_intrinsics.h
@@ -0,0 +1,298 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache 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 _HEXAGON_CIRC_BREV_INTRINSICS_H_
+#define _HEXAGON_CIRC_BREV_INTRINSICS_H_ 1
+
+#include <hexagon_protos.h>
+#include <stdint.h>
+
+/* Circular Load */
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_load_update_D(Word64 dst, Word64 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_load_update_D(dest,ptr,incr,bufsize,K) \
+ { ptr = (int64_t *) HEXAGON_circ_ldd (ptr, &(dest), ((((K)+1)<<24)|((bufsize)<<3)), ((incr)*8)); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_load_update_W(Word32 dst, Word32 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_load_update_W(dest,ptr,incr,bufsize,K) \
+ { ptr = (int *) HEXAGON_circ_ldw (ptr, &(dest), (((K)<<24)|((bufsize)<<2)), ((incr)*4)); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_load_update_H(Word16 dst, Word16 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_load_update_H(dest,ptr,incr,bufsize,K) \
+ { ptr = (int16_t *) HEXAGON_circ_ldh (ptr, &(dest), ((((K)-1)<<24)|((bufsize)<<1)), ((incr)*2)); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_load_update_UH( UWord16 dst, UWord16 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_load_update_UH(dest,ptr,incr,bufsize,K) \
+ { ptr = (uint16_t *) HEXAGON_circ_lduh (ptr, &(dest), ((((K)-1)<<24)|((bufsize)<<1)), ((incr)*2)); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_load_update_B(Word8 dst, Word8 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_load_update_B(dest,ptr,incr,bufsize,K) \
+ { ptr = (int8_t *) HEXAGON_circ_ldb (ptr, &(dest), ((((K)-2)<<24)|(bufsize)), incr); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_load_update_UB(UWord8 dst, UWord8 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_load_update_UB(dest,ptr,incr,bufsize,K) \
+ { ptr = (uint8_t *) HEXAGON_circ_ldub (ptr, &(dest), ((((K)-2)<<24)|(bufsize)), incr); }
+
+/* Circular Store */
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_store_update_D(Word64 *src, Word64 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_store_update_D(src,ptr,incr,bufsize,K) \
+ { ptr = (int64_t *) HEXAGON_circ_std (ptr, src, ((((K)+1)<<24)|((bufsize)<<3)), ((incr)*8)); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_store_update_W(Word32 *src, Word32 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_store_update_W(src,ptr,incr,bufsize,K) \
+ { ptr = (int *) HEXAGON_circ_stw (ptr, src, (((K)<<24)|((bufsize)<<2)), ((incr)*4)); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_store_update_HL(Word16 *src, Word16 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_store_update_HL(src,ptr,incr,bufsize,K) \
+ { ptr = (int16_t *) HEXAGON_circ_sth (ptr, src, ((((K)-1)<<24)|((bufsize)<<1)), ((incr)*2)); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_store_update_HH(Word16 *src, Word16 *ptr, UWord32 incr, UWord32 bufsize, UWord32 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_store_update_HH(src,ptr,incr,bufsize,K) \
+ { ptr = (int16_t *) HEXAGON_circ_sthhi (ptr, src, ((((K)-1)<<24)|((bufsize)<<1)), ((incr)*2)); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_circ_store_update_B(Word8 *src, Word8 *ptr, UWord32 I4, UWord32 bufsize, UWord64 K)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_circ_store_update_B(src,ptr,incr,bufsize,K) \
+ { ptr = (int8_t *) HEXAGON_circ_stb (ptr, src, ((((K)-2)<<24)|(bufsize)), incr); }
+
+
+/* Bit Reverse Load */
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_load_update_D(Word64 dst, Word64 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_load_update_D(dest,ptr,log2bufsize) \
+ { ptr = (int64_t *) HEXAGON_brev_ldd (ptr, &(dest), (1<<(16-((log2bufsize) + 3)))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_load_update_W(Word32 dst, Word32 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_load_update_W(dest,ptr,log2bufsize) \
+ { ptr = (int *) HEXAGON_brev_ldw (ptr, &(dest), (1<<(16-((log2bufsize) + 2)))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_load_update_H(Word16 dst, Word16 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_load_update_H(dest,ptr,log2bufsize) \
+ { ptr = (int16_t *) HEXAGON_brev_ldh (ptr, &(dest), (1<<(16-((log2bufsize) + 1)))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_load_update_UH(UWord16 dst, UWord16 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_load_update_UH(dest,ptr,log2bufsize) \
+ { ptr = (uint16_t *) HEXAGON_brev_lduh (ptr, &(dest), (1<<(16-((log2bufsize) + 1)))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_load_update_B(Word8 dst, Word8 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_load_update_B(dest,ptr,log2bufsize) \
+ { ptr = (int8_t *) HEXAGON_brev_ldb (ptr, &(dest), (1<<(16-((log2bufsize))))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_load_update_UB(UWord8 dst, UWord8 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_load_update_UB(dest,ptr,log2bufsize) \
+ { ptr = (uint8_t *) HEXAGON_brev_ldub (ptr, &(dest), (1<<(16-((log2bufsize))))); }
+
+/* Bit Reverse Store */
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_store_update_D(Word64 *src, Word64 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_store_update_D(src,ptr,log2bufsize) \
+ { ptr = (int64_t *) HEXAGON_brev_std (ptr, src, (1<<(16-((log2bufsize) + 3)))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_store_update_W(Word32 *src, Word32 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_store_update_W(src,ptr,log2bufsize) \
+ { ptr = (int *) HEXAGON_brev_stw (ptr, src, (1<<(16-((log2bufsize) + 2)))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_store_update_HL(Word16 *src, Word16 *ptr, Word32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_store_update_HL(src,ptr,log2bufsize) \
+ { ptr = (int16_t *) HEXAGON_brev_sth (ptr, src, (1<<(16-((log2bufsize) + 1)))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_store_update_HH(Word16 *src, Word16 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_store_update_HH(src,ptr,log2bufsize) \
+ { ptr = (int16_t *) HEXAGON_brev_sthhi (ptr, src, (1<<(16-((log2bufsize) + 1)))); }
+
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: void Q6_bitrev_store_update_B(Word8 *src, Word8 *ptr, UWord32 Iu4)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#define Q6_bitrev_store_update_B(src,ptr,log2bufsize) \
+ { ptr = (int8_t *) HEXAGON_brev_stb (ptr, src, (1<<(16-((log2bufsize))))); }
+
+
+#define HEXAGON_circ_ldd __builtin_circ_ldd
+#define HEXAGON_circ_ldw __builtin_circ_ldw
+#define HEXAGON_circ_ldh __builtin_circ_ldh
+#define HEXAGON_circ_lduh __builtin_circ_lduh
+#define HEXAGON_circ_ldb __builtin_circ_ldb
+#define HEXAGON_circ_ldub __builtin_circ_ldub
+
+
+#define HEXAGON_circ_std __builtin_circ_std
+#define HEXAGON_circ_stw __builtin_circ_stw
+#define HEXAGON_circ_sth __builtin_circ_sth
+#define HEXAGON_circ_sthhi __builtin_circ_sthhi
+#define HEXAGON_circ_stb __builtin_circ_stb
+
+
+#define HEXAGON_brev_ldd __builtin_brev_ldd
+#define HEXAGON_brev_ldw __builtin_brev_ldw
+#define HEXAGON_brev_ldh __builtin_brev_ldh
+#define HEXAGON_brev_lduh __builtin_brev_lduh
+#define HEXAGON_brev_ldb __builtin_brev_ldb
+#define HEXAGON_brev_ldub __builtin_brev_ldub
+
+#define HEXAGON_brev_std __builtin_brev_std
+#define HEXAGON_brev_stw __builtin_brev_stw
+#define HEXAGON_brev_sth __builtin_brev_sth
+#define HEXAGON_brev_sthhi __builtin_brev_sthhi
+#define HEXAGON_brev_stb __builtin_brev_stb
+
+#ifdef __HVX__
+/* ==========================================================================
+ Assembly Syntax: if (Qt) vmem(Rt+#0) = Vs
+ C Intrinsic Prototype: void Q6_vmaskedstoreq_QAV(HVX_VectorPred Qt, HVX_VectorAddress A, HVX_Vector Vs)
+ Instruction Type: COPROC_VMEM
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vmaskedstoreq_QAV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaskedstoreq)
+
+/* ==========================================================================
+ Assembly Syntax: if (!Qt) vmem(Rt+#0) = Vs
+ C Intrinsic Prototype: void Q6_vmaskedstorenq_QAV(HVX_VectorPred Qt, HVX_VectorAddress A, HVX_Vector Vs)
+ Instruction Type: COPROC_VMEM
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vmaskedstorenq_QAV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaskedstorenq)
+
+/* ==========================================================================
+ Assembly Syntax: if (Qt) vmem(Rt+#0):nt = Vs
+ C Intrinsic Prototype: void Q6_vmaskedstorentq_QAV(HVX_VectorPred Qt, HVX_VectorAddress A, HVX_Vector Vs)
+ Instruction Type: COPROC_VMEM
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vmaskedstorentq_QAV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaskedstorentq)
+
+/* ==========================================================================
+ Assembly Syntax: if (!Qt) vmem(Rt+#0):nt = Vs
+ C Intrinsic Prototype: void Q6_vmaskedstorentnq_QAV(HVX_VectorPred Qt, HVX_VectorAddress A, HVX_Vector Vs)
+ Instruction Type: COPROC_VMEM
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vmaskedstorentnq_QAV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaskedstorentnq)
+
+#endif
+
+
+#endif /* #ifndef _HEXAGON_CIRC_BREV_INTRINSICS_H_ */
+
+#ifdef __NOT_DEFINED__
+/*** comment block template ***/
+/* ==========================================================================
+ Assembly Syntax: Return=instruction()
+ C Intrinsic Prototype: ReturnType Intrinsic(ParamType Rs, ParamType Rt)
+ Instruction Type: InstructionType
+ Execution Slots: SLOT0123
+ ========================================================================== */
+#endif /*** __NOT_DEFINED__ ***/
diff --git a/src/llvm-project/clang/lib/Headers/hexagon_protos.h b/src/llvm-project/clang/lib/Headers/hexagon_protos.h
new file mode 100644
index 0000000..cdffd93
--- /dev/null
+++ b/src/llvm-project/clang/lib/Headers/hexagon_protos.h
@@ -0,0 +1,8450 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Automatically generated file, do not edit!
+//===----------------------------------------------------------------------===//
+
+
+
+#ifndef __HEXAGON_PROTOS_H_
+#define __HEXAGON_PROTOS_H_ 1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=abs(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_abs_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_abs_R __builtin_HEXAGON_A2_abs
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=abs(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_abs_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_abs_P __builtin_HEXAGON_A2_absp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=abs(Rs32):sat
+ C Intrinsic Prototype: Word32 Q6_R_abs_R_sat(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_abs_R_sat __builtin_HEXAGON_A2_abssat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_add_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_add_RR __builtin_HEXAGON_A2_add
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.h,Rs32.h):<<16
+ C Intrinsic Prototype: Word32 Q6_R_add_RhRh_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RhRh_s16 __builtin_HEXAGON_A2_addh_h16_hh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.h,Rs32.l):<<16
+ C Intrinsic Prototype: Word32 Q6_R_add_RhRl_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RhRl_s16 __builtin_HEXAGON_A2_addh_h16_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.l,Rs32.h):<<16
+ C Intrinsic Prototype: Word32 Q6_R_add_RlRh_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RlRh_s16 __builtin_HEXAGON_A2_addh_h16_lh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.l,Rs32.l):<<16
+ C Intrinsic Prototype: Word32 Q6_R_add_RlRl_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RlRl_s16 __builtin_HEXAGON_A2_addh_h16_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.h,Rs32.h):sat:<<16
+ C Intrinsic Prototype: Word32 Q6_R_add_RhRh_sat_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RhRh_sat_s16 __builtin_HEXAGON_A2_addh_h16_sat_hh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.h,Rs32.l):sat:<<16
+ C Intrinsic Prototype: Word32 Q6_R_add_RhRl_sat_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RhRl_sat_s16 __builtin_HEXAGON_A2_addh_h16_sat_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.l,Rs32.h):sat:<<16
+ C Intrinsic Prototype: Word32 Q6_R_add_RlRh_sat_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RlRh_sat_s16 __builtin_HEXAGON_A2_addh_h16_sat_lh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.l,Rs32.l):sat:<<16
+ C Intrinsic Prototype: Word32 Q6_R_add_RlRl_sat_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RlRl_sat_s16 __builtin_HEXAGON_A2_addh_h16_sat_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.l,Rs32.h)
+ C Intrinsic Prototype: Word32 Q6_R_add_RlRh(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RlRh __builtin_HEXAGON_A2_addh_l16_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.l,Rs32.l)
+ C Intrinsic Prototype: Word32 Q6_R_add_RlRl(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RlRl __builtin_HEXAGON_A2_addh_l16_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.l,Rs32.h):sat
+ C Intrinsic Prototype: Word32 Q6_R_add_RlRh_sat(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RlRh_sat __builtin_HEXAGON_A2_addh_l16_sat_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rt32.l,Rs32.l):sat
+ C Intrinsic Prototype: Word32 Q6_R_add_RlRl_sat(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_RlRl_sat __builtin_HEXAGON_A2_addh_l16_sat_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rs32,#s16)
+ C Intrinsic Prototype: Word32 Q6_R_add_RI(Word32 Rs, Word32 Is16)
+ Instruction Type: ALU32_ADDI
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_add_RI __builtin_HEXAGON_A2_addi
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=add(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_add_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_add_PP __builtin_HEXAGON_A2_addp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=add(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_add_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_add_PP_sat __builtin_HEXAGON_A2_addpsat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word32 Q6_R_add_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_add_RR_sat __builtin_HEXAGON_A2_addsat
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=add(Rs32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_add_RP(Word32 Rs, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_add_RP __builtin_HEXAGON_A2_addsp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=and(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_and_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_and_RR __builtin_HEXAGON_A2_and
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=and(Rs32,#s10)
+ C Intrinsic Prototype: Word32 Q6_R_and_RI(Word32 Rs, Word32 Is10)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_and_RI __builtin_HEXAGON_A2_andir
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=and(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_and_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_and_PP __builtin_HEXAGON_A2_andp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=aslh(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_aslh_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_aslh_R __builtin_HEXAGON_A2_aslh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asrh(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_asrh_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_asrh_R __builtin_HEXAGON_A2_asrh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=combine(Rt32.h,Rs32.h)
+ C Intrinsic Prototype: Word32 Q6_R_combine_RhRh(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_combine_RhRh __builtin_HEXAGON_A2_combine_hh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=combine(Rt32.h,Rs32.l)
+ C Intrinsic Prototype: Word32 Q6_R_combine_RhRl(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_combine_RhRl __builtin_HEXAGON_A2_combine_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=combine(Rt32.l,Rs32.h)
+ C Intrinsic Prototype: Word32 Q6_R_combine_RlRh(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_combine_RlRh __builtin_HEXAGON_A2_combine_lh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=combine(Rt32.l,Rs32.l)
+ C Intrinsic Prototype: Word32 Q6_R_combine_RlRl(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_combine_RlRl __builtin_HEXAGON_A2_combine_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=combine(#s8,#S8)
+ C Intrinsic Prototype: Word64 Q6_P_combine_II(Word32 Is8, Word32 IS8)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_combine_II __builtin_HEXAGON_A2_combineii
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=combine(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_combine_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_combine_RR __builtin_HEXAGON_A2_combinew
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=max(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_max_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_max_RR __builtin_HEXAGON_A2_max
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=max(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_max_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_max_PP __builtin_HEXAGON_A2_maxp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=maxu(Rs32,Rt32)
+ C Intrinsic Prototype: UWord32 Q6_R_maxu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_maxu_RR __builtin_HEXAGON_A2_maxu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=maxu(Rss32,Rtt32)
+ C Intrinsic Prototype: UWord64 Q6_P_maxu_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_maxu_PP __builtin_HEXAGON_A2_maxup
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=min(Rt32,Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_min_RR(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_min_RR __builtin_HEXAGON_A2_min
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=min(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_min_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_min_PP __builtin_HEXAGON_A2_minp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=minu(Rt32,Rs32)
+ C Intrinsic Prototype: UWord32 Q6_R_minu_RR(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_minu_RR __builtin_HEXAGON_A2_minu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=minu(Rtt32,Rss32)
+ C Intrinsic Prototype: UWord64 Q6_P_minu_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_minu_PP __builtin_HEXAGON_A2_minup
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=neg(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_neg_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_neg_R __builtin_HEXAGON_A2_neg
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=neg(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_neg_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_neg_P __builtin_HEXAGON_A2_negp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=neg(Rs32):sat
+ C Intrinsic Prototype: Word32 Q6_R_neg_R_sat(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_neg_R_sat __builtin_HEXAGON_A2_negsat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=not(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_not_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_not_R __builtin_HEXAGON_A2_not
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=not(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_not_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_not_P __builtin_HEXAGON_A2_notp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=or(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_or_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_or_RR __builtin_HEXAGON_A2_or
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=or(Rs32,#s10)
+ C Intrinsic Prototype: Word32 Q6_R_or_RI(Word32 Rs, Word32 Is10)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_or_RI __builtin_HEXAGON_A2_orir
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=or(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_or_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_or_PP __builtin_HEXAGON_A2_orp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=round(Rss32):sat
+ C Intrinsic Prototype: Word32 Q6_R_round_P_sat(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_round_P_sat __builtin_HEXAGON_A2_roundsat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sat(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_sat_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sat_P __builtin_HEXAGON_A2_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=satb(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_satb_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_satb_R __builtin_HEXAGON_A2_satb
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sath(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_sath_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sath_R __builtin_HEXAGON_A2_sath
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=satub(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_satub_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_satub_R __builtin_HEXAGON_A2_satub
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=satuh(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_satuh_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_satuh_R __builtin_HEXAGON_A2_satuh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32,Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_sub_RR(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_sub_RR __builtin_HEXAGON_A2_sub
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.h,Rs32.h):<<16
+ C Intrinsic Prototype: Word32 Q6_R_sub_RhRh_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RhRh_s16 __builtin_HEXAGON_A2_subh_h16_hh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.h,Rs32.l):<<16
+ C Intrinsic Prototype: Word32 Q6_R_sub_RhRl_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RhRl_s16 __builtin_HEXAGON_A2_subh_h16_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.l,Rs32.h):<<16
+ C Intrinsic Prototype: Word32 Q6_R_sub_RlRh_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RlRh_s16 __builtin_HEXAGON_A2_subh_h16_lh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.l,Rs32.l):<<16
+ C Intrinsic Prototype: Word32 Q6_R_sub_RlRl_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RlRl_s16 __builtin_HEXAGON_A2_subh_h16_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.h,Rs32.h):sat:<<16
+ C Intrinsic Prototype: Word32 Q6_R_sub_RhRh_sat_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RhRh_sat_s16 __builtin_HEXAGON_A2_subh_h16_sat_hh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.h,Rs32.l):sat:<<16
+ C Intrinsic Prototype: Word32 Q6_R_sub_RhRl_sat_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RhRl_sat_s16 __builtin_HEXAGON_A2_subh_h16_sat_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.l,Rs32.h):sat:<<16
+ C Intrinsic Prototype: Word32 Q6_R_sub_RlRh_sat_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RlRh_sat_s16 __builtin_HEXAGON_A2_subh_h16_sat_lh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.l,Rs32.l):sat:<<16
+ C Intrinsic Prototype: Word32 Q6_R_sub_RlRl_sat_s16(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RlRl_sat_s16 __builtin_HEXAGON_A2_subh_h16_sat_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.l,Rs32.h)
+ C Intrinsic Prototype: Word32 Q6_R_sub_RlRh(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RlRh __builtin_HEXAGON_A2_subh_l16_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.l,Rs32.l)
+ C Intrinsic Prototype: Word32 Q6_R_sub_RlRl(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RlRl __builtin_HEXAGON_A2_subh_l16_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.l,Rs32.h):sat
+ C Intrinsic Prototype: Word32 Q6_R_sub_RlRh_sat(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RlRh_sat __builtin_HEXAGON_A2_subh_l16_sat_hl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32.l,Rs32.l):sat
+ C Intrinsic Prototype: Word32 Q6_R_sub_RlRl_sat(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_RlRl_sat __builtin_HEXAGON_A2_subh_l16_sat_ll
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=sub(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_sub_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_sub_PP __builtin_HEXAGON_A2_subp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(#s10,Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_sub_IR(Word32 Is10, Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_sub_IR __builtin_HEXAGON_A2_subri
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sub(Rt32,Rs32):sat
+ C Intrinsic Prototype: Word32 Q6_R_sub_RR_sat(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_sub_RR_sat __builtin_HEXAGON_A2_subsat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vaddh(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_vaddh_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vaddh_RR __builtin_HEXAGON_A2_svaddh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vaddh(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word32 Q6_R_vaddh_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vaddh_RR_sat __builtin_HEXAGON_A2_svaddhs
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vadduh(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word32 Q6_R_vadduh_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vadduh_RR_sat __builtin_HEXAGON_A2_svadduhs
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vavgh(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_vavgh_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vavgh_RR __builtin_HEXAGON_A2_svavgh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vavgh(Rs32,Rt32):rnd
+ C Intrinsic Prototype: Word32 Q6_R_vavgh_RR_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vavgh_RR_rnd __builtin_HEXAGON_A2_svavghs
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vnavgh(Rt32,Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_vnavgh_RR(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vnavgh_RR __builtin_HEXAGON_A2_svnavgh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsubh(Rt32,Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_vsubh_RR(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vsubh_RR __builtin_HEXAGON_A2_svsubh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsubh(Rt32,Rs32):sat
+ C Intrinsic Prototype: Word32 Q6_R_vsubh_RR_sat(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vsubh_RR_sat __builtin_HEXAGON_A2_svsubhs
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsubuh(Rt32,Rs32):sat
+ C Intrinsic Prototype: Word32 Q6_R_vsubuh_RR_sat(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vsubuh_RR_sat __builtin_HEXAGON_A2_svsubuhs
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=swiz(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_swiz_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_swiz_R __builtin_HEXAGON_A2_swiz
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sxtb(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_sxtb_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_sxtb_R __builtin_HEXAGON_A2_sxtb
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sxth(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_sxth_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_sxth_R __builtin_HEXAGON_A2_sxth
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=sxtw(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_sxtw_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_sxtw_R __builtin_HEXAGON_A2_sxtw
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=Rs32
+ C Intrinsic Prototype: Word32 Q6_R_equals_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_equals_R __builtin_HEXAGON_A2_tfr
+
+/* ==========================================================================
+ Assembly Syntax: Rx32.h=#u16
+ C Intrinsic Prototype: Word32 Q6_Rh_equals_I(Word32 Rx, Word32 Iu16)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Rh_equals_I __builtin_HEXAGON_A2_tfrih
+
+/* ==========================================================================
+ Assembly Syntax: Rx32.l=#u16
+ C Intrinsic Prototype: Word32 Q6_Rl_equals_I(Word32 Rx, Word32 Iu16)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Rl_equals_I __builtin_HEXAGON_A2_tfril
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=Rss32
+ C Intrinsic Prototype: Word64 Q6_P_equals_P(Word64 Rss)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_equals_P __builtin_HEXAGON_A2_tfrp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=#s8
+ C Intrinsic Prototype: Word64 Q6_P_equals_I(Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_equals_I __builtin_HEXAGON_A2_tfrpi
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=#s16
+ C Intrinsic Prototype: Word32 Q6_R_equals_I(Word32 Is16)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_equals_I __builtin_HEXAGON_A2_tfrsi
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vabsh(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vabsh_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vabsh_P __builtin_HEXAGON_A2_vabsh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vabsh(Rss32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vabsh_P_sat(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vabsh_P_sat __builtin_HEXAGON_A2_vabshsat
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vabsw(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vabsw_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vabsw_P __builtin_HEXAGON_A2_vabsw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vabsw(Rss32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vabsw_P_sat(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vabsw_P_sat __builtin_HEXAGON_A2_vabswsat
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaddb(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vaddb_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: MAPPING
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_vaddb_PP __builtin_HEXAGON_A2_vaddb_map
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaddh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vaddh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaddh_PP __builtin_HEXAGON_A2_vaddh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaddh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vaddh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaddh_PP_sat __builtin_HEXAGON_A2_vaddhs
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaddub(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vaddub_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaddub_PP __builtin_HEXAGON_A2_vaddub
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaddub(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vaddub_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaddub_PP_sat __builtin_HEXAGON_A2_vaddubs
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vadduh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vadduh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vadduh_PP_sat __builtin_HEXAGON_A2_vadduhs
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaddw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vaddw_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaddw_PP __builtin_HEXAGON_A2_vaddw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaddw(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vaddw_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaddw_PP_sat __builtin_HEXAGON_A2_vaddws
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavgh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vavgh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavgh_PP __builtin_HEXAGON_A2_vavgh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavgh(Rss32,Rtt32):crnd
+ C Intrinsic Prototype: Word64 Q6_P_vavgh_PP_crnd(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavgh_PP_crnd __builtin_HEXAGON_A2_vavghcr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavgh(Rss32,Rtt32):rnd
+ C Intrinsic Prototype: Word64 Q6_P_vavgh_PP_rnd(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavgh_PP_rnd __builtin_HEXAGON_A2_vavghr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavgub(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vavgub_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavgub_PP __builtin_HEXAGON_A2_vavgub
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavgub(Rss32,Rtt32):rnd
+ C Intrinsic Prototype: Word64 Q6_P_vavgub_PP_rnd(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavgub_PP_rnd __builtin_HEXAGON_A2_vavgubr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavguh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vavguh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavguh_PP __builtin_HEXAGON_A2_vavguh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavguh(Rss32,Rtt32):rnd
+ C Intrinsic Prototype: Word64 Q6_P_vavguh_PP_rnd(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavguh_PP_rnd __builtin_HEXAGON_A2_vavguhr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavguw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vavguw_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavguw_PP __builtin_HEXAGON_A2_vavguw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavguw(Rss32,Rtt32):rnd
+ C Intrinsic Prototype: Word64 Q6_P_vavguw_PP_rnd(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavguw_PP_rnd __builtin_HEXAGON_A2_vavguwr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavgw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vavgw_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavgw_PP __builtin_HEXAGON_A2_vavgw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavgw(Rss32,Rtt32):crnd
+ C Intrinsic Prototype: Word64 Q6_P_vavgw_PP_crnd(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavgw_PP_crnd __builtin_HEXAGON_A2_vavgwcr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vavgw(Rss32,Rtt32):rnd
+ C Intrinsic Prototype: Word64 Q6_P_vavgw_PP_rnd(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vavgw_PP_rnd __builtin_HEXAGON_A2_vavgwr
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpb.eq(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmpb_eq_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpb_eq_PP __builtin_HEXAGON_A2_vcmpbeq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpb.gtu(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmpb_gtu_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpb_gtu_PP __builtin_HEXAGON_A2_vcmpbgtu
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmph.eq(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmph_eq_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmph_eq_PP __builtin_HEXAGON_A2_vcmpheq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmph.gt(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmph_gt_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmph_gt_PP __builtin_HEXAGON_A2_vcmphgt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmph.gtu(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmph_gtu_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmph_gtu_PP __builtin_HEXAGON_A2_vcmphgtu
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpw.eq(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmpw_eq_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpw_eq_PP __builtin_HEXAGON_A2_vcmpweq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpw.gt(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmpw_gt_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpw_gt_PP __builtin_HEXAGON_A2_vcmpwgt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpw.gtu(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmpw_gtu_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpw_gtu_PP __builtin_HEXAGON_A2_vcmpwgtu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vconj(Rss32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vconj_P_sat(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vconj_P_sat __builtin_HEXAGON_A2_vconj
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmaxb(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vmaxb_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmaxb_PP __builtin_HEXAGON_A2_vmaxb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmaxh(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vmaxh_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmaxh_PP __builtin_HEXAGON_A2_vmaxh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmaxub(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vmaxub_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmaxub_PP __builtin_HEXAGON_A2_vmaxub
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmaxuh(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vmaxuh_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmaxuh_PP __builtin_HEXAGON_A2_vmaxuh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmaxuw(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vmaxuw_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmaxuw_PP __builtin_HEXAGON_A2_vmaxuw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmaxw(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vmaxw_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmaxw_PP __builtin_HEXAGON_A2_vmaxw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vminb(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vminb_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vminb_PP __builtin_HEXAGON_A2_vminb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vminh(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vminh_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vminh_PP __builtin_HEXAGON_A2_vminh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vminub(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vminub_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vminub_PP __builtin_HEXAGON_A2_vminub
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vminuh(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vminuh_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vminuh_PP __builtin_HEXAGON_A2_vminuh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vminuw(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vminuw_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vminuw_PP __builtin_HEXAGON_A2_vminuw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vminw(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vminw_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vminw_PP __builtin_HEXAGON_A2_vminw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vnavgh(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vnavgh_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vnavgh_PP __builtin_HEXAGON_A2_vnavgh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vnavgh(Rtt32,Rss32):crnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vnavgh_PP_crnd_sat(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vnavgh_PP_crnd_sat __builtin_HEXAGON_A2_vnavghcr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vnavgh(Rtt32,Rss32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vnavgh_PP_rnd_sat(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vnavgh_PP_rnd_sat __builtin_HEXAGON_A2_vnavghr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vnavgw(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vnavgw_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vnavgw_PP __builtin_HEXAGON_A2_vnavgw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vnavgw(Rtt32,Rss32):crnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vnavgw_PP_crnd_sat(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vnavgw_PP_crnd_sat __builtin_HEXAGON_A2_vnavgwcr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vnavgw(Rtt32,Rss32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vnavgw_PP_rnd_sat(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vnavgw_PP_rnd_sat __builtin_HEXAGON_A2_vnavgwr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vraddub(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vraddub_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vraddub_PP __builtin_HEXAGON_A2_vraddub
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vraddub(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vraddubacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vraddubacc_PP __builtin_HEXAGON_A2_vraddub_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrsadub(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrsadub_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrsadub_PP __builtin_HEXAGON_A2_vrsadub
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrsadub(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrsadubacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrsadubacc_PP __builtin_HEXAGON_A2_vrsadub_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsubb(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vsubb_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: MAPPING
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_vsubb_PP __builtin_HEXAGON_A2_vsubb_map
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsubh(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vsubh_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsubh_PP __builtin_HEXAGON_A2_vsubh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsubh(Rtt32,Rss32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vsubh_PP_sat(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsubh_PP_sat __builtin_HEXAGON_A2_vsubhs
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsubub(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vsubub_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsubub_PP __builtin_HEXAGON_A2_vsubub
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsubub(Rtt32,Rss32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vsubub_PP_sat(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsubub_PP_sat __builtin_HEXAGON_A2_vsububs
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsubuh(Rtt32,Rss32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vsubuh_PP_sat(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsubuh_PP_sat __builtin_HEXAGON_A2_vsubuhs
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsubw(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vsubw_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsubw_PP __builtin_HEXAGON_A2_vsubw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsubw(Rtt32,Rss32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vsubw_PP_sat(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsubw_PP_sat __builtin_HEXAGON_A2_vsubws
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=xor(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_xor_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_xor_RR __builtin_HEXAGON_A2_xor
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=xor(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_xor_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_xor_PP __builtin_HEXAGON_A2_xorp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=zxtb(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_zxtb_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_zxtb_R __builtin_HEXAGON_A2_zxtb
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=zxth(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_zxth_R(Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_zxth_R __builtin_HEXAGON_A2_zxth
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=and(Rt32,~Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_and_RnR(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_and_RnR __builtin_HEXAGON_A4_andn
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=and(Rtt32,~Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_and_PnP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_and_PnP __builtin_HEXAGON_A4_andnp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=bitsplit(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_bitsplit_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_bitsplit_RR __builtin_HEXAGON_A4_bitsplit
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=bitsplit(Rs32,#u5)
+ C Intrinsic Prototype: Word64 Q6_P_bitsplit_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_bitsplit_RI __builtin_HEXAGON_A4_bitspliti
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=boundscheck(Rs32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_boundscheck_RP(Word32 Rs, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_boundscheck_RP __builtin_HEXAGON_A4_boundscheck
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmpb.eq(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmpb_eq_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmpb_eq_RR __builtin_HEXAGON_A4_cmpbeq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmpb.eq(Rs32,#u8)
+ C Intrinsic Prototype: Byte Q6_p_cmpb_eq_RI(Word32 Rs, Word32 Iu8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmpb_eq_RI __builtin_HEXAGON_A4_cmpbeqi
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmpb.gt(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmpb_gt_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmpb_gt_RR __builtin_HEXAGON_A4_cmpbgt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmpb.gt(Rs32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_cmpb_gt_RI(Word32 Rs, Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmpb_gt_RI __builtin_HEXAGON_A4_cmpbgti
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmpb.gtu(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmpb_gtu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmpb_gtu_RR __builtin_HEXAGON_A4_cmpbgtu
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmpb.gtu(Rs32,#u7)
+ C Intrinsic Prototype: Byte Q6_p_cmpb_gtu_RI(Word32 Rs, Word32 Iu7)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmpb_gtu_RI __builtin_HEXAGON_A4_cmpbgtui
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmph.eq(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmph_eq_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmph_eq_RR __builtin_HEXAGON_A4_cmpheq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmph.eq(Rs32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_cmph_eq_RI(Word32 Rs, Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmph_eq_RI __builtin_HEXAGON_A4_cmpheqi
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmph.gt(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmph_gt_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmph_gt_RR __builtin_HEXAGON_A4_cmphgt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmph.gt(Rs32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_cmph_gt_RI(Word32 Rs, Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmph_gt_RI __builtin_HEXAGON_A4_cmphgti
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmph.gtu(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmph_gtu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmph_gtu_RR __builtin_HEXAGON_A4_cmphgtu
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmph.gtu(Rs32,#u7)
+ C Intrinsic Prototype: Byte Q6_p_cmph_gtu_RI(Word32 Rs, Word32 Iu7)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmph_gtu_RI __builtin_HEXAGON_A4_cmphgtui
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=combine(#s8,Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_combine_IR(Word32 Is8, Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_combine_IR __builtin_HEXAGON_A4_combineir
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=combine(Rs32,#s8)
+ C Intrinsic Prototype: Word64 Q6_P_combine_RI(Word32 Rs, Word32 Is8)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_combine_RI __builtin_HEXAGON_A4_combineri
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cround(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_cround_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cround_RI __builtin_HEXAGON_A4_cround_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cround(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_cround_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cround_RR __builtin_HEXAGON_A4_cround_rr
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=modwrap(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_modwrap_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_modwrap_RR __builtin_HEXAGON_A4_modwrapu
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=or(Rt32,~Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_or_RnR(Word32 Rt, Word32 Rs)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_or_RnR __builtin_HEXAGON_A4_orn
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=or(Rtt32,~Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_or_PnP(Word64 Rtt, Word64 Rss)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_or_PnP __builtin_HEXAGON_A4_ornp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmp.eq(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_cmp_eq_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_cmp_eq_RR __builtin_HEXAGON_A4_rcmpeq
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmp.eq(Rs32,#s8)
+ C Intrinsic Prototype: Word32 Q6_R_cmp_eq_RI(Word32 Rs, Word32 Is8)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_cmp_eq_RI __builtin_HEXAGON_A4_rcmpeqi
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=!cmp.eq(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_not_cmp_eq_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_not_cmp_eq_RR __builtin_HEXAGON_A4_rcmpneq
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=!cmp.eq(Rs32,#s8)
+ C Intrinsic Prototype: Word32 Q6_R_not_cmp_eq_RI(Word32 Rs, Word32 Is8)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_not_cmp_eq_RI __builtin_HEXAGON_A4_rcmpneqi
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=round(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_round_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_round_RI __builtin_HEXAGON_A4_round_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=round(Rs32,#u5):sat
+ C Intrinsic Prototype: Word32 Q6_R_round_RI_sat(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_round_RI_sat __builtin_HEXAGON_A4_round_ri_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=round(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_round_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_round_RR __builtin_HEXAGON_A4_round_rr
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=round(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word32 Q6_R_round_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_round_RR_sat __builtin_HEXAGON_A4_round_rr_sat
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=tlbmatch(Rss32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_tlbmatch_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_tlbmatch_PR __builtin_HEXAGON_A4_tlbmatch
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=any8(vcmpb.eq(Rss32,Rtt32))
+ C Intrinsic Prototype: Byte Q6_p_any8_vcmpb_eq_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_any8_vcmpb_eq_PP __builtin_HEXAGON_A4_vcmpbeq_any
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpb.eq(Rss32,#u8)
+ C Intrinsic Prototype: Byte Q6_p_vcmpb_eq_PI(Word64 Rss, Word32 Iu8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpb_eq_PI __builtin_HEXAGON_A4_vcmpbeqi
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpb.gt(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_vcmpb_gt_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpb_gt_PP __builtin_HEXAGON_A4_vcmpbgt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpb.gt(Rss32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_vcmpb_gt_PI(Word64 Rss, Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpb_gt_PI __builtin_HEXAGON_A4_vcmpbgti
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpb.gtu(Rss32,#u7)
+ C Intrinsic Prototype: Byte Q6_p_vcmpb_gtu_PI(Word64 Rss, Word32 Iu7)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpb_gtu_PI __builtin_HEXAGON_A4_vcmpbgtui
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmph.eq(Rss32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_vcmph_eq_PI(Word64 Rss, Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmph_eq_PI __builtin_HEXAGON_A4_vcmpheqi
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmph.gt(Rss32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_vcmph_gt_PI(Word64 Rss, Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmph_gt_PI __builtin_HEXAGON_A4_vcmphgti
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmph.gtu(Rss32,#u7)
+ C Intrinsic Prototype: Byte Q6_p_vcmph_gtu_PI(Word64 Rss, Word32 Iu7)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmph_gtu_PI __builtin_HEXAGON_A4_vcmphgtui
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpw.eq(Rss32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_vcmpw_eq_PI(Word64 Rss, Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpw_eq_PI __builtin_HEXAGON_A4_vcmpweqi
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpw.gt(Rss32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_vcmpw_gt_PI(Word64 Rss, Word32 Is8)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpw_gt_PI __builtin_HEXAGON_A4_vcmpwgti
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=vcmpw.gtu(Rss32,#u7)
+ C Intrinsic Prototype: Byte Q6_p_vcmpw_gtu_PI(Word64 Rss, Word32 Iu7)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_vcmpw_gtu_PI __builtin_HEXAGON_A4_vcmpwgtui
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=vrmaxh(Rss32,Ru32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmaxh_PR(Word64 Rxx, Word64 Rss, Word32 Ru)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmaxh_PR __builtin_HEXAGON_A4_vrmaxh
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=vrmaxuh(Rss32,Ru32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmaxuh_PR(Word64 Rxx, Word64 Rss, Word32 Ru)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmaxuh_PR __builtin_HEXAGON_A4_vrmaxuh
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=vrmaxuw(Rss32,Ru32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmaxuw_PR(Word64 Rxx, Word64 Rss, Word32 Ru)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmaxuw_PR __builtin_HEXAGON_A4_vrmaxuw
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=vrmaxw(Rss32,Ru32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmaxw_PR(Word64 Rxx, Word64 Rss, Word32 Ru)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmaxw_PR __builtin_HEXAGON_A4_vrmaxw
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=vrminh(Rss32,Ru32)
+ C Intrinsic Prototype: Word64 Q6_P_vrminh_PR(Word64 Rxx, Word64 Rss, Word32 Ru)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrminh_PR __builtin_HEXAGON_A4_vrminh
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=vrminuh(Rss32,Ru32)
+ C Intrinsic Prototype: Word64 Q6_P_vrminuh_PR(Word64 Rxx, Word64 Rss, Word32 Ru)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrminuh_PR __builtin_HEXAGON_A4_vrminuh
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=vrminuw(Rss32,Ru32)
+ C Intrinsic Prototype: Word64 Q6_P_vrminuw_PR(Word64 Rxx, Word64 Rss, Word32 Ru)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrminuw_PR __builtin_HEXAGON_A4_vrminuw
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=vrminw(Rss32,Ru32)
+ C Intrinsic Prototype: Word64 Q6_P_vrminw_PR(Word64 Rxx, Word64 Rss, Word32 Ru)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrminw_PR __builtin_HEXAGON_A4_vrminw
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vaddhub(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word32 Q6_R_vaddhub_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vaddhub_PP_sat __builtin_HEXAGON_A5_vaddhubs
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=all8(Ps4)
+ C Intrinsic Prototype: Byte Q6_p_all8_p(Byte Ps)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_all8_p __builtin_HEXAGON_C2_all8
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=and(Pt4,Ps4)
+ C Intrinsic Prototype: Byte Q6_p_and_pp(Byte Pt, Byte Ps)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_and_pp __builtin_HEXAGON_C2_and
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=and(Pt4,!Ps4)
+ C Intrinsic Prototype: Byte Q6_p_and_pnp(Byte Pt, Byte Ps)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_and_pnp __builtin_HEXAGON_C2_andn
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=any8(Ps4)
+ C Intrinsic Prototype: Byte Q6_p_any8_p(Byte Ps)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_any8_p __builtin_HEXAGON_C2_any8
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=bitsclr(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_bitsclr_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_bitsclr_RR __builtin_HEXAGON_C2_bitsclr
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=bitsclr(Rs32,#u6)
+ C Intrinsic Prototype: Byte Q6_p_bitsclr_RI(Word32 Rs, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_bitsclr_RI __builtin_HEXAGON_C2_bitsclri
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=bitsset(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_bitsset_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_bitsset_RR __builtin_HEXAGON_C2_bitsset
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.eq(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmp_eq_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_eq_RR __builtin_HEXAGON_C2_cmpeq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.eq(Rs32,#s10)
+ C Intrinsic Prototype: Byte Q6_p_cmp_eq_RI(Word32 Rs, Word32 Is10)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_eq_RI __builtin_HEXAGON_C2_cmpeqi
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.eq(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_cmp_eq_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmp_eq_PP __builtin_HEXAGON_C2_cmpeqp
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.ge(Rs32,#s8)
+ C Intrinsic Prototype: Byte Q6_p_cmp_ge_RI(Word32 Rs, Word32 Is8)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_ge_RI __builtin_HEXAGON_C2_cmpgei
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.geu(Rs32,#u8)
+ C Intrinsic Prototype: Byte Q6_p_cmp_geu_RI(Word32 Rs, Word32 Iu8)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_geu_RI __builtin_HEXAGON_C2_cmpgeui
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.gt(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmp_gt_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_gt_RR __builtin_HEXAGON_C2_cmpgt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.gt(Rs32,#s10)
+ C Intrinsic Prototype: Byte Q6_p_cmp_gt_RI(Word32 Rs, Word32 Is10)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_gt_RI __builtin_HEXAGON_C2_cmpgti
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.gt(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_cmp_gt_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmp_gt_PP __builtin_HEXAGON_C2_cmpgtp
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.gtu(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmp_gtu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_gtu_RR __builtin_HEXAGON_C2_cmpgtu
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.gtu(Rs32,#u9)
+ C Intrinsic Prototype: Byte Q6_p_cmp_gtu_RI(Word32 Rs, Word32 Iu9)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_gtu_RI __builtin_HEXAGON_C2_cmpgtui
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.gtu(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_cmp_gtu_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_cmp_gtu_PP __builtin_HEXAGON_C2_cmpgtup
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.lt(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmp_lt_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_lt_RR __builtin_HEXAGON_C2_cmplt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=cmp.ltu(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_cmp_ltu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_cmp_ltu_RR __builtin_HEXAGON_C2_cmpltu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mask(Pt4)
+ C Intrinsic Prototype: Word64 Q6_P_mask_p(Byte Pt)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mask_p __builtin_HEXAGON_C2_mask
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mux(Pu4,Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_mux_pRR(Byte Pu, Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_mux_pRR __builtin_HEXAGON_C2_mux
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mux(Pu4,#s8,#S8)
+ C Intrinsic Prototype: Word32 Q6_R_mux_pII(Byte Pu, Word32 Is8, Word32 IS8)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_mux_pII __builtin_HEXAGON_C2_muxii
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mux(Pu4,Rs32,#s8)
+ C Intrinsic Prototype: Word32 Q6_R_mux_pRI(Byte Pu, Word32 Rs, Word32 Is8)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_mux_pRI __builtin_HEXAGON_C2_muxir
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mux(Pu4,#s8,Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_mux_pIR(Byte Pu, Word32 Is8, Word32 Rs)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_mux_pIR __builtin_HEXAGON_C2_muxri
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=not(Ps4)
+ C Intrinsic Prototype: Byte Q6_p_not_p(Byte Ps)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_not_p __builtin_HEXAGON_C2_not
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=or(Pt4,Ps4)
+ C Intrinsic Prototype: Byte Q6_p_or_pp(Byte Pt, Byte Ps)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_or_pp __builtin_HEXAGON_C2_or
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=or(Pt4,!Ps4)
+ C Intrinsic Prototype: Byte Q6_p_or_pnp(Byte Pt, Byte Ps)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_or_pnp __builtin_HEXAGON_C2_orn
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=Ps4
+ C Intrinsic Prototype: Byte Q6_p_equals_p(Byte Ps)
+ Instruction Type: MAPPING
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_equals_p __builtin_HEXAGON_C2_pxfer_map
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=Ps4
+ C Intrinsic Prototype: Word32 Q6_R_equals_p(Byte Ps)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_equals_p __builtin_HEXAGON_C2_tfrpr
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=Rs32
+ C Intrinsic Prototype: Byte Q6_p_equals_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_equals_R __builtin_HEXAGON_C2_tfrrp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vitpack(Ps4,Pt4)
+ C Intrinsic Prototype: Word32 Q6_R_vitpack_pp(Byte Ps, Byte Pt)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vitpack_pp __builtin_HEXAGON_C2_vitpack
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmux(Pu4,Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vmux_pPP(Byte Pu, Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmux_pPP __builtin_HEXAGON_C2_vmux
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=xor(Ps4,Pt4)
+ C Intrinsic Prototype: Byte Q6_p_xor_pp(Byte Ps, Byte Pt)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_xor_pp __builtin_HEXAGON_C2_xor
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=and(Ps4,and(Pt4,Pu4))
+ C Intrinsic Prototype: Byte Q6_p_and_and_ppp(Byte Ps, Byte Pt, Byte Pu)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_and_and_ppp __builtin_HEXAGON_C4_and_and
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=and(Ps4,and(Pt4,!Pu4))
+ C Intrinsic Prototype: Byte Q6_p_and_and_ppnp(Byte Ps, Byte Pt, Byte Pu)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_and_and_ppnp __builtin_HEXAGON_C4_and_andn
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=and(Ps4,or(Pt4,Pu4))
+ C Intrinsic Prototype: Byte Q6_p_and_or_ppp(Byte Ps, Byte Pt, Byte Pu)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_and_or_ppp __builtin_HEXAGON_C4_and_or
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=and(Ps4,or(Pt4,!Pu4))
+ C Intrinsic Prototype: Byte Q6_p_and_or_ppnp(Byte Ps, Byte Pt, Byte Pu)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_and_or_ppnp __builtin_HEXAGON_C4_and_orn
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!cmp.gt(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_not_cmp_gt_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_not_cmp_gt_RR __builtin_HEXAGON_C4_cmplte
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!cmp.gt(Rs32,#s10)
+ C Intrinsic Prototype: Byte Q6_p_not_cmp_gt_RI(Word32 Rs, Word32 Is10)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_not_cmp_gt_RI __builtin_HEXAGON_C4_cmpltei
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!cmp.gtu(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_not_cmp_gtu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_not_cmp_gtu_RR __builtin_HEXAGON_C4_cmplteu
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!cmp.gtu(Rs32,#u9)
+ C Intrinsic Prototype: Byte Q6_p_not_cmp_gtu_RI(Word32 Rs, Word32 Iu9)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_not_cmp_gtu_RI __builtin_HEXAGON_C4_cmplteui
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!cmp.eq(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_not_cmp_eq_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_not_cmp_eq_RR __builtin_HEXAGON_C4_cmpneq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!cmp.eq(Rs32,#s10)
+ C Intrinsic Prototype: Byte Q6_p_not_cmp_eq_RI(Word32 Rs, Word32 Is10)
+ Instruction Type: ALU32_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_p_not_cmp_eq_RI __builtin_HEXAGON_C4_cmpneqi
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=fastcorner9(Ps4,Pt4)
+ C Intrinsic Prototype: Byte Q6_p_fastcorner9_pp(Byte Ps, Byte Pt)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_fastcorner9_pp __builtin_HEXAGON_C4_fastcorner9
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!fastcorner9(Ps4,Pt4)
+ C Intrinsic Prototype: Byte Q6_p_not_fastcorner9_pp(Byte Ps, Byte Pt)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_not_fastcorner9_pp __builtin_HEXAGON_C4_fastcorner9_not
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!bitsclr(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_not_bitsclr_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_not_bitsclr_RR __builtin_HEXAGON_C4_nbitsclr
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!bitsclr(Rs32,#u6)
+ C Intrinsic Prototype: Byte Q6_p_not_bitsclr_RI(Word32 Rs, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_not_bitsclr_RI __builtin_HEXAGON_C4_nbitsclri
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!bitsset(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_not_bitsset_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_not_bitsset_RR __builtin_HEXAGON_C4_nbitsset
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=or(Ps4,and(Pt4,Pu4))
+ C Intrinsic Prototype: Byte Q6_p_or_and_ppp(Byte Ps, Byte Pt, Byte Pu)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_or_and_ppp __builtin_HEXAGON_C4_or_and
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=or(Ps4,and(Pt4,!Pu4))
+ C Intrinsic Prototype: Byte Q6_p_or_and_ppnp(Byte Ps, Byte Pt, Byte Pu)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_or_and_ppnp __builtin_HEXAGON_C4_or_andn
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=or(Ps4,or(Pt4,Pu4))
+ C Intrinsic Prototype: Byte Q6_p_or_or_ppp(Byte Ps, Byte Pt, Byte Pu)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_or_or_ppp __builtin_HEXAGON_C4_or_or
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=or(Ps4,or(Pt4,!Pu4))
+ C Intrinsic Prototype: Byte Q6_p_or_or_ppnp(Byte Ps, Byte Pt, Byte Pu)
+ Instruction Type: CR
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_or_or_ppnp __builtin_HEXAGON_C4_or_orn
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_d2df(Rss32)
+ C Intrinsic Prototype: Float64 Q6_P_convert_d2df_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_d2df_P __builtin_HEXAGON_F2_conv_d2df
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_d2sf(Rss32)
+ C Intrinsic Prototype: Float32 Q6_R_convert_d2sf_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_d2sf_P __builtin_HEXAGON_F2_conv_d2sf
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_df2d(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_convert_df2d_P(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_df2d_P __builtin_HEXAGON_F2_conv_df2d
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_df2d(Rss32):chop
+ C Intrinsic Prototype: Word64 Q6_P_convert_df2d_P_chop(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_df2d_P_chop __builtin_HEXAGON_F2_conv_df2d_chop
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_df2sf(Rss32)
+ C Intrinsic Prototype: Float32 Q6_R_convert_df2sf_P(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_df2sf_P __builtin_HEXAGON_F2_conv_df2sf
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_df2ud(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_convert_df2ud_P(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_df2ud_P __builtin_HEXAGON_F2_conv_df2ud
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_df2ud(Rss32):chop
+ C Intrinsic Prototype: Word64 Q6_P_convert_df2ud_P_chop(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_df2ud_P_chop __builtin_HEXAGON_F2_conv_df2ud_chop
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_df2uw(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_convert_df2uw_P(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_df2uw_P __builtin_HEXAGON_F2_conv_df2uw
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_df2uw(Rss32):chop
+ C Intrinsic Prototype: Word32 Q6_R_convert_df2uw_P_chop(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_df2uw_P_chop __builtin_HEXAGON_F2_conv_df2uw_chop
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_df2w(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_convert_df2w_P(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_df2w_P __builtin_HEXAGON_F2_conv_df2w
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_df2w(Rss32):chop
+ C Intrinsic Prototype: Word32 Q6_R_convert_df2w_P_chop(Float64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_df2w_P_chop __builtin_HEXAGON_F2_conv_df2w_chop
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_sf2d(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_convert_sf2d_R(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_sf2d_R __builtin_HEXAGON_F2_conv_sf2d
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_sf2d(Rs32):chop
+ C Intrinsic Prototype: Word64 Q6_P_convert_sf2d_R_chop(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_sf2d_R_chop __builtin_HEXAGON_F2_conv_sf2d_chop
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_sf2df(Rs32)
+ C Intrinsic Prototype: Float64 Q6_P_convert_sf2df_R(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_sf2df_R __builtin_HEXAGON_F2_conv_sf2df
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_sf2ud(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_convert_sf2ud_R(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_sf2ud_R __builtin_HEXAGON_F2_conv_sf2ud
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_sf2ud(Rs32):chop
+ C Intrinsic Prototype: Word64 Q6_P_convert_sf2ud_R_chop(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_sf2ud_R_chop __builtin_HEXAGON_F2_conv_sf2ud_chop
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_sf2uw(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_convert_sf2uw_R(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_sf2uw_R __builtin_HEXAGON_F2_conv_sf2uw
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_sf2uw(Rs32):chop
+ C Intrinsic Prototype: Word32 Q6_R_convert_sf2uw_R_chop(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_sf2uw_R_chop __builtin_HEXAGON_F2_conv_sf2uw_chop
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_sf2w(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_convert_sf2w_R(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_sf2w_R __builtin_HEXAGON_F2_conv_sf2w
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_sf2w(Rs32):chop
+ C Intrinsic Prototype: Word32 Q6_R_convert_sf2w_R_chop(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_sf2w_R_chop __builtin_HEXAGON_F2_conv_sf2w_chop
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_ud2df(Rss32)
+ C Intrinsic Prototype: Float64 Q6_P_convert_ud2df_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_ud2df_P __builtin_HEXAGON_F2_conv_ud2df
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_ud2sf(Rss32)
+ C Intrinsic Prototype: Float32 Q6_R_convert_ud2sf_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_ud2sf_P __builtin_HEXAGON_F2_conv_ud2sf
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_uw2df(Rs32)
+ C Intrinsic Prototype: Float64 Q6_P_convert_uw2df_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_uw2df_R __builtin_HEXAGON_F2_conv_uw2df
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_uw2sf(Rs32)
+ C Intrinsic Prototype: Float32 Q6_R_convert_uw2sf_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_uw2sf_R __builtin_HEXAGON_F2_conv_uw2sf
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=convert_w2df(Rs32)
+ C Intrinsic Prototype: Float64 Q6_P_convert_w2df_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_convert_w2df_R __builtin_HEXAGON_F2_conv_w2df
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=convert_w2sf(Rs32)
+ C Intrinsic Prototype: Float32 Q6_R_convert_w2sf_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_convert_w2sf_R __builtin_HEXAGON_F2_conv_w2sf
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=dfclass(Rss32,#u5)
+ C Intrinsic Prototype: Byte Q6_p_dfclass_PI(Float64 Rss, Word32 Iu5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_dfclass_PI __builtin_HEXAGON_F2_dfclass
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=dfcmp.eq(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_dfcmp_eq_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_dfcmp_eq_PP __builtin_HEXAGON_F2_dfcmpeq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=dfcmp.ge(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_dfcmp_ge_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_dfcmp_ge_PP __builtin_HEXAGON_F2_dfcmpge
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=dfcmp.gt(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_dfcmp_gt_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_dfcmp_gt_PP __builtin_HEXAGON_F2_dfcmpgt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=dfcmp.uo(Rss32,Rtt32)
+ C Intrinsic Prototype: Byte Q6_p_dfcmp_uo_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_dfcmp_uo_PP __builtin_HEXAGON_F2_dfcmpuo
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=dfmake(#u10):neg
+ C Intrinsic Prototype: Float64 Q6_P_dfmake_I_neg(Word32 Iu10)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfmake_I_neg __builtin_HEXAGON_F2_dfimm_n
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=dfmake(#u10):pos
+ C Intrinsic Prototype: Float64 Q6_P_dfmake_I_pos(Word32 Iu10)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfmake_I_pos __builtin_HEXAGON_F2_dfimm_p
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sfadd(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sfadd_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfadd_RR __builtin_HEXAGON_F2_sfadd
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=sfclass(Rs32,#u5)
+ C Intrinsic Prototype: Byte Q6_p_sfclass_RI(Float32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_sfclass_RI __builtin_HEXAGON_F2_sfclass
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=sfcmp.eq(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_sfcmp_eq_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_sfcmp_eq_RR __builtin_HEXAGON_F2_sfcmpeq
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=sfcmp.ge(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_sfcmp_ge_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_sfcmp_ge_RR __builtin_HEXAGON_F2_sfcmpge
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=sfcmp.gt(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_sfcmp_gt_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_sfcmp_gt_RR __builtin_HEXAGON_F2_sfcmpgt
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=sfcmp.uo(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_sfcmp_uo_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_sfcmp_uo_RR __builtin_HEXAGON_F2_sfcmpuo
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sffixupd(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sffixupd_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sffixupd_RR __builtin_HEXAGON_F2_sffixupd
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sffixupn(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sffixupn_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sffixupn_RR __builtin_HEXAGON_F2_sffixupn
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sffixupr(Rs32)
+ C Intrinsic Prototype: Float32 Q6_R_sffixupr_R(Float32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sffixupr_R __builtin_HEXAGON_F2_sffixupr
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=sfmpy(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sfmpyacc_RR(Float32 Rx, Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmpyacc_RR __builtin_HEXAGON_F2_sffma
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=sfmpy(Rs32,Rt32):lib
+ C Intrinsic Prototype: Float32 Q6_R_sfmpyacc_RR_lib(Float32 Rx, Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmpyacc_RR_lib __builtin_HEXAGON_F2_sffma_lib
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=sfmpy(Rs32,Rt32,Pu4):scale
+ C Intrinsic Prototype: Float32 Q6_R_sfmpyacc_RRp_scale(Float32 Rx, Float32 Rs, Float32 Rt, Byte Pu)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmpyacc_RRp_scale __builtin_HEXAGON_F2_sffma_sc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=sfmpy(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sfmpynac_RR(Float32 Rx, Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmpynac_RR __builtin_HEXAGON_F2_sffms
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=sfmpy(Rs32,Rt32):lib
+ C Intrinsic Prototype: Float32 Q6_R_sfmpynac_RR_lib(Float32 Rx, Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmpynac_RR_lib __builtin_HEXAGON_F2_sffms_lib
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sfmake(#u10):neg
+ C Intrinsic Prototype: Float32 Q6_R_sfmake_I_neg(Word32 Iu10)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmake_I_neg __builtin_HEXAGON_F2_sfimm_n
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sfmake(#u10):pos
+ C Intrinsic Prototype: Float32 Q6_R_sfmake_I_pos(Word32 Iu10)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmake_I_pos __builtin_HEXAGON_F2_sfimm_p
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sfmax(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sfmax_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmax_RR __builtin_HEXAGON_F2_sfmax
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sfmin(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sfmin_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmin_RR __builtin_HEXAGON_F2_sfmin
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sfmpy(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sfmpy_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfmpy_RR __builtin_HEXAGON_F2_sfmpy
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=sfsub(Rs32,Rt32)
+ C Intrinsic Prototype: Float32 Q6_R_sfsub_RR(Float32 Rs, Float32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sfsub_RR __builtin_HEXAGON_F2_sfsub
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memb(Rx32++#s4:0:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memb_IM_circ(void** Rx, Word32 Is4_0, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memb_IM_circ __builtin_HEXAGON_L2_loadrb_pci
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memb(Rx32++I:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memb_M_circ(void** Rx, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memb_M_circ __builtin_HEXAGON_L2_loadrb_pcr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=memd(Rx32++#s4:3:circ(Mu2))
+ C Intrinsic Prototype: Word64 Q6_P_memd_IM_circ(void** Rx, Word32 Is4_3, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_P_memd_IM_circ __builtin_HEXAGON_L2_loadrd_pci
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=memd(Rx32++I:circ(Mu2))
+ C Intrinsic Prototype: Word64 Q6_P_memd_M_circ(void** Rx, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_P_memd_M_circ __builtin_HEXAGON_L2_loadrd_pcr
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memh(Rx32++#s4:1:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memh_IM_circ(void** Rx, Word32 Is4_1, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memh_IM_circ __builtin_HEXAGON_L2_loadrh_pci
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memh(Rx32++I:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memh_M_circ(void** Rx, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memh_M_circ __builtin_HEXAGON_L2_loadrh_pcr
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memw(Rx32++#s4:2:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memw_IM_circ(void** Rx, Word32 Is4_2, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memw_IM_circ __builtin_HEXAGON_L2_loadri_pci
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memw(Rx32++I:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memw_M_circ(void** Rx, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memw_M_circ __builtin_HEXAGON_L2_loadri_pcr
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memub(Rx32++#s4:0:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memub_IM_circ(void** Rx, Word32 Is4_0, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memub_IM_circ __builtin_HEXAGON_L2_loadrub_pci
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memub(Rx32++I:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memub_M_circ(void** Rx, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memub_M_circ __builtin_HEXAGON_L2_loadrub_pcr
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memuh(Rx32++#s4:1:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memuh_IM_circ(void** Rx, Word32 Is4_1, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memuh_IM_circ __builtin_HEXAGON_L2_loadruh_pci
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=memuh(Rx32++I:circ(Mu2))
+ C Intrinsic Prototype: Word32 Q6_R_memuh_M_circ(void** Rx, Word32 Mu, void* BaseAddress)
+ Instruction Type: LD
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_R_memuh_M_circ __builtin_HEXAGON_L2_loadruh_pcr
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=add(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_addacc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_addacc_RR __builtin_HEXAGON_M2_acci
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=add(Rs32,#s8)
+ C Intrinsic Prototype: Word32 Q6_R_addacc_RI(Word32 Rx, Word32 Rs, Word32 Is8)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_addacc_RI __builtin_HEXAGON_M2_accii
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpyi(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyiacc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpyiacc_RR __builtin_HEXAGON_M2_cmaci_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpyr(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyracc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpyracc_RR __builtin_HEXAGON_M2_cmacr_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpy(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpyacc_RR_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpyacc_RR_sat __builtin_HEXAGON_M2_cmacs_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpy(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpyacc_RR_s1_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpyacc_RR_s1_sat __builtin_HEXAGON_M2_cmacs_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpy(Rs32,Rt32*):sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpyacc_RR_conj_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpyacc_RR_conj_sat __builtin_HEXAGON_M2_cmacsc_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpy(Rs32,Rt32*):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpyacc_RR_conj_s1_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpyacc_RR_conj_s1_sat __builtin_HEXAGON_M2_cmacsc_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpyi(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyi_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpyi_RR __builtin_HEXAGON_M2_cmpyi_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpyr(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyr_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpyr_RR __builtin_HEXAGON_M2_cmpyr_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpy(Rs32,Rt32):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpy_RR_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cmpy_RR_rnd_sat __builtin_HEXAGON_M2_cmpyrs_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpy(Rs32,Rt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpy_RR_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cmpy_RR_s1_rnd_sat __builtin_HEXAGON_M2_cmpyrs_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpy(Rs32,Rt32*):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpy_RR_conj_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cmpy_RR_conj_rnd_sat __builtin_HEXAGON_M2_cmpyrsc_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpy(Rs32,Rt32*):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpy_RR_conj_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cmpy_RR_conj_s1_rnd_sat __builtin_HEXAGON_M2_cmpyrsc_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpy(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpy_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpy_RR_sat __builtin_HEXAGON_M2_cmpys_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpy(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpy_RR_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpy_RR_s1_sat __builtin_HEXAGON_M2_cmpys_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpy(Rs32,Rt32*):sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpy_RR_conj_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpy_RR_conj_sat __builtin_HEXAGON_M2_cmpysc_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpy(Rs32,Rt32*):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpy_RR_conj_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpy_RR_conj_s1_sat __builtin_HEXAGON_M2_cmpysc_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=cmpy(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpynac_RR_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpynac_RR_sat __builtin_HEXAGON_M2_cnacs_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=cmpy(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpynac_RR_s1_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpynac_RR_s1_sat __builtin_HEXAGON_M2_cnacs_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=cmpy(Rs32,Rt32*):sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpynac_RR_conj_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpynac_RR_conj_sat __builtin_HEXAGON_M2_cnacsc_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=cmpy(Rs32,Rt32*):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_cmpynac_RR_conj_s1_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cmpynac_RR_conj_s1_sat __builtin_HEXAGON_M2_cnacsc_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RR __builtin_HEXAGON_M2_dpmpyss_acc_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RR __builtin_HEXAGON_M2_dpmpyss_nac_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32,Rt32):rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RR_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RR_rnd __builtin_HEXAGON_M2_dpmpyss_rnd_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RR __builtin_HEXAGON_M2_dpmpyss_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RR __builtin_HEXAGON_M2_dpmpyuu_acc_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RR __builtin_HEXAGON_M2_dpmpyuu_nac_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32,Rt32)
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RR __builtin_HEXAGON_M2_dpmpyuu_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32,Rt32.h):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RRh_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RRh_s1_rnd_sat __builtin_HEXAGON_M2_hmmpyh_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32,Rt32.h):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RRh_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RRh_s1_sat __builtin_HEXAGON_M2_hmmpyh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32,Rt32.l):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RRl_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RRl_s1_rnd_sat __builtin_HEXAGON_M2_hmmpyl_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32,Rt32.l):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RRl_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RRl_s1_sat __builtin_HEXAGON_M2_hmmpyl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyi(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_mpyiacc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyiacc_RR __builtin_HEXAGON_M2_maci
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyi(Rs32,#u8)
+ C Intrinsic Prototype: Word32 Q6_R_mpyinac_RI(Word32 Rx, Word32 Rs, Word32 Iu8)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyinac_RI __builtin_HEXAGON_M2_macsin
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyi(Rs32,#u8)
+ C Intrinsic Prototype: Word32 Q6_R_mpyiacc_RI(Word32 Rx, Word32 Rs, Word32 Iu8)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyiacc_RI __builtin_HEXAGON_M2_macsip
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpywoh(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywohacc_PP_rnd_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywohacc_PP_rnd_sat __builtin_HEXAGON_M2_mmachs_rs0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpywoh(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywohacc_PP_s1_rnd_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywohacc_PP_s1_rnd_sat __builtin_HEXAGON_M2_mmachs_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpywoh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywohacc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywohacc_PP_sat __builtin_HEXAGON_M2_mmachs_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpywoh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywohacc_PP_s1_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywohacc_PP_s1_sat __builtin_HEXAGON_M2_mmachs_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyweh(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywehacc_PP_rnd_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywehacc_PP_rnd_sat __builtin_HEXAGON_M2_mmacls_rs0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyweh(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywehacc_PP_s1_rnd_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywehacc_PP_s1_rnd_sat __builtin_HEXAGON_M2_mmacls_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyweh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywehacc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywehacc_PP_sat __builtin_HEXAGON_M2_mmacls_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyweh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywehacc_PP_s1_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywehacc_PP_s1_sat __builtin_HEXAGON_M2_mmacls_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpywouh(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywouhacc_PP_rnd_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywouhacc_PP_rnd_sat __builtin_HEXAGON_M2_mmacuhs_rs0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpywouh(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywouhacc_PP_s1_rnd_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywouhacc_PP_s1_rnd_sat __builtin_HEXAGON_M2_mmacuhs_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpywouh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywouhacc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywouhacc_PP_sat __builtin_HEXAGON_M2_mmacuhs_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpywouh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywouhacc_PP_s1_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywouhacc_PP_s1_sat __builtin_HEXAGON_M2_mmacuhs_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyweuh(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweuhacc_PP_rnd_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweuhacc_PP_rnd_sat __builtin_HEXAGON_M2_mmaculs_rs0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyweuh(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweuhacc_PP_s1_rnd_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweuhacc_PP_s1_rnd_sat __builtin_HEXAGON_M2_mmaculs_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyweuh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweuhacc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweuhacc_PP_sat __builtin_HEXAGON_M2_mmaculs_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyweuh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweuhacc_PP_s1_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweuhacc_PP_s1_sat __builtin_HEXAGON_M2_mmaculs_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpywoh(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywoh_PP_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywoh_PP_rnd_sat __builtin_HEXAGON_M2_mmpyh_rs0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpywoh(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywoh_PP_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywoh_PP_s1_rnd_sat __builtin_HEXAGON_M2_mmpyh_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpywoh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywoh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywoh_PP_sat __builtin_HEXAGON_M2_mmpyh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpywoh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywoh_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywoh_PP_s1_sat __builtin_HEXAGON_M2_mmpyh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyweh(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweh_PP_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweh_PP_rnd_sat __builtin_HEXAGON_M2_mmpyl_rs0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyweh(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweh_PP_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweh_PP_s1_rnd_sat __builtin_HEXAGON_M2_mmpyl_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyweh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweh_PP_sat __builtin_HEXAGON_M2_mmpyl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyweh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweh_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweh_PP_s1_sat __builtin_HEXAGON_M2_mmpyl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpywouh(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywouh_PP_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywouh_PP_rnd_sat __builtin_HEXAGON_M2_mmpyuh_rs0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpywouh(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywouh_PP_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywouh_PP_s1_rnd_sat __builtin_HEXAGON_M2_mmpyuh_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpywouh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywouh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywouh_PP_sat __builtin_HEXAGON_M2_mmpyuh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpywouh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpywouh_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpywouh_PP_s1_sat __builtin_HEXAGON_M2_mmpyuh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyweuh(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweuh_PP_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweuh_PP_rnd_sat __builtin_HEXAGON_M2_mmpyul_rs0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyweuh(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweuh_PP_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweuh_PP_s1_rnd_sat __builtin_HEXAGON_M2_mmpyul_rs1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyweuh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweuh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweuh_PP_sat __builtin_HEXAGON_M2_mmpyul_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyweuh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyweuh_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyweuh_PP_s1_sat __builtin_HEXAGON_M2_mmpyul_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RhRh(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RhRh __builtin_HEXAGON_M2_mpy_acc_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RhRh_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RhRh_s1 __builtin_HEXAGON_M2_mpy_acc_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RhRl(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RhRl __builtin_HEXAGON_M2_mpy_acc_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RhRl_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RhRl_s1 __builtin_HEXAGON_M2_mpy_acc_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RlRh(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RlRh __builtin_HEXAGON_M2_mpy_acc_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RlRh_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RlRh_s1 __builtin_HEXAGON_M2_mpy_acc_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RlRl(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RlRl __builtin_HEXAGON_M2_mpy_acc_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RlRl_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RlRl_s1 __builtin_HEXAGON_M2_mpy_acc_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.h,Rt32.h):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RhRh_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RhRh_sat __builtin_HEXAGON_M2_mpy_acc_sat_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.h,Rt32.h):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RhRh_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RhRh_s1_sat __builtin_HEXAGON_M2_mpy_acc_sat_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.h,Rt32.l):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RhRl_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RhRl_sat __builtin_HEXAGON_M2_mpy_acc_sat_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.h,Rt32.l):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RhRl_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RhRl_s1_sat __builtin_HEXAGON_M2_mpy_acc_sat_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.l,Rt32.h):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RlRh_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RlRh_sat __builtin_HEXAGON_M2_mpy_acc_sat_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.l,Rt32.h):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RlRh_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RlRh_s1_sat __builtin_HEXAGON_M2_mpy_acc_sat_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.l,Rt32.l):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RlRl_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RlRl_sat __builtin_HEXAGON_M2_mpy_acc_sat_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32.l,Rt32.l):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RlRl_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RlRl_s1_sat __builtin_HEXAGON_M2_mpy_acc_sat_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRh(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRh __builtin_HEXAGON_M2_mpy_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRh_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRh_s1 __builtin_HEXAGON_M2_mpy_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRl(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRl __builtin_HEXAGON_M2_mpy_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRl_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRl_s1 __builtin_HEXAGON_M2_mpy_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRh(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRh __builtin_HEXAGON_M2_mpy_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRh_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRh_s1 __builtin_HEXAGON_M2_mpy_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRl(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRl __builtin_HEXAGON_M2_mpy_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRl_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRl_s1 __builtin_HEXAGON_M2_mpy_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RhRh(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RhRh __builtin_HEXAGON_M2_mpy_nac_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RhRh_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RhRh_s1 __builtin_HEXAGON_M2_mpy_nac_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RhRl(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RhRl __builtin_HEXAGON_M2_mpy_nac_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RhRl_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RhRl_s1 __builtin_HEXAGON_M2_mpy_nac_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RlRh(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RlRh __builtin_HEXAGON_M2_mpy_nac_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RlRh_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RlRh_s1 __builtin_HEXAGON_M2_mpy_nac_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RlRl(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RlRl __builtin_HEXAGON_M2_mpy_nac_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RlRl_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RlRl_s1 __builtin_HEXAGON_M2_mpy_nac_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.h,Rt32.h):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RhRh_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RhRh_sat __builtin_HEXAGON_M2_mpy_nac_sat_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.h,Rt32.h):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RhRh_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RhRh_s1_sat __builtin_HEXAGON_M2_mpy_nac_sat_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.h,Rt32.l):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RhRl_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RhRl_sat __builtin_HEXAGON_M2_mpy_nac_sat_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.h,Rt32.l):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RhRl_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RhRl_s1_sat __builtin_HEXAGON_M2_mpy_nac_sat_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.l,Rt32.h):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RlRh_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RlRh_sat __builtin_HEXAGON_M2_mpy_nac_sat_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.l,Rt32.h):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RlRh_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RlRh_s1_sat __builtin_HEXAGON_M2_mpy_nac_sat_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.l,Rt32.l):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RlRl_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RlRl_sat __builtin_HEXAGON_M2_mpy_nac_sat_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32.l,Rt32.l):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RlRl_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RlRl_s1_sat __builtin_HEXAGON_M2_mpy_nac_sat_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.h):rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRh_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRh_rnd __builtin_HEXAGON_M2_mpy_rnd_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.h):<<1:rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRh_s1_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRh_s1_rnd __builtin_HEXAGON_M2_mpy_rnd_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.l):rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRl_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRl_rnd __builtin_HEXAGON_M2_mpy_rnd_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.l):<<1:rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRl_s1_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRl_s1_rnd __builtin_HEXAGON_M2_mpy_rnd_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.h):rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRh_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRh_rnd __builtin_HEXAGON_M2_mpy_rnd_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.h):<<1:rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRh_s1_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRh_s1_rnd __builtin_HEXAGON_M2_mpy_rnd_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.l):rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRl_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRl_rnd __builtin_HEXAGON_M2_mpy_rnd_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.l):<<1:rnd
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRl_s1_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRl_s1_rnd __builtin_HEXAGON_M2_mpy_rnd_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.h):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRh_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRh_sat __builtin_HEXAGON_M2_mpy_sat_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.h):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRh_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRh_s1_sat __builtin_HEXAGON_M2_mpy_sat_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.l):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRl_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRl_sat __builtin_HEXAGON_M2_mpy_sat_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.l):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRl_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRl_s1_sat __builtin_HEXAGON_M2_mpy_sat_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.h):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRh_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRh_sat __builtin_HEXAGON_M2_mpy_sat_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.h):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRh_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRh_s1_sat __builtin_HEXAGON_M2_mpy_sat_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.l):sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRl_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRl_sat __builtin_HEXAGON_M2_mpy_sat_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.l):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRl_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRl_s1_sat __builtin_HEXAGON_M2_mpy_sat_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.h):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRh_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRh_rnd_sat __builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.h):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRh_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRh_s1_rnd_sat __builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.l):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRl_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRl_rnd_sat __builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.h,Rt32.l):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RhRl_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RhRl_s1_rnd_sat __builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.h):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRh_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRh_rnd_sat __builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.h):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRh_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRh_s1_rnd_sat __builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.l):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRl_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRl_rnd_sat __builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32.l,Rt32.l):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RlRl_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RlRl_s1_rnd_sat __builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RR __builtin_HEXAGON_M2_mpy_up
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32,Rt32):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RR_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RR_s1 __builtin_HEXAGON_M2_mpy_up_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpy(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpy_RR_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpy_RR_s1_sat __builtin_HEXAGON_M2_mpy_up_s1_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RhRh(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RhRh __builtin_HEXAGON_M2_mpyd_acc_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RhRh_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RhRh_s1 __builtin_HEXAGON_M2_mpyd_acc_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RhRl(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RhRl __builtin_HEXAGON_M2_mpyd_acc_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RhRl_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RhRl_s1 __builtin_HEXAGON_M2_mpyd_acc_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RlRh(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RlRh __builtin_HEXAGON_M2_mpyd_acc_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RlRh_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RlRh_s1 __builtin_HEXAGON_M2_mpyd_acc_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RlRl(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RlRl __builtin_HEXAGON_M2_mpyd_acc_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpy(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyacc_RlRl_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyacc_RlRl_s1 __builtin_HEXAGON_M2_mpyd_acc_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RhRh(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RhRh __builtin_HEXAGON_M2_mpyd_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RhRh_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RhRh_s1 __builtin_HEXAGON_M2_mpyd_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RhRl(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RhRl __builtin_HEXAGON_M2_mpyd_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RhRl_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RhRl_s1 __builtin_HEXAGON_M2_mpyd_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RlRh(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RlRh __builtin_HEXAGON_M2_mpyd_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RlRh_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RlRh_s1 __builtin_HEXAGON_M2_mpyd_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RlRl(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RlRl __builtin_HEXAGON_M2_mpyd_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RlRl_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RlRl_s1 __builtin_HEXAGON_M2_mpyd_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RhRh(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RhRh __builtin_HEXAGON_M2_mpyd_nac_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RhRh_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RhRh_s1 __builtin_HEXAGON_M2_mpyd_nac_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RhRl(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RhRl __builtin_HEXAGON_M2_mpyd_nac_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RhRl_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RhRl_s1 __builtin_HEXAGON_M2_mpyd_nac_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RlRh(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RlRh __builtin_HEXAGON_M2_mpyd_nac_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RlRh_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RlRh_s1 __builtin_HEXAGON_M2_mpyd_nac_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RlRl(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RlRl __builtin_HEXAGON_M2_mpyd_nac_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpy(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpynac_RlRl_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpynac_RlRl_s1 __builtin_HEXAGON_M2_mpyd_nac_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.h,Rt32.h):rnd
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RhRh_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RhRh_rnd __builtin_HEXAGON_M2_mpyd_rnd_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.h,Rt32.h):<<1:rnd
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RhRh_s1_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RhRh_s1_rnd __builtin_HEXAGON_M2_mpyd_rnd_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.h,Rt32.l):rnd
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RhRl_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RhRl_rnd __builtin_HEXAGON_M2_mpyd_rnd_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.h,Rt32.l):<<1:rnd
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RhRl_s1_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RhRl_s1_rnd __builtin_HEXAGON_M2_mpyd_rnd_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.l,Rt32.h):rnd
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RlRh_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RlRh_rnd __builtin_HEXAGON_M2_mpyd_rnd_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.l,Rt32.h):<<1:rnd
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RlRh_s1_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RlRh_s1_rnd __builtin_HEXAGON_M2_mpyd_rnd_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.l,Rt32.l):rnd
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RlRl_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RlRl_rnd __builtin_HEXAGON_M2_mpyd_rnd_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpy(Rs32.l,Rt32.l):<<1:rnd
+ C Intrinsic Prototype: Word64 Q6_P_mpy_RlRl_s1_rnd(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpy_RlRl_s1_rnd __builtin_HEXAGON_M2_mpyd_rnd_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyi(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_mpyi_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyi_RR __builtin_HEXAGON_M2_mpyi
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyi(Rs32,#m9)
+ C Intrinsic Prototype: Word32 Q6_R_mpyi_RI(Word32 Rs, Word32 Im9)
+ Instruction Type: M
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_mpyi_RI __builtin_HEXAGON_M2_mpysmi
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpysu(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_mpysu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpysu_RR __builtin_HEXAGON_M2_mpysu_up
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyu(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpyuacc_RhRh(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyuacc_RhRh __builtin_HEXAGON_M2_mpyu_acc_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyu(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyuacc_RhRh_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyuacc_RhRh_s1 __builtin_HEXAGON_M2_mpyu_acc_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyu(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpyuacc_RhRl(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyuacc_RhRl __builtin_HEXAGON_M2_mpyu_acc_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyu(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyuacc_RhRl_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyuacc_RhRl_s1 __builtin_HEXAGON_M2_mpyu_acc_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyu(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpyuacc_RlRh(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyuacc_RlRh __builtin_HEXAGON_M2_mpyu_acc_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyu(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyuacc_RlRh_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyuacc_RlRh_s1 __builtin_HEXAGON_M2_mpyu_acc_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyu(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpyuacc_RlRl(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyuacc_RlRl __builtin_HEXAGON_M2_mpyu_acc_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpyu(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyuacc_RlRl_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyuacc_RlRl_s1 __builtin_HEXAGON_M2_mpyu_acc_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RhRh(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RhRh __builtin_HEXAGON_M2_mpyu_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RhRh_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RhRh_s1 __builtin_HEXAGON_M2_mpyu_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RhRl(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RhRl __builtin_HEXAGON_M2_mpyu_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RhRl_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RhRl_s1 __builtin_HEXAGON_M2_mpyu_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RlRh(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RlRh __builtin_HEXAGON_M2_mpyu_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RlRh_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RlRh_s1 __builtin_HEXAGON_M2_mpyu_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RlRl(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RlRl __builtin_HEXAGON_M2_mpyu_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RlRl_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RlRl_s1 __builtin_HEXAGON_M2_mpyu_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyu(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpyunac_RhRh(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyunac_RhRh __builtin_HEXAGON_M2_mpyu_nac_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyu(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyunac_RhRh_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyunac_RhRh_s1 __builtin_HEXAGON_M2_mpyu_nac_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyu(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpyunac_RhRl(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyunac_RhRl __builtin_HEXAGON_M2_mpyu_nac_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyu(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyunac_RhRl_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyunac_RhRl_s1 __builtin_HEXAGON_M2_mpyu_nac_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyu(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word32 Q6_R_mpyunac_RlRh(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyunac_RlRh __builtin_HEXAGON_M2_mpyu_nac_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyu(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyunac_RlRh_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyunac_RlRh_s1 __builtin_HEXAGON_M2_mpyu_nac_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyu(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word32 Q6_R_mpyunac_RlRl(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyunac_RlRl __builtin_HEXAGON_M2_mpyu_nac_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyu(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word32 Q6_R_mpyunac_RlRl_s1(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyunac_RlRl_s1 __builtin_HEXAGON_M2_mpyu_nac_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyu(Rs32,Rt32)
+ C Intrinsic Prototype: UWord32 Q6_R_mpyu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyu_RR __builtin_HEXAGON_M2_mpyu_up
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RhRh(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RhRh __builtin_HEXAGON_M2_mpyud_acc_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RhRh_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RhRh_s1 __builtin_HEXAGON_M2_mpyud_acc_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RhRl(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RhRl __builtin_HEXAGON_M2_mpyud_acc_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RhRl_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RhRl_s1 __builtin_HEXAGON_M2_mpyud_acc_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RlRh(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RlRh __builtin_HEXAGON_M2_mpyud_acc_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RlRh_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RlRh_s1 __builtin_HEXAGON_M2_mpyud_acc_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RlRl(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RlRl __builtin_HEXAGON_M2_mpyud_acc_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=mpyu(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyuacc_RlRl_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyuacc_RlRl_s1 __builtin_HEXAGON_M2_mpyud_acc_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RhRh(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RhRh __builtin_HEXAGON_M2_mpyud_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RhRh_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RhRh_s1 __builtin_HEXAGON_M2_mpyud_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RhRl(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RhRl __builtin_HEXAGON_M2_mpyud_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RhRl_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RhRl_s1 __builtin_HEXAGON_M2_mpyud_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RlRh(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RlRh __builtin_HEXAGON_M2_mpyud_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RlRh_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RlRh_s1 __builtin_HEXAGON_M2_mpyud_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RlRl(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RlRl __builtin_HEXAGON_M2_mpyud_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=mpyu(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: UWord64 Q6_P_mpyu_RlRl_s1(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyu_RlRl_s1 __builtin_HEXAGON_M2_mpyud_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32.h,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RhRh(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RhRh __builtin_HEXAGON_M2_mpyud_nac_hh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32.h,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RhRh_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RhRh_s1 __builtin_HEXAGON_M2_mpyud_nac_hh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32.h,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RhRl(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RhRl __builtin_HEXAGON_M2_mpyud_nac_hl_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32.h,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RhRl_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RhRl_s1 __builtin_HEXAGON_M2_mpyud_nac_hl_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32.l,Rt32.h)
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RlRh(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RlRh __builtin_HEXAGON_M2_mpyud_nac_lh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32.l,Rt32.h):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RlRh_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RlRh_s1 __builtin_HEXAGON_M2_mpyud_nac_lh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32.l,Rt32.l)
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RlRl(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RlRl __builtin_HEXAGON_M2_mpyud_nac_ll_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=mpyu(Rs32.l,Rt32.l):<<1
+ C Intrinsic Prototype: Word64 Q6_P_mpyunac_RlRl_s1(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_mpyunac_RlRl_s1 __builtin_HEXAGON_M2_mpyud_nac_ll_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=mpyui(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_mpyui_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_mpyui_RR __builtin_HEXAGON_M2_mpyui
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=add(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_addnac_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_addnac_RR __builtin_HEXAGON_M2_nacci
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=add(Rs32,#s8)
+ C Intrinsic Prototype: Word32 Q6_R_addnac_RI(Word32 Rx, Word32 Rs, Word32 Is8)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_addnac_RI __builtin_HEXAGON_M2_naccii
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=sub(Rt32,Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_subacc_RR(Word32 Rx, Word32 Rt, Word32 Rs)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_subacc_RR __builtin_HEXAGON_M2_subacc
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vabsdiffh(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vabsdiffh_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vabsdiffh_PP __builtin_HEXAGON_M2_vabsdiffh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vabsdiffw(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vabsdiffw_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vabsdiffw_PP __builtin_HEXAGON_M2_vabsdiffw
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vcmpyi(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vcmpyiacc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vcmpyiacc_PP_sat __builtin_HEXAGON_M2_vcmac_s0_sat_i
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vcmpyr(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vcmpyracc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vcmpyracc_PP_sat __builtin_HEXAGON_M2_vcmac_s0_sat_r
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vcmpyi(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vcmpyi_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vcmpyi_PP_sat __builtin_HEXAGON_M2_vcmpy_s0_sat_i
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vcmpyr(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vcmpyr_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vcmpyr_PP_sat __builtin_HEXAGON_M2_vcmpy_s0_sat_r
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vcmpyi(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vcmpyi_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vcmpyi_PP_s1_sat __builtin_HEXAGON_M2_vcmpy_s1_sat_i
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vcmpyr(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vcmpyr_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vcmpyr_PP_s1_sat __builtin_HEXAGON_M2_vcmpy_s1_sat_r
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vdmpy(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vdmpyacc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vdmpyacc_PP_sat __builtin_HEXAGON_M2_vdmacs_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vdmpy(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vdmpyacc_PP_s1_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vdmpyacc_PP_s1_sat __builtin_HEXAGON_M2_vdmacs_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vdmpy(Rss32,Rtt32):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_vdmpy_PP_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vdmpy_PP_rnd_sat __builtin_HEXAGON_M2_vdmpyrs_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vdmpy(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_vdmpy_PP_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vdmpy_PP_s1_rnd_sat __builtin_HEXAGON_M2_vdmpyrs_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vdmpy(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vdmpy_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vdmpy_PP_sat __builtin_HEXAGON_M2_vdmpys_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vdmpy(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vdmpy_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vdmpy_PP_s1_sat __builtin_HEXAGON_M2_vdmpys_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyh(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vmpyhacc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyhacc_RR __builtin_HEXAGON_M2_vmac2
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyeh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vmpyehacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyehacc_PP __builtin_HEXAGON_M2_vmac2es
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyeh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyehacc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyehacc_PP_sat __builtin_HEXAGON_M2_vmac2es_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyeh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyehacc_PP_s1_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyehacc_PP_s1_sat __builtin_HEXAGON_M2_vmac2es_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyh(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyhacc_RR_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyhacc_RR_sat __builtin_HEXAGON_M2_vmac2s_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyh(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyhacc_RR_s1_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyhacc_RR_s1_sat __builtin_HEXAGON_M2_vmac2s_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyhsu(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyhsuacc_RR_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyhsuacc_RR_sat __builtin_HEXAGON_M2_vmac2su_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpyhsu(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyhsuacc_RR_s1_sat(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyhsuacc_RR_s1_sat __builtin_HEXAGON_M2_vmac2su_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyeh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyeh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyeh_PP_sat __builtin_HEXAGON_M2_vmpy2es_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyeh(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyeh_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyeh_PP_s1_sat __builtin_HEXAGON_M2_vmpy2es_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyh(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyh_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyh_RR_sat __builtin_HEXAGON_M2_vmpy2s_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vmpyh(Rs32,Rt32):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_vmpyh_RR_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vmpyh_RR_rnd_sat __builtin_HEXAGON_M2_vmpy2s_s0pack
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyh(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyh_RR_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyh_RR_s1_sat __builtin_HEXAGON_M2_vmpy2s_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vmpyh(Rs32,Rt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_vmpyh_RR_s1_rnd_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vmpyh_RR_s1_rnd_sat __builtin_HEXAGON_M2_vmpy2s_s1pack
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyhsu(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyhsu_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyhsu_RR_sat __builtin_HEXAGON_M2_vmpy2su_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpyhsu(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vmpyhsu_RR_s1_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpyhsu_RR_s1_sat __builtin_HEXAGON_M2_vmpy2su_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vraddh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word32 Q6_R_vraddh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vraddh_PP __builtin_HEXAGON_M2_vraddh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vradduh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word32 Q6_R_vradduh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vradduh_PP __builtin_HEXAGON_M2_vradduh
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrcmpyi(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpyiacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcmpyiacc_PP __builtin_HEXAGON_M2_vrcmaci_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrcmpyi(Rss32,Rtt32*)
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpyiacc_PP_conj(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcmpyiacc_PP_conj __builtin_HEXAGON_M2_vrcmaci_s0c
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrcmpyr(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpyracc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcmpyracc_PP __builtin_HEXAGON_M2_vrcmacr_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrcmpyr(Rss32,Rtt32*)
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpyracc_PP_conj(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcmpyracc_PP_conj __builtin_HEXAGON_M2_vrcmacr_s0c
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrcmpyi(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpyi_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcmpyi_PP __builtin_HEXAGON_M2_vrcmpyi_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrcmpyi(Rss32,Rtt32*)
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpyi_PP_conj(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcmpyi_PP_conj __builtin_HEXAGON_M2_vrcmpyi_s0c
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrcmpyr(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpyr_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcmpyr_PP __builtin_HEXAGON_M2_vrcmpyr_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrcmpyr(Rss32,Rtt32*)
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpyr_PP_conj(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcmpyr_PP_conj __builtin_HEXAGON_M2_vrcmpyr_s0c
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrcmpys(Rss32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpysacc_PR_s1_sat(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_vrcmpysacc_PR_s1_sat __builtin_HEXAGON_M2_vrcmpys_acc_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrcmpys(Rss32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vrcmpys_PR_s1_sat(Word64 Rss, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_vrcmpys_PR_s1_sat __builtin_HEXAGON_M2_vrcmpys_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vrcmpys(Rss32,Rt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_vrcmpys_PR_s1_rnd_sat(Word64 Rss, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vrcmpys_PR_s1_rnd_sat __builtin_HEXAGON_M2_vrcmpys_s1rp
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrmpyh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpyhacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpyhacc_PP __builtin_HEXAGON_M2_vrmac_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrmpyh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpyh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpyh_PP __builtin_HEXAGON_M2_vrmpy_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rx32^=xor(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_xorxacc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_xorxacc_RR __builtin_HEXAGON_M2_xor_xacc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=and(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_andand_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_andand_RR __builtin_HEXAGON_M4_and_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=and(Rs32,~Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_andand_RnR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_andand_RnR __builtin_HEXAGON_M4_and_andn
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=or(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_orand_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_orand_RR __builtin_HEXAGON_M4_and_or
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=xor(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_xorand_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_xorand_RR __builtin_HEXAGON_M4_and_xor
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyiwh(Rss32,Rt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyiwh_PR_s1_rnd_sat(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cmpyiwh_PR_s1_rnd_sat __builtin_HEXAGON_M4_cmpyi_wh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyiwh(Rss32,Rt32*):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyiwh_PR_conj_s1_rnd_sat(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cmpyiwh_PR_conj_s1_rnd_sat __builtin_HEXAGON_M4_cmpyi_whc
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyrwh(Rss32,Rt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyrwh_PR_s1_rnd_sat(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cmpyrwh_PR_s1_rnd_sat __builtin_HEXAGON_M4_cmpyr_wh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyrwh(Rss32,Rt32*):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyrwh_PR_conj_s1_rnd_sat(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cmpyrwh_PR_conj_s1_rnd_sat __builtin_HEXAGON_M4_cmpyr_whc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=mpy(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpyacc_RR_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyacc_RR_s1_sat __builtin_HEXAGON_M4_mac_up_s1_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(#u6,mpyi(Rs32,#U6))
+ C Intrinsic Prototype: Word32 Q6_R_add_mpyi_IRI(Word32 Iu6, Word32 Rs, Word32 IU6)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_mpyi_IRI __builtin_HEXAGON_M4_mpyri_addi
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Ru32,mpyi(Rs32,#u6))
+ C Intrinsic Prototype: Word32 Q6_R_add_mpyi_RRI(Word32 Ru, Word32 Rs, Word32 Iu6)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_mpyi_RRI __builtin_HEXAGON_M4_mpyri_addr
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Ru32,mpyi(#u6:2,Rs32))
+ C Intrinsic Prototype: Word32 Q6_R_add_mpyi_RIR(Word32 Ru, Word32 Iu6_2, Word32 Rs)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_mpyi_RIR __builtin_HEXAGON_M4_mpyri_addr_u2
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(#u6,mpyi(Rs32,Rt32))
+ C Intrinsic Prototype: Word32 Q6_R_add_mpyi_IRR(Word32 Iu6, Word32 Rs, Word32 Rt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_mpyi_IRR __builtin_HEXAGON_M4_mpyrr_addi
+
+/* ==========================================================================
+ Assembly Syntax: Ry32=add(Ru32,mpyi(Ry32,Rs32))
+ C Intrinsic Prototype: Word32 Q6_R_add_mpyi_RRR(Word32 Ru, Word32 Ry, Word32 Rs)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_mpyi_RRR __builtin_HEXAGON_M4_mpyrr_addr
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpy(Rs32,Rt32):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_mpynac_RR_s1_sat(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpynac_RR_s1_sat __builtin_HEXAGON_M4_nac_up_s1_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=and(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_andor_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_andor_RR __builtin_HEXAGON_M4_or_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=and(Rs32,~Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_andor_RnR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_andor_RnR __builtin_HEXAGON_M4_or_andn
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=or(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_oror_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_oror_RR __builtin_HEXAGON_M4_or_or
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=xor(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_xoror_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_xoror_RR __builtin_HEXAGON_M4_or_xor
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=pmpyw(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_pmpyw_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_pmpyw_RR __builtin_HEXAGON_M4_pmpyw
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=pmpyw(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_pmpywxacc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_pmpywxacc_RR __builtin_HEXAGON_M4_pmpyw_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vpmpyh(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vpmpyh_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vpmpyh_RR __builtin_HEXAGON_M4_vpmpyh
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=vpmpyh(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vpmpyhxacc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vpmpyhxacc_RR __builtin_HEXAGON_M4_vpmpyh_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrmpyweh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpywehacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpywehacc_PP __builtin_HEXAGON_M4_vrmpyeh_acc_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrmpyweh(Rss32,Rtt32):<<1
+ C Intrinsic Prototype: Word64 Q6_P_vrmpywehacc_PP_s1(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpywehacc_PP_s1 __builtin_HEXAGON_M4_vrmpyeh_acc_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrmpyweh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpyweh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpyweh_PP __builtin_HEXAGON_M4_vrmpyeh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrmpyweh(Rss32,Rtt32):<<1
+ C Intrinsic Prototype: Word64 Q6_P_vrmpyweh_PP_s1(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpyweh_PP_s1 __builtin_HEXAGON_M4_vrmpyeh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrmpywoh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpywohacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpywohacc_PP __builtin_HEXAGON_M4_vrmpyoh_acc_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrmpywoh(Rss32,Rtt32):<<1
+ C Intrinsic Prototype: Word64 Q6_P_vrmpywohacc_PP_s1(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpywohacc_PP_s1 __builtin_HEXAGON_M4_vrmpyoh_acc_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrmpywoh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpywoh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpywoh_PP __builtin_HEXAGON_M4_vrmpyoh_s0
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrmpywoh(Rss32,Rtt32):<<1
+ C Intrinsic Prototype: Word64 Q6_P_vrmpywoh_PP_s1(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpywoh_PP_s1 __builtin_HEXAGON_M4_vrmpyoh_s1
+
+/* ==========================================================================
+ Assembly Syntax: Rx32^=and(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_andxacc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_andxacc_RR __builtin_HEXAGON_M4_xor_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32^=and(Rs32,~Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_andxacc_RnR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_andxacc_RnR __builtin_HEXAGON_M4_xor_andn
+
+/* ==========================================================================
+ Assembly Syntax: Rx32^=or(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_orxacc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_orxacc_RR __builtin_HEXAGON_M4_xor_or
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=xor(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_xorxacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_xorxacc_PP __builtin_HEXAGON_M4_xor_xacc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vdmpybsu(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vdmpybsuacc_PP_sat(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vdmpybsuacc_PP_sat __builtin_HEXAGON_M5_vdmacbsu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vdmpybsu(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vdmpybsu_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vdmpybsu_PP_sat __builtin_HEXAGON_M5_vdmpybsu
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpybsu(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vmpybsuacc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpybsuacc_RR __builtin_HEXAGON_M5_vmacbsu
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vmpybu(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vmpybuacc_RR(Word64 Rxx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpybuacc_RR __builtin_HEXAGON_M5_vmacbuu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpybsu(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vmpybsu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpybsu_RR __builtin_HEXAGON_M5_vmpybsu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vmpybu(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vmpybu_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vmpybu_RR __builtin_HEXAGON_M5_vmpybuu
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrmpybsu(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpybsuacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpybsuacc_PP __builtin_HEXAGON_M5_vrmacbsu
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrmpybu(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpybuacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpybuacc_PP __builtin_HEXAGON_M5_vrmacbuu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrmpybsu(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpybsu_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpybsu_PP __builtin_HEXAGON_M5_vrmpybsu
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrmpybu(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrmpybu_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrmpybu_PP __builtin_HEXAGON_M5_vrmpybuu
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=addasl(Rt32,Rs32,#u3)
+ C Intrinsic Prototype: Word32 Q6_R_addasl_RRI(Word32 Rt, Word32 Rs, Word32 Iu3)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_addasl_RRI __builtin_HEXAGON_S2_addasl_rrri
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=asl(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_asl_PI(Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asl_PI __builtin_HEXAGON_S2_asl_i_p
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=asl(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_aslacc_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_aslacc_PI __builtin_HEXAGON_S2_asl_i_p_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32&=asl(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_asland_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asland_PI __builtin_HEXAGON_S2_asl_i_p_and
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=asl(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_aslnac_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_aslnac_PI __builtin_HEXAGON_S2_asl_i_p_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32|=asl(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_aslor_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_aslor_PI __builtin_HEXAGON_S2_asl_i_p_or
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=asl(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_aslxacc_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_aslxacc_PI __builtin_HEXAGON_S2_asl_i_p_xacc
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asl(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_asl_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asl_RI __builtin_HEXAGON_S2_asl_i_r
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=asl(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_aslacc_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_aslacc_RI __builtin_HEXAGON_S2_asl_i_r_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=asl(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_asland_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asland_RI __builtin_HEXAGON_S2_asl_i_r_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=asl(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_aslnac_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_aslnac_RI __builtin_HEXAGON_S2_asl_i_r_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=asl(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_aslor_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_aslor_RI __builtin_HEXAGON_S2_asl_i_r_or
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asl(Rs32,#u5):sat
+ C Intrinsic Prototype: Word32 Q6_R_asl_RI_sat(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asl_RI_sat __builtin_HEXAGON_S2_asl_i_r_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rx32^=asl(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_aslxacc_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_aslxacc_RI __builtin_HEXAGON_S2_asl_i_r_xacc
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaslh(Rss32,#u4)
+ C Intrinsic Prototype: Word64 Q6_P_vaslh_PI(Word64 Rss, Word32 Iu4)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaslh_PI __builtin_HEXAGON_S2_asl_i_vh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaslw(Rss32,#u5)
+ C Intrinsic Prototype: Word64 Q6_P_vaslw_PI(Word64 Rss, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaslw_PI __builtin_HEXAGON_S2_asl_i_vw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=asl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_asl_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asl_PR __builtin_HEXAGON_S2_asl_r_p
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=asl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_aslacc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_aslacc_PR __builtin_HEXAGON_S2_asl_r_p_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32&=asl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_asland_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asland_PR __builtin_HEXAGON_S2_asl_r_p_and
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=asl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_aslnac_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_aslnac_PR __builtin_HEXAGON_S2_asl_r_p_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32|=asl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_aslor_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_aslor_PR __builtin_HEXAGON_S2_asl_r_p_or
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=asl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_aslxacc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_aslxacc_PR __builtin_HEXAGON_S2_asl_r_p_xor
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_asl_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asl_RR __builtin_HEXAGON_S2_asl_r_r
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=asl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_aslacc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_aslacc_RR __builtin_HEXAGON_S2_asl_r_r_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=asl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_asland_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asland_RR __builtin_HEXAGON_S2_asl_r_r_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=asl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_aslnac_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_aslnac_RR __builtin_HEXAGON_S2_asl_r_r_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=asl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_aslor_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_aslor_RR __builtin_HEXAGON_S2_asl_r_r_or
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asl(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word32 Q6_R_asl_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asl_RR_sat __builtin_HEXAGON_S2_asl_r_r_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaslh(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vaslh_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaslh_PR __builtin_HEXAGON_S2_asl_r_vh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vaslw(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vaslw_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vaslw_PR __builtin_HEXAGON_S2_asl_r_vw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=asr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_asr_PI(Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asr_PI __builtin_HEXAGON_S2_asr_i_p
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=asr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_asracc_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asracc_PI __builtin_HEXAGON_S2_asr_i_p_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32&=asr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_asrand_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asrand_PI __builtin_HEXAGON_S2_asr_i_p_and
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=asr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_asrnac_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asrnac_PI __builtin_HEXAGON_S2_asr_i_p_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32|=asr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_asror_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asror_PI __builtin_HEXAGON_S2_asr_i_p_or
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=asr(Rss32,#u6):rnd
+ C Intrinsic Prototype: Word64 Q6_P_asr_PI_rnd(Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asr_PI_rnd __builtin_HEXAGON_S2_asr_i_p_rnd
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=asrrnd(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_asrrnd_PI(Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_asrrnd_PI __builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_asr_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asr_RI __builtin_HEXAGON_S2_asr_i_r
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=asr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_asracc_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asracc_RI __builtin_HEXAGON_S2_asr_i_r_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=asr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_asrand_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asrand_RI __builtin_HEXAGON_S2_asr_i_r_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=asr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_asrnac_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asrnac_RI __builtin_HEXAGON_S2_asr_i_r_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=asr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_asror_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asror_RI __builtin_HEXAGON_S2_asr_i_r_or
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asr(Rs32,#u5):rnd
+ C Intrinsic Prototype: Word32 Q6_R_asr_RI_rnd(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asr_RI_rnd __builtin_HEXAGON_S2_asr_i_r_rnd
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asrrnd(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_asrrnd_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_asrrnd_RI __builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vasrw(Rss32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_vasrw_PI(Word64 Rss, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vasrw_PI __builtin_HEXAGON_S2_asr_i_svw_trun
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vasrh(Rss32,#u4)
+ C Intrinsic Prototype: Word64 Q6_P_vasrh_PI(Word64 Rss, Word32 Iu4)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vasrh_PI __builtin_HEXAGON_S2_asr_i_vh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vasrw(Rss32,#u5)
+ C Intrinsic Prototype: Word64 Q6_P_vasrw_PI(Word64 Rss, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vasrw_PI __builtin_HEXAGON_S2_asr_i_vw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=asr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_asr_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asr_PR __builtin_HEXAGON_S2_asr_r_p
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=asr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_asracc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asracc_PR __builtin_HEXAGON_S2_asr_r_p_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32&=asr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_asrand_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asrand_PR __builtin_HEXAGON_S2_asr_r_p_and
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=asr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_asrnac_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asrnac_PR __builtin_HEXAGON_S2_asr_r_p_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32|=asr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_asror_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asror_PR __builtin_HEXAGON_S2_asr_r_p_or
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=asr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_asrxacc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_asrxacc_PR __builtin_HEXAGON_S2_asr_r_p_xor
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_asr_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asr_RR __builtin_HEXAGON_S2_asr_r_r
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=asr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_asracc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asracc_RR __builtin_HEXAGON_S2_asr_r_r_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=asr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_asrand_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asrand_RR __builtin_HEXAGON_S2_asr_r_r_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=asr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_asrnac_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asrnac_RR __builtin_HEXAGON_S2_asr_r_r_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=asr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_asror_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asror_RR __builtin_HEXAGON_S2_asr_r_r_or
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=asr(Rs32,Rt32):sat
+ C Intrinsic Prototype: Word32 Q6_R_asr_RR_sat(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_asr_RR_sat __builtin_HEXAGON_S2_asr_r_r_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vasrw(Rss32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_vasrw_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vasrw_PR __builtin_HEXAGON_S2_asr_r_svw_trun
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vasrh(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vasrh_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vasrh_PR __builtin_HEXAGON_S2_asr_r_vh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vasrw(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vasrw_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vasrw_PR __builtin_HEXAGON_S2_asr_r_vw
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=brev(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_brev_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_brev_R __builtin_HEXAGON_S2_brev
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=brev(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_brev_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_brev_P __builtin_HEXAGON_S2_brevp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cl0(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_cl0_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cl0_R __builtin_HEXAGON_S2_cl0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cl0(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_cl0_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cl0_P __builtin_HEXAGON_S2_cl0p
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cl1(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_cl1_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cl1_R __builtin_HEXAGON_S2_cl1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=cl1(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_cl1_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_cl1_P __builtin_HEXAGON_S2_cl1p
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=clb(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_clb_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_clb_R __builtin_HEXAGON_S2_clb
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=normamt(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_normamt_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_normamt_R __builtin_HEXAGON_S2_clbnorm
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=clb(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_clb_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_clb_P __builtin_HEXAGON_S2_clbp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=clrbit(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_clrbit_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_clrbit_RI __builtin_HEXAGON_S2_clrbit_i
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=clrbit(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_clrbit_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_clrbit_RR __builtin_HEXAGON_S2_clrbit_r
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=ct0(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_ct0_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_ct0_R __builtin_HEXAGON_S2_ct0
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=ct0(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_ct0_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_ct0_P __builtin_HEXAGON_S2_ct0p
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=ct1(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_ct1_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_ct1_R __builtin_HEXAGON_S2_ct1
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=ct1(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_ct1_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_ct1_P __builtin_HEXAGON_S2_ct1p
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=deinterleave(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_deinterleave_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_deinterleave_P __builtin_HEXAGON_S2_deinterleave
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=extractu(Rs32,#u5,#U5)
+ C Intrinsic Prototype: Word32 Q6_R_extractu_RII(Word32 Rs, Word32 Iu5, Word32 IU5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_extractu_RII __builtin_HEXAGON_S2_extractu
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=extractu(Rs32,Rtt32)
+ C Intrinsic Prototype: Word32 Q6_R_extractu_RP(Word32 Rs, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_extractu_RP __builtin_HEXAGON_S2_extractu_rp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=extractu(Rss32,#u6,#U6)
+ C Intrinsic Prototype: Word64 Q6_P_extractu_PII(Word64 Rss, Word32 Iu6, Word32 IU6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_extractu_PII __builtin_HEXAGON_S2_extractup
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=extractu(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_extractu_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_extractu_PP __builtin_HEXAGON_S2_extractup_rp
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=insert(Rs32,#u5,#U5)
+ C Intrinsic Prototype: Word32 Q6_R_insert_RII(Word32 Rx, Word32 Rs, Word32 Iu5, Word32 IU5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_insert_RII __builtin_HEXAGON_S2_insert
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=insert(Rs32,Rtt32)
+ C Intrinsic Prototype: Word32 Q6_R_insert_RP(Word32 Rx, Word32 Rs, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_insert_RP __builtin_HEXAGON_S2_insert_rp
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=insert(Rss32,#u6,#U6)
+ C Intrinsic Prototype: Word64 Q6_P_insert_PII(Word64 Rxx, Word64 Rss, Word32 Iu6, Word32 IU6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_insert_PII __builtin_HEXAGON_S2_insertp
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32=insert(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_insert_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_insert_PP __builtin_HEXAGON_S2_insertp_rp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=interleave(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_interleave_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_interleave_P __builtin_HEXAGON_S2_interleave
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=lfs(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_lfs_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lfs_PP __builtin_HEXAGON_S2_lfsp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=lsl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lsl_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsl_PR __builtin_HEXAGON_S2_lsl_r_p
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=lsl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lslacc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lslacc_PR __builtin_HEXAGON_S2_lsl_r_p_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32&=lsl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lsland_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsland_PR __builtin_HEXAGON_S2_lsl_r_p_and
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=lsl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lslnac_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lslnac_PR __builtin_HEXAGON_S2_lsl_r_p_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32|=lsl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lslor_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lslor_PR __builtin_HEXAGON_S2_lsl_r_p_or
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=lsl(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lslxacc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lslxacc_PR __builtin_HEXAGON_S2_lsl_r_p_xor
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=lsl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lsl_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsl_RR __builtin_HEXAGON_S2_lsl_r_r
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=lsl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lslacc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lslacc_RR __builtin_HEXAGON_S2_lsl_r_r_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=lsl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lsland_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsland_RR __builtin_HEXAGON_S2_lsl_r_r_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=lsl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lslnac_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lslnac_RR __builtin_HEXAGON_S2_lsl_r_r_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=lsl(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lslor_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lslor_RR __builtin_HEXAGON_S2_lsl_r_r_or
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vlslh(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vlslh_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vlslh_PR __builtin_HEXAGON_S2_lsl_r_vh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vlslw(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vlslw_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vlslw_PR __builtin_HEXAGON_S2_lsl_r_vw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=lsr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_lsr_PI(Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsr_PI __builtin_HEXAGON_S2_lsr_i_p
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=lsr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_lsracc_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsracc_PI __builtin_HEXAGON_S2_lsr_i_p_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32&=lsr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_lsrand_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsrand_PI __builtin_HEXAGON_S2_lsr_i_p_and
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=lsr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_lsrnac_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsrnac_PI __builtin_HEXAGON_S2_lsr_i_p_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32|=lsr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_lsror_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsror_PI __builtin_HEXAGON_S2_lsr_i_p_or
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=lsr(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_lsrxacc_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsrxacc_PI __builtin_HEXAGON_S2_lsr_i_p_xacc
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=lsr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_lsr_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsr_RI __builtin_HEXAGON_S2_lsr_i_r
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=lsr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_lsracc_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsracc_RI __builtin_HEXAGON_S2_lsr_i_r_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=lsr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_lsrand_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsrand_RI __builtin_HEXAGON_S2_lsr_i_r_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=lsr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_lsrnac_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsrnac_RI __builtin_HEXAGON_S2_lsr_i_r_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=lsr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_lsror_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsror_RI __builtin_HEXAGON_S2_lsr_i_r_or
+
+/* ==========================================================================
+ Assembly Syntax: Rx32^=lsr(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_lsrxacc_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsrxacc_RI __builtin_HEXAGON_S2_lsr_i_r_xacc
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vlsrh(Rss32,#u4)
+ C Intrinsic Prototype: Word64 Q6_P_vlsrh_PI(Word64 Rss, Word32 Iu4)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vlsrh_PI __builtin_HEXAGON_S2_lsr_i_vh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vlsrw(Rss32,#u5)
+ C Intrinsic Prototype: Word64 Q6_P_vlsrw_PI(Word64 Rss, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vlsrw_PI __builtin_HEXAGON_S2_lsr_i_vw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=lsr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lsr_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsr_PR __builtin_HEXAGON_S2_lsr_r_p
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=lsr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lsracc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsracc_PR __builtin_HEXAGON_S2_lsr_r_p_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32&=lsr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lsrand_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsrand_PR __builtin_HEXAGON_S2_lsr_r_p_and
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=lsr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lsrnac_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsrnac_PR __builtin_HEXAGON_S2_lsr_r_p_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32|=lsr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lsror_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsror_PR __builtin_HEXAGON_S2_lsr_r_p_or
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=lsr(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_lsrxacc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_lsrxacc_PR __builtin_HEXAGON_S2_lsr_r_p_xor
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=lsr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lsr_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsr_RR __builtin_HEXAGON_S2_lsr_r_r
+
+/* ==========================================================================
+ Assembly Syntax: Rx32+=lsr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lsracc_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsracc_RR __builtin_HEXAGON_S2_lsr_r_r_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rx32&=lsr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lsrand_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsrand_RR __builtin_HEXAGON_S2_lsr_r_r_and
+
+/* ==========================================================================
+ Assembly Syntax: Rx32-=lsr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lsrnac_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsrnac_RR __builtin_HEXAGON_S2_lsr_r_r_nac
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=lsr(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lsror_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsror_RR __builtin_HEXAGON_S2_lsr_r_r_or
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vlsrh(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vlsrh_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vlsrh_PR __builtin_HEXAGON_S2_lsr_r_vh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vlsrw(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vlsrw_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vlsrw_PR __builtin_HEXAGON_S2_lsr_r_vw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=packhl(Rs32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_packhl_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU32_3op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_packhl_RR __builtin_HEXAGON_S2_packhl
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=parity(Rss32,Rtt32)
+ C Intrinsic Prototype: Word32 Q6_R_parity_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_parity_PP __builtin_HEXAGON_S2_parityp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=setbit(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_setbit_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_setbit_RI __builtin_HEXAGON_S2_setbit_i
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=setbit(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_setbit_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_setbit_RR __builtin_HEXAGON_S2_setbit_r
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=shuffeb(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_shuffeb_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_shuffeb_PP __builtin_HEXAGON_S2_shuffeb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=shuffeh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_shuffeh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_shuffeh_PP __builtin_HEXAGON_S2_shuffeh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=shuffob(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_shuffob_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_shuffob_PP __builtin_HEXAGON_S2_shuffob
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=shuffoh(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_shuffoh_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_shuffoh_PP __builtin_HEXAGON_S2_shuffoh
+
+/* ==========================================================================
+ Assembly Syntax: memb(Rx32++#s4:0:circ(Mu2))=Rt32
+ C Intrinsic Prototype: void Q6_memb_IMR_circ(void** Rx, Word32 Is4_0, Word32 Mu, Word32 Rt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memb_IMR_circ __builtin_HEXAGON_S2_storerb_pci
+
+/* ==========================================================================
+ Assembly Syntax: memb(Rx32++I:circ(Mu2))=Rt32
+ C Intrinsic Prototype: void Q6_memb_MR_circ(void** Rx, Word32 Mu, Word32 Rt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memb_MR_circ __builtin_HEXAGON_S2_storerb_pcr
+
+/* ==========================================================================
+ Assembly Syntax: memd(Rx32++#s4:3:circ(Mu2))=Rtt32
+ C Intrinsic Prototype: void Q6_memd_IMP_circ(void** Rx, Word32 Is4_3, Word32 Mu, Word64 Rtt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memd_IMP_circ __builtin_HEXAGON_S2_storerd_pci
+
+/* ==========================================================================
+ Assembly Syntax: memd(Rx32++I:circ(Mu2))=Rtt32
+ C Intrinsic Prototype: void Q6_memd_MP_circ(void** Rx, Word32 Mu, Word64 Rtt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memd_MP_circ __builtin_HEXAGON_S2_storerd_pcr
+
+/* ==========================================================================
+ Assembly Syntax: memh(Rx32++#s4:1:circ(Mu2))=Rt32.h
+ C Intrinsic Prototype: void Q6_memh_IMRh_circ(void** Rx, Word32 Is4_1, Word32 Mu, Word32 Rt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memh_IMRh_circ __builtin_HEXAGON_S2_storerf_pci
+
+/* ==========================================================================
+ Assembly Syntax: memh(Rx32++I:circ(Mu2))=Rt32.h
+ C Intrinsic Prototype: void Q6_memh_MRh_circ(void** Rx, Word32 Mu, Word32 Rt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memh_MRh_circ __builtin_HEXAGON_S2_storerf_pcr
+
+/* ==========================================================================
+ Assembly Syntax: memh(Rx32++#s4:1:circ(Mu2))=Rt32
+ C Intrinsic Prototype: void Q6_memh_IMR_circ(void** Rx, Word32 Is4_1, Word32 Mu, Word32 Rt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memh_IMR_circ __builtin_HEXAGON_S2_storerh_pci
+
+/* ==========================================================================
+ Assembly Syntax: memh(Rx32++I:circ(Mu2))=Rt32
+ C Intrinsic Prototype: void Q6_memh_MR_circ(void** Rx, Word32 Mu, Word32 Rt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memh_MR_circ __builtin_HEXAGON_S2_storerh_pcr
+
+/* ==========================================================================
+ Assembly Syntax: memw(Rx32++#s4:2:circ(Mu2))=Rt32
+ C Intrinsic Prototype: void Q6_memw_IMR_circ(void** Rx, Word32 Is4_2, Word32 Mu, Word32 Rt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memw_IMR_circ __builtin_HEXAGON_S2_storeri_pci
+
+/* ==========================================================================
+ Assembly Syntax: memw(Rx32++I:circ(Mu2))=Rt32
+ C Intrinsic Prototype: void Q6_memw_MR_circ(void** Rx, Word32 Mu, Word32 Rt, void* BaseAddress)
+ Instruction Type: ST
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_memw_MR_circ __builtin_HEXAGON_S2_storeri_pcr
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsathb(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_vsathb_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vsathb_R __builtin_HEXAGON_S2_svsathb
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsathub(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_vsathub_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vsathub_R __builtin_HEXAGON_S2_svsathub
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=tableidxb(Rs32,#u4,#U5)
+ C Intrinsic Prototype: Word32 Q6_R_tableidxb_RII(Word32 Rx, Word32 Rs, Word32 Iu4, Word32 IU5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_tableidxb_RII __builtin_HEXAGON_S2_tableidxb_goodsyntax
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=tableidxd(Rs32,#u4,#U5)
+ C Intrinsic Prototype: Word32 Q6_R_tableidxd_RII(Word32 Rx, Word32 Rs, Word32 Iu4, Word32 IU5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_tableidxd_RII __builtin_HEXAGON_S2_tableidxd_goodsyntax
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=tableidxh(Rs32,#u4,#U5)
+ C Intrinsic Prototype: Word32 Q6_R_tableidxh_RII(Word32 Rx, Word32 Rs, Word32 Iu4, Word32 IU5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_tableidxh_RII __builtin_HEXAGON_S2_tableidxh_goodsyntax
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=tableidxw(Rs32,#u4,#U5)
+ C Intrinsic Prototype: Word32 Q6_R_tableidxw_RII(Word32 Rx, Word32 Rs, Word32 Iu4, Word32 IU5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_tableidxw_RII __builtin_HEXAGON_S2_tableidxw_goodsyntax
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=togglebit(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_togglebit_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_togglebit_RI __builtin_HEXAGON_S2_togglebit_i
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=togglebit(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_togglebit_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_togglebit_RR __builtin_HEXAGON_S2_togglebit_r
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=tstbit(Rs32,#u5)
+ C Intrinsic Prototype: Byte Q6_p_tstbit_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_tstbit_RI __builtin_HEXAGON_S2_tstbit_i
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=tstbit(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_tstbit_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_tstbit_RR __builtin_HEXAGON_S2_tstbit_r
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=valignb(Rtt32,Rss32,#u3)
+ C Intrinsic Prototype: Word64 Q6_P_valignb_PPI(Word64 Rtt, Word64 Rss, Word32 Iu3)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_valignb_PPI __builtin_HEXAGON_S2_valignib
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=valignb(Rtt32,Rss32,Pu4)
+ C Intrinsic Prototype: Word64 Q6_P_valignb_PPp(Word64 Rtt, Word64 Rss, Byte Pu)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_valignb_PPp __builtin_HEXAGON_S2_valignrb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vcnegh(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vcnegh_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vcnegh_PR __builtin_HEXAGON_S2_vcnegh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vcrotate(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vcrotate_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vcrotate_PR __builtin_HEXAGON_S2_vcrotate
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrcnegh(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_vrcneghacc_PR(Word64 Rxx, Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcneghacc_PR __builtin_HEXAGON_S2_vrcnegh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vrndwh(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_vrndwh_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vrndwh_P __builtin_HEXAGON_S2_vrndpackwh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vrndwh(Rss32):sat
+ C Intrinsic Prototype: Word32 Q6_R_vrndwh_P_sat(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vrndwh_P_sat __builtin_HEXAGON_S2_vrndpackwhs
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsathb(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_vsathb_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vsathb_P __builtin_HEXAGON_S2_vsathb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsathb(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vsathb_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsathb_P __builtin_HEXAGON_S2_vsathb_nopack
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsathub(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_vsathub_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vsathub_P __builtin_HEXAGON_S2_vsathub
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsathub(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vsathub_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsathub_P __builtin_HEXAGON_S2_vsathub_nopack
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsatwh(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_vsatwh_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vsatwh_P __builtin_HEXAGON_S2_vsatwh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsatwh(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vsatwh_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsatwh_P __builtin_HEXAGON_S2_vsatwh_nopack
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsatwuh(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_vsatwuh_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vsatwuh_P __builtin_HEXAGON_S2_vsatwuh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsatwuh(Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vsatwuh_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsatwuh_P __builtin_HEXAGON_S2_vsatwuh_nopack
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vsplatb(Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_vsplatb_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vsplatb_R __builtin_HEXAGON_S2_vsplatrb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsplath(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_vsplath_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsplath_R __builtin_HEXAGON_S2_vsplatrh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vspliceb(Rss32,Rtt32,#u3)
+ C Intrinsic Prototype: Word64 Q6_P_vspliceb_PPI(Word64 Rss, Word64 Rtt, Word32 Iu3)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vspliceb_PPI __builtin_HEXAGON_S2_vspliceib
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vspliceb(Rss32,Rtt32,Pu4)
+ C Intrinsic Prototype: Word64 Q6_P_vspliceb_PPp(Word64 Rss, Word64 Rtt, Byte Pu)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vspliceb_PPp __builtin_HEXAGON_S2_vsplicerb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsxtbh(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_vsxtbh_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsxtbh_R __builtin_HEXAGON_S2_vsxtbh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsxthw(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_vsxthw_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsxthw_R __builtin_HEXAGON_S2_vsxthw
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vtrunehb(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_vtrunehb_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vtrunehb_P __builtin_HEXAGON_S2_vtrunehb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vtrunewh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vtrunewh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vtrunewh_PP __builtin_HEXAGON_S2_vtrunewh
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vtrunohb(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_vtrunohb_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vtrunohb_P __builtin_HEXAGON_S2_vtrunohb
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vtrunowh(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vtrunowh_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vtrunowh_PP __builtin_HEXAGON_S2_vtrunowh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vzxtbh(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_vzxtbh_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vzxtbh_R __builtin_HEXAGON_S2_vzxtbh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vzxthw(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_vzxthw_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vzxthw_R __builtin_HEXAGON_S2_vzxthw
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rs32,add(Ru32,#s6))
+ C Intrinsic Prototype: Word32 Q6_R_add_add_RRI(Word32 Rs, Word32 Ru, Word32 Is6)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_add_RRI __builtin_HEXAGON_S4_addaddi
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=add(#u8,asl(Rx32,#U5))
+ C Intrinsic Prototype: Word32 Q6_R_add_asl_IRI(Word32 Iu8, Word32 Rx, Word32 IU5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_asl_IRI __builtin_HEXAGON_S4_addi_asl_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=add(#u8,lsr(Rx32,#U5))
+ C Intrinsic Prototype: Word32 Q6_R_add_lsr_IRI(Word32 Iu8, Word32 Rx, Word32 IU5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_lsr_IRI __builtin_HEXAGON_S4_addi_lsr_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=and(#u8,asl(Rx32,#U5))
+ C Intrinsic Prototype: Word32 Q6_R_and_asl_IRI(Word32 Iu8, Word32 Rx, Word32 IU5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_and_asl_IRI __builtin_HEXAGON_S4_andi_asl_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=and(#u8,lsr(Rx32,#U5))
+ C Intrinsic Prototype: Word32 Q6_R_and_lsr_IRI(Word32 Iu8, Word32 Rx, Word32 IU5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_and_lsr_IRI __builtin_HEXAGON_S4_andi_lsr_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(clb(Rs32),#s6)
+ C Intrinsic Prototype: Word32 Q6_R_add_clb_RI(Word32 Rs, Word32 Is6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_clb_RI __builtin_HEXAGON_S4_clbaddi
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(clb(Rss32),#s6)
+ C Intrinsic Prototype: Word32 Q6_R_add_clb_PI(Word64 Rss, Word32 Is6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_clb_PI __builtin_HEXAGON_S4_clbpaddi
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=normamt(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_normamt_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_normamt_P __builtin_HEXAGON_S4_clbpnorm
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=extract(Rs32,#u5,#U5)
+ C Intrinsic Prototype: Word32 Q6_R_extract_RII(Word32 Rs, Word32 Iu5, Word32 IU5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_extract_RII __builtin_HEXAGON_S4_extract
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=extract(Rs32,Rtt32)
+ C Intrinsic Prototype: Word32 Q6_R_extract_RP(Word32 Rs, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_extract_RP __builtin_HEXAGON_S4_extract_rp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=extract(Rss32,#u6,#U6)
+ C Intrinsic Prototype: Word64 Q6_P_extract_PII(Word64 Rss, Word32 Iu6, Word32 IU6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_extract_PII __builtin_HEXAGON_S4_extractp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=extract(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_extract_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_extract_PP __builtin_HEXAGON_S4_extractp_rp
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=lsl(#s6,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_lsl_IR(Word32 Is6, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_lsl_IR __builtin_HEXAGON_S4_lsli
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!tstbit(Rs32,#u5)
+ C Intrinsic Prototype: Byte Q6_p_not_tstbit_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_not_tstbit_RI __builtin_HEXAGON_S4_ntstbit_i
+
+/* ==========================================================================
+ Assembly Syntax: Pd4=!tstbit(Rs32,Rt32)
+ C Intrinsic Prototype: Byte Q6_p_not_tstbit_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_not_tstbit_RR __builtin_HEXAGON_S4_ntstbit_r
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=and(Rs32,#s10)
+ C Intrinsic Prototype: Word32 Q6_R_andor_RI(Word32 Rx, Word32 Rs, Word32 Is10)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_andor_RI __builtin_HEXAGON_S4_or_andi
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=or(Ru32,and(Rx32,#s10))
+ C Intrinsic Prototype: Word32 Q6_R_or_and_RRI(Word32 Ru, Word32 Rx, Word32 Is10)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_or_and_RRI __builtin_HEXAGON_S4_or_andix
+
+/* ==========================================================================
+ Assembly Syntax: Rx32|=or(Rs32,#s10)
+ C Intrinsic Prototype: Word32 Q6_R_oror_RI(Word32 Rx, Word32 Rs, Word32 Is10)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_oror_RI __builtin_HEXAGON_S4_or_ori
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=or(#u8,asl(Rx32,#U5))
+ C Intrinsic Prototype: Word32 Q6_R_or_asl_IRI(Word32 Iu8, Word32 Rx, Word32 IU5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_or_asl_IRI __builtin_HEXAGON_S4_ori_asl_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=or(#u8,lsr(Rx32,#U5))
+ C Intrinsic Prototype: Word32 Q6_R_or_lsr_IRI(Word32 Iu8, Word32 Rx, Word32 IU5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_or_lsr_IRI __builtin_HEXAGON_S4_ori_lsr_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=parity(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_parity_RR(Word32 Rs, Word32 Rt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_parity_RR __builtin_HEXAGON_S4_parity
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=add(Rs32,sub(#s6,Ru32))
+ C Intrinsic Prototype: Word32 Q6_R_add_sub_RIR(Word32 Rs, Word32 Is6, Word32 Ru)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_add_sub_RIR __builtin_HEXAGON_S4_subaddi
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=sub(#u8,asl(Rx32,#U5))
+ C Intrinsic Prototype: Word32 Q6_R_sub_asl_IRI(Word32 Iu8, Word32 Rx, Word32 IU5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_asl_IRI __builtin_HEXAGON_S4_subi_asl_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rx32=sub(#u8,lsr(Rx32,#U5))
+ C Intrinsic Prototype: Word32 Q6_R_sub_lsr_IRI(Word32 Iu8, Word32 Rx, Word32 IU5)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_sub_lsr_IRI __builtin_HEXAGON_S4_subi_lsr_ri
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vrcrotate(Rss32,Rt32,#u2)
+ C Intrinsic Prototype: Word64 Q6_P_vrcrotate_PRI(Word64 Rss, Word32 Rt, Word32 Iu2)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcrotate_PRI __builtin_HEXAGON_S4_vrcrotate
+
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vrcrotate(Rss32,Rt32,#u2)
+ C Intrinsic Prototype: Word64 Q6_P_vrcrotateacc_PRI(Word64 Rxx, Word64 Rss, Word32 Rt, Word32 Iu2)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vrcrotateacc_PRI __builtin_HEXAGON_S4_vrcrotate_acc
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vxaddsubh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vxaddsubh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vxaddsubh_PP_sat __builtin_HEXAGON_S4_vxaddsubh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vxaddsubh(Rss32,Rtt32):rnd:>>1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vxaddsubh_PP_rnd_rs1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vxaddsubh_PP_rnd_rs1_sat __builtin_HEXAGON_S4_vxaddsubhr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vxaddsubw(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vxaddsubw_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vxaddsubw_PP_sat __builtin_HEXAGON_S4_vxaddsubw
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vxsubaddh(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vxsubaddh_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vxsubaddh_PP_sat __builtin_HEXAGON_S4_vxsubaddh
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vxsubaddh(Rss32,Rtt32):rnd:>>1:sat
+ C Intrinsic Prototype: Word64 Q6_P_vxsubaddh_PP_rnd_rs1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vxsubaddh_PP_rnd_rs1_sat __builtin_HEXAGON_S4_vxsubaddhr
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vxsubaddw(Rss32,Rtt32):sat
+ C Intrinsic Prototype: Word64 Q6_P_vxsubaddw_PP_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vxsubaddw_PP_sat __builtin_HEXAGON_S4_vxsubaddw
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vasrhub(Rss32,#u4):rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_vasrhub_PI_rnd_sat(Word64 Rss, Word32 Iu4)
+ Instruction Type: S_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_R_vasrhub_PI_rnd_sat __builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=vasrhub(Rss32,#u4):sat
+ C Intrinsic Prototype: Word32 Q6_R_vasrhub_PI_sat(Word64 Rss, Word32 Iu4)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_vasrhub_PI_sat __builtin_HEXAGON_S5_asrhub_sat
+
+/* ==========================================================================
+ Assembly Syntax: Rd32=popcount(Rss32)
+ C Intrinsic Prototype: Word32 Q6_R_popcount_P(Word64 Rss)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_popcount_P __builtin_HEXAGON_S5_popcountp
+
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vasrh(Rss32,#u4):rnd
+ C Intrinsic Prototype: Word64 Q6_P_vasrh_PI_rnd(Word64 Rss, Word32 Iu4)
+ Instruction Type: S_2op
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_P_vasrh_PI_rnd __builtin_HEXAGON_S5_vasrhrnd_goodsyntax
+
+/* ==========================================================================
+ Assembly Syntax: dccleana(Rs32)
+ C Intrinsic Prototype: void Q6_dccleana_A(Address Rs)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_dccleana_A __builtin_HEXAGON_Y2_dccleana
+
+/* ==========================================================================
+ Assembly Syntax: dccleaninva(Rs32)
+ C Intrinsic Prototype: void Q6_dccleaninva_A(Address Rs)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_dccleaninva_A __builtin_HEXAGON_Y2_dccleaninva
+
+/* ==========================================================================
+ Assembly Syntax: dcfetch(Rs32)
+ C Intrinsic Prototype: void Q6_dcfetch_A(Address Rs)
+ Instruction Type: MAPPING
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_dcfetch_A __builtin_HEXAGON_Y2_dcfetch
+
+/* ==========================================================================
+ Assembly Syntax: dcinva(Rs32)
+ C Intrinsic Prototype: void Q6_dcinva_A(Address Rs)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_dcinva_A __builtin_HEXAGON_Y2_dcinva
+
+/* ==========================================================================
+ Assembly Syntax: dczeroa(Rs32)
+ C Intrinsic Prototype: void Q6_dczeroa_A(Address Rs)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_dczeroa_A __builtin_HEXAGON_Y2_dczeroa
+
+/* ==========================================================================
+ Assembly Syntax: l2fetch(Rs32,Rt32)
+ C Intrinsic Prototype: void Q6_l2fetch_AR(Address Rs, Word32 Rt)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_l2fetch_AR __builtin_HEXAGON_Y4_l2fetch
+
+/* ==========================================================================
+ Assembly Syntax: l2fetch(Rs32,Rtt32)
+ C Intrinsic Prototype: void Q6_l2fetch_AP(Address Rs, Word64 Rtt)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_l2fetch_AP __builtin_HEXAGON_Y5_l2fetch
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rdd32=rol(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_rol_PI(Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_rol_PI __builtin_HEXAGON_S6_rol_i_p
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=rol(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_rolacc_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_rolacc_PI __builtin_HEXAGON_S6_rol_i_p_acc
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rxx32&=rol(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_roland_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_roland_PI __builtin_HEXAGON_S6_rol_i_p_and
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rxx32-=rol(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_rolnac_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_rolnac_PI __builtin_HEXAGON_S6_rol_i_p_nac
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rxx32|=rol(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_rolor_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_rolor_PI __builtin_HEXAGON_S6_rol_i_p_or
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rxx32^=rol(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_rolxacc_PI(Word64 Rxx, Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_rolxacc_PI __builtin_HEXAGON_S6_rol_i_p_xacc
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rd32=rol(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_rol_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_rol_RI __builtin_HEXAGON_S6_rol_i_r
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rx32+=rol(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_rolacc_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_rolacc_RI __builtin_HEXAGON_S6_rol_i_r_acc
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rx32&=rol(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_roland_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_roland_RI __builtin_HEXAGON_S6_rol_i_r_and
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rx32-=rol(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_rolnac_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_rolnac_RI __builtin_HEXAGON_S6_rol_i_r_nac
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rx32|=rol(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_rolor_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_rolor_RI __builtin_HEXAGON_S6_rol_i_r_or
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rx32^=rol(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_rolxacc_RI(Word32 Rx, Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_rolxacc_RI __builtin_HEXAGON_S6_rol_i_r_xacc
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HEXAGON_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vabsdiffb(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vabsdiffb_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vabsdiffb_PP __builtin_HEXAGON_M6_vabsdiffb
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HEXAGON_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vabsdiffub(Rtt32,Rss32)
+ C Intrinsic Prototype: Word64 Q6_P_vabsdiffub_PP(Word64 Rtt, Word64 Rss)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vabsdiffub_PP __builtin_HEXAGON_M6_vabsdiffub
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HEXAGON_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vsplatb(Rs32)
+ C Intrinsic Prototype: Word64 Q6_P_vsplatb_R(Word32 Rs)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vsplatb_R __builtin_HEXAGON_S6_vsplatrbp
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HEXAGON_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vtrunehb(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vtrunehb_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vtrunehb_PP __builtin_HEXAGON_S6_vtrunehb_ppp
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HEXAGON_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vtrunohb(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vtrunohb_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vtrunohb_PP __builtin_HEXAGON_S6_vtrunohb_ppp
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HEXAGON_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32=vmem(Rt32):nt
+ C Intrinsic Prototype: HVX_Vector Q6_V_vmem_R_nt(Word32 Rt)
+ Instruction Type: MAPPING
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vmem_R_nt __builtin_HEXAGON_V6_ldntnt0
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HEXAGON_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Pd4=!any8(vcmpb.eq(Rss32,Rtt32))
+ C Intrinsic Prototype: Byte Q6_p_not_any8_vcmpb_eq_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: ALU64
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_p_not_any8_vcmpb_eq_PP __builtin_HEXAGON_A6_vcmpbeq_notany
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HEXAGON_ARCH__ >= 66
+/* ==========================================================================
+ Assembly Syntax: Rdd32=dfadd(Rss32,Rtt32)
+ C Intrinsic Prototype: Float64 Q6_P_dfadd_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfadd_PP __builtin_HEXAGON_F2_dfadd
+#endif /* __HEXAGON_ARCH___ >= 66 */
+
+#if __HEXAGON_ARCH__ >= 66
+/* ==========================================================================
+ Assembly Syntax: Rdd32=dfsub(Rss32,Rtt32)
+ C Intrinsic Prototype: Float64 Q6_P_dfsub_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfsub_PP __builtin_HEXAGON_F2_dfsub
+#endif /* __HEXAGON_ARCH___ >= 66 */
+
+#if __HEXAGON_ARCH__ >= 66
+/* ==========================================================================
+ Assembly Syntax: Rx32-=mpyi(Rs32,Rt32)
+ C Intrinsic Prototype: Word32 Q6_R_mpyinac_RR(Word32 Rx, Word32 Rs, Word32 Rt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mpyinac_RR __builtin_HEXAGON_M2_mnaci
+#endif /* __HEXAGON_ARCH___ >= 66 */
+
+#if __HEXAGON_ARCH__ >= 66
+/* ==========================================================================
+ Assembly Syntax: Rd32=mask(#u5,#U5)
+ C Intrinsic Prototype: Word32 Q6_R_mask_II(Word32 Iu5, Word32 IU5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_mask_II __builtin_HEXAGON_S2_mask
+#endif /* __HEXAGON_ARCH___ >= 66 */
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=clip(Rs32,#u5)
+ C Intrinsic Prototype: Word32 Q6_R_clip_RI(Word32 Rs, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_R_clip_RI __builtin_HEXAGON_A7_clip
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cround(Rss32,#u6)
+ C Intrinsic Prototype: Word64 Q6_P_cround_PI(Word64 Rss, Word32 Iu6)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cround_PI __builtin_HEXAGON_A7_croundd_ri
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cround(Rss32,Rt32)
+ C Intrinsic Prototype: Word64 Q6_P_cround_PR(Word64 Rss, Word32 Rt)
+ Instruction Type: S_3op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_cround_PR __builtin_HEXAGON_A7_croundd_rr
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vclip(Rss32,#u5)
+ C Intrinsic Prototype: Word64 Q6_P_vclip_PI(Word64 Rss, Word32 Iu5)
+ Instruction Type: S_2op
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_vclip_PI __builtin_HEXAGON_A7_vclip
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67
+/* ==========================================================================
+ Assembly Syntax: Rdd32=dfmax(Rss32,Rtt32)
+ C Intrinsic Prototype: Float64 Q6_P_dfmax_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfmax_PP __builtin_HEXAGON_F2_dfmax
+#endif /* __HEXAGON_ARCH___ >= 67 */
+
+#if __HEXAGON_ARCH__ >= 67
+/* ==========================================================================
+ Assembly Syntax: Rdd32=dfmin(Rss32,Rtt32)
+ C Intrinsic Prototype: Float64 Q6_P_dfmin_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfmin_PP __builtin_HEXAGON_F2_dfmin
+#endif /* __HEXAGON_ARCH___ >= 67 */
+
+#if __HEXAGON_ARCH__ >= 67
+/* ==========================================================================
+ Assembly Syntax: Rdd32=dfmpyfix(Rss32,Rtt32)
+ C Intrinsic Prototype: Float64 Q6_P_dfmpyfix_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfmpyfix_PP __builtin_HEXAGON_F2_dfmpyfix
+#endif /* __HEXAGON_ARCH___ >= 67 */
+
+#if __HEXAGON_ARCH__ >= 67
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=dfmpyhh(Rss32,Rtt32)
+ C Intrinsic Prototype: Float64 Q6_P_dfmpyhhacc_PP(Float64 Rxx, Float64 Rss, Float64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfmpyhhacc_PP __builtin_HEXAGON_F2_dfmpyhh
+#endif /* __HEXAGON_ARCH___ >= 67 */
+
+#if __HEXAGON_ARCH__ >= 67
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=dfmpylh(Rss32,Rtt32)
+ C Intrinsic Prototype: Float64 Q6_P_dfmpylhacc_PP(Float64 Rxx, Float64 Rss, Float64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfmpylhacc_PP __builtin_HEXAGON_F2_dfmpylh
+#endif /* __HEXAGON_ARCH___ >= 67 */
+
+#if __HEXAGON_ARCH__ >= 67
+/* ==========================================================================
+ Assembly Syntax: Rdd32=dfmpyll(Rss32,Rtt32)
+ C Intrinsic Prototype: Float64 Q6_P_dfmpyll_PP(Float64 Rss, Float64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_P_dfmpyll_PP __builtin_HEXAGON_F2_dfmpyll
+#endif /* __HEXAGON_ARCH___ >= 67 */
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpyiw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyiw_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_cmpyiw_PP __builtin_HEXAGON_M7_dcmpyiw
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpyiw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyiwacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_cmpyiwacc_PP __builtin_HEXAGON_M7_dcmpyiw_acc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpyiw(Rss32,Rtt32*)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyiw_PP_conj(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_cmpyiw_PP_conj __builtin_HEXAGON_M7_dcmpyiwc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpyiw(Rss32,Rtt32*)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyiwacc_PP_conj(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_cmpyiwacc_PP_conj __builtin_HEXAGON_M7_dcmpyiwc_acc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpyrw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyrw_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_cmpyrw_PP __builtin_HEXAGON_M7_dcmpyrw
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpyrw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyrwacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_cmpyrwacc_PP __builtin_HEXAGON_M7_dcmpyrw_acc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rdd32=cmpyrw(Rss32,Rtt32*)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyrw_PP_conj(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_cmpyrw_PP_conj __builtin_HEXAGON_M7_dcmpyrwc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=cmpyrw(Rss32,Rtt32*)
+ C Intrinsic Prototype: Word64 Q6_P_cmpyrwacc_PP_conj(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_cmpyrwacc_PP_conj __builtin_HEXAGON_M7_dcmpyrwc_acc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rdd32=vdmpyw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vdmpyw_PP(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_vdmpyw_PP __builtin_HEXAGON_M7_vdmpy
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rxx32+=vdmpyw(Rss32,Rtt32)
+ C Intrinsic Prototype: Word64 Q6_P_vdmpywacc_PP(Word64 Rxx, Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_P_vdmpywacc_PP __builtin_HEXAGON_M7_vdmpy_acc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyiw(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyiw_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_R_cmpyiw_PP_s1_sat __builtin_HEXAGON_M7_wcmpyiw
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyiw(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyiw_PP_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_R_cmpyiw_PP_s1_rnd_sat __builtin_HEXAGON_M7_wcmpyiw_rnd
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyiw(Rss32,Rtt32*):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyiw_PP_conj_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_R_cmpyiw_PP_conj_s1_sat __builtin_HEXAGON_M7_wcmpyiwc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyiw(Rss32,Rtt32*):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyiw_PP_conj_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_R_cmpyiw_PP_conj_s1_rnd_sat __builtin_HEXAGON_M7_wcmpyiwc_rnd
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyrw(Rss32,Rtt32):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyrw_PP_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_R_cmpyrw_PP_s1_sat __builtin_HEXAGON_M7_wcmpyrw
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyrw(Rss32,Rtt32):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyrw_PP_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_R_cmpyrw_PP_s1_rnd_sat __builtin_HEXAGON_M7_wcmpyrw_rnd
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyrw(Rss32,Rtt32*):<<1:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyrw_PP_conj_s1_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_R_cmpyrw_PP_conj_s1_sat __builtin_HEXAGON_M7_wcmpyrwc
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 67 && defined __HEXAGON_AUDIO__
+/* ==========================================================================
+ Assembly Syntax: Rd32=cmpyrw(Rss32,Rtt32*):<<1:rnd:sat
+ C Intrinsic Prototype: Word32 Q6_R_cmpyrw_PP_conj_s1_rnd_sat(Word64 Rss, Word64 Rtt)
+ Instruction Type: M
+ Execution Slots: SLOT3
+ ========================================================================== */
+
+#define Q6_R_cmpyrw_PP_conj_s1_rnd_sat __builtin_HEXAGON_M7_wcmpyrwc_rnd
+#endif /* __HEXAGON_ARCH___ >= 67 && defined __HEXAGON_AUDIO__*/
+
+#if __HEXAGON_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: dmlink(Rs32,Rt32)
+ C Intrinsic Prototype: void Q6_dmlink_AA(Address Rs, Address Rt)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_dmlink_AA __builtin_HEXAGON_Y6_dmlink
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#if __HEXAGON_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: Rd32=dmpause
+ C Intrinsic Prototype: Word32 Q6_R_dmpause()
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_R_dmpause __builtin_HEXAGON_Y6_dmpause
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#if __HEXAGON_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: Rd32=dmpoll
+ C Intrinsic Prototype: Word32 Q6_R_dmpoll()
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_R_dmpoll __builtin_HEXAGON_Y6_dmpoll
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#if __HEXAGON_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: dmresume(Rs32)
+ C Intrinsic Prototype: void Q6_dmresume_A(Address Rs)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_dmresume_A __builtin_HEXAGON_Y6_dmresume
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#if __HEXAGON_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: dmstart(Rs32)
+ C Intrinsic Prototype: void Q6_dmstart_A(Address Rs)
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_dmstart_A __builtin_HEXAGON_Y6_dmstart
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#if __HEXAGON_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: Rd32=dmwait
+ C Intrinsic Prototype: Word32 Q6_R_dmwait()
+ Instruction Type: ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_R_dmwait __builtin_HEXAGON_Y6_dmwait
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#include <hexagon_circ_brev_intrinsics.h>
+#ifdef __HVX__
+#include <hvx_hexagon_protos.h>
+#endif /* __HVX__ */
+#endif
diff --git a/src/llvm-project/clang/lib/Headers/hexagon_types.h b/src/llvm-project/clang/lib/Headers/hexagon_types.h
new file mode 100644
index 0000000..6958809
--- /dev/null
+++ b/src/llvm-project/clang/lib/Headers/hexagon_types.h
@@ -0,0 +1,2653 @@
+/******************************************************************************/
+/* (c) 2020 Qualcomm Innovation Center, Inc. All rights reserved. */
+/* */
+/******************************************************************************/
+#ifndef HEXAGON_TYPES_H
+#define HEXAGON_TYPES_H
+
+#include <hexagon_protos.h>
+
+/* Hexagon names */
+#define HEXAGON_Vect HEXAGON_Vect64
+#define HEXAGON_V_GET_D HEXAGON_V64_GET_D
+#define HEXAGON_V_GET_UD HEXAGON_V64_GET_UD
+#define HEXAGON_V_GET_W0 HEXAGON_V64_GET_W0
+#define HEXAGON_V_GET_W1 HEXAGON_V64_GET_W1
+#define HEXAGON_V_GET_UW0 HEXAGON_V64_GET_UW0
+#define HEXAGON_V_GET_UW1 HEXAGON_V64_GET_UW1
+#define HEXAGON_V_GET_H0 HEXAGON_V64_GET_H0
+#define HEXAGON_V_GET_H1 HEXAGON_V64_GET_H1
+#define HEXAGON_V_GET_H2 HEXAGON_V64_GET_H2
+#define HEXAGON_V_GET_H3 HEXAGON_V64_GET_H3
+#define HEXAGON_V_GET_UH0 HEXAGON_V64_GET_UH0
+#define HEXAGON_V_GET_UH1 HEXAGON_V64_GET_UH1
+#define HEXAGON_V_GET_UH2 HEXAGON_V64_GET_UH2
+#define HEXAGON_V_GET_UH3 HEXAGON_V64_GET_UH3
+#define HEXAGON_V_GET_B0 HEXAGON_V64_GET_B0
+#define HEXAGON_V_GET_B1 HEXAGON_V64_GET_B1
+#define HEXAGON_V_GET_B2 HEXAGON_V64_GET_B2
+#define HEXAGON_V_GET_B3 HEXAGON_V64_GET_B3
+#define HEXAGON_V_GET_B4 HEXAGON_V64_GET_B4
+#define HEXAGON_V_GET_B5 HEXAGON_V64_GET_B5
+#define HEXAGON_V_GET_B6 HEXAGON_V64_GET_B6
+#define HEXAGON_V_GET_B7 HEXAGON_V64_GET_B7
+#define HEXAGON_V_GET_UB0 HEXAGON_V64_GET_UB0
+#define HEXAGON_V_GET_UB1 HEXAGON_V64_GET_UB1
+#define HEXAGON_V_GET_UB2 HEXAGON_V64_GET_UB2
+#define HEXAGON_V_GET_UB3 HEXAGON_V64_GET_UB3
+#define HEXAGON_V_GET_UB4 HEXAGON_V64_GET_UB4
+#define HEXAGON_V_GET_UB5 HEXAGON_V64_GET_UB5
+#define HEXAGON_V_GET_UB6 HEXAGON_V64_GET_UB6
+#define HEXAGON_V_GET_UB7 HEXAGON_V64_GET_UB7
+#define HEXAGON_V_PUT_D HEXAGON_V64_PUT_D
+#define HEXAGON_V_PUT_W0 HEXAGON_V64_PUT_W0
+#define HEXAGON_V_PUT_W1 HEXAGON_V64_PUT_W1
+#define HEXAGON_V_PUT_H0 HEXAGON_V64_PUT_H0
+#define HEXAGON_V_PUT_H1 HEXAGON_V64_PUT_H1
+#define HEXAGON_V_PUT_H2 HEXAGON_V64_PUT_H2
+#define HEXAGON_V_PUT_H3 HEXAGON_V64_PUT_H3
+#define HEXAGON_V_PUT_B0 HEXAGON_V64_PUT_B0
+#define HEXAGON_V_PUT_B1 HEXAGON_V64_PUT_B1
+#define HEXAGON_V_PUT_B2 HEXAGON_V64_PUT_B2
+#define HEXAGON_V_PUT_B3 HEXAGON_V64_PUT_B3
+#define HEXAGON_V_PUT_B4 HEXAGON_V64_PUT_B4
+#define HEXAGON_V_PUT_B5 HEXAGON_V64_PUT_B5
+#define HEXAGON_V_PUT_B6 HEXAGON_V64_PUT_B6
+#define HEXAGON_V_PUT_B7 HEXAGON_V64_PUT_B7
+#define HEXAGON_V_CREATE_D HEXAGON_V64_CREATE_D
+#define HEXAGON_V_CREATE_W HEXAGON_V64_CREATE_W
+#define HEXAGON_V_CREATE_H HEXAGON_V64_CREATE_H
+#define HEXAGON_V_CREATE_B HEXAGON_V64_CREATE_B
+
+#ifdef __cplusplus
+#define HEXAGON_VectC HEXAGON_Vect64C
+#endif /* __cplusplus */
+
+/* 64 Bit Vectors */
+
+typedef long long __attribute__((__may_alias__)) HEXAGON_Vect64;
+
+/* Extract doubleword macros */
+
+#define HEXAGON_V64_GET_D(v) (v)
+#define HEXAGON_V64_GET_UD(v) ((unsigned long long)(v))
+
+/* Extract word macros */
+
+#define HEXAGON_V64_GET_W0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.w[0]; \
+ })
+#define HEXAGON_V64_GET_W1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.w[1]; \
+ })
+#define HEXAGON_V64_GET_UW0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned int uw[2]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.uw[0]; \
+ })
+#define HEXAGON_V64_GET_UW1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned int uw[2]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.uw[1]; \
+ })
+
+/* Extract half word macros */
+
+#define HEXAGON_V64_GET_H0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.h[0]; \
+ })
+#define HEXAGON_V64_GET_H1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.h[1]; \
+ })
+#define HEXAGON_V64_GET_H2(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.h[2]; \
+ })
+#define HEXAGON_V64_GET_H3(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.h[3]; \
+ })
+#define HEXAGON_V64_GET_UH0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned short uh[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.uh[0]; \
+ })
+#define HEXAGON_V64_GET_UH1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned short uh[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.uh[1]; \
+ })
+#define HEXAGON_V64_GET_UH2(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned short uh[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.uh[2]; \
+ })
+#define HEXAGON_V64_GET_UH3(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned short uh[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.uh[3]; \
+ })
+
+/* Extract byte macros */
+
+#define HEXAGON_V64_GET_B0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[0]; \
+ })
+#define HEXAGON_V64_GET_B1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[1]; \
+ })
+#define HEXAGON_V64_GET_B2(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[2]; \
+ })
+#define HEXAGON_V64_GET_B3(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[3]; \
+ })
+#define HEXAGON_V64_GET_B4(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[4]; \
+ })
+#define HEXAGON_V64_GET_B5(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[5]; \
+ })
+#define HEXAGON_V64_GET_B6(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[6]; \
+ })
+#define HEXAGON_V64_GET_B7(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[7]; \
+ })
+#define HEXAGON_V64_GET_UB0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.ub[0]; \
+ })
+#define HEXAGON_V64_GET_UB1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.ub[1]; \
+ })
+#define HEXAGON_V64_GET_UB2(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.ub[2]; \
+ })
+#define HEXAGON_V64_GET_UB3(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.ub[3]; \
+ })
+#define HEXAGON_V64_GET_UB4(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.ub[4]; \
+ })
+#define HEXAGON_V64_GET_UB5(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.ub[5]; \
+ })
+#define HEXAGON_V64_GET_UB6(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.ub[6]; \
+ })
+#define HEXAGON_V64_GET_UB7(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.ub[7]; \
+ })
+
+/* NOTE: All set macros return a HEXAGON_Vect64 type */
+
+/* Set doubleword macro */
+
+#define HEXAGON_V64_PUT_D(v, new) (new)
+
+/* Set word macros */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V64_PUT_W0(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.w[0] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_W1(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.w[1] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V64_PUT_W0(v, new) \
+ (((v) & 0xffffffff00000000LL) | ((HEXAGON_Vect64)((unsigned int)(new))))
+#define HEXAGON_V64_PUT_W1(v, new) \
+ (((v) & 0x00000000ffffffffLL) | (((HEXAGON_Vect64)(new)) << 32LL))
+
+#endif /* !__hexagon__ */
+
+/* Set half word macros */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V64_PUT_H0(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.h[0] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_H1(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.h[1] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_H2(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.h[2] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_H3(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.h[3] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V64_PUT_H0(v, new) \
+ (((v) & 0xffffffffffff0000LL) | ((HEXAGON_Vect64)((unsigned short)(new))))
+#define HEXAGON_V64_PUT_H1(v, new) \
+ (((v) & 0xffffffff0000ffffLL) | (((HEXAGON_Vect64)((unsigned short)(new))) << 16LL))
+#define HEXAGON_V64_PUT_H2(v, new) \
+ (((v) & 0xffff0000ffffffffLL) | (((HEXAGON_Vect64)((unsigned short)(new))) << 32LL))
+#define HEXAGON_V64_PUT_H3(v, new) \
+ (((v) & 0x0000ffffffffffffLL) | (((HEXAGON_Vect64)(new)) << 48LL))
+
+#endif /* !__hexagon__ */
+
+/* Set byte macros */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V64_PUT_B0(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[0] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_B1(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[1] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_B2(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[2] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_B3(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[3] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_B4(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[4] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_B5(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[5] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_B6(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[6] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+#define HEXAGON_V64_PUT_B7(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.d = (v); \
+ _HEXAGON_V64_internal_union.b[7] = (new); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V64_PUT_B0(v, new) \
+ (((v) & 0xffffffffffffff00LL) | ((HEXAGON_Vect64)((unsigned char)(new))))
+#define HEXAGON_V64_PUT_B1(v, new) \
+ (((v) & 0xffffffffffff00ffLL) | (((HEXAGON_Vect64)((unsigned char)(new))) << 8LL))
+#define HEXAGON_V64_PUT_B2(v, new) \
+ (((v) & 0xffffffffff00ffffLL) | (((HEXAGON_Vect64)((unsigned char)(new))) << 16LL))
+#define HEXAGON_V64_PUT_B3(v, new) \
+ (((v) & 0xffffffff00ffffffLL) | (((HEXAGON_Vect64)((unsigned char)(new))) << 24LL))
+#define HEXAGON_V64_PUT_B4(v, new) \
+ (((v) & 0xffffff00ffffffffLL) | (((HEXAGON_Vect64)((unsigned char)(new))) << 32LL))
+#define HEXAGON_V64_PUT_B5(v, new) \
+ (((v) & 0xffff00ffffffffffLL) | (((HEXAGON_Vect64)((unsigned char)(new))) << 40LL))
+#define HEXAGON_V64_PUT_B6(v, new) \
+ (((v) & 0xff00ffffffffffffLL) | (((HEXAGON_Vect64)((unsigned char)(new))) << 48LL))
+#define HEXAGON_V64_PUT_B7(v, new) \
+ (((v) & 0x00ffffffffffffffLL) | (((HEXAGON_Vect64)(new)) << 56LL))
+
+#endif /* !__hexagon__ */
+
+/* NOTE: All create macros return a HEXAGON_Vect64 type */
+
+/* Create from a doubleword */
+
+#define HEXAGON_V64_CREATE_D(d) (d)
+
+/* Create from words */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V64_CREATE_W(w1, w0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.w[0] = (w0); \
+ _HEXAGON_V64_internal_union.w[1] = (w1); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V64_CREATE_W(w1, w0) \
+ ((((HEXAGON_Vect64)(w1)) << 32LL) | ((HEXAGON_Vect64)((w0) & 0xffffffff)))
+
+#endif /* !__hexagon__ */
+
+/* Create from half words */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V64_CREATE_H(h3, h2, h1, h0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.h[0] = (h0); \
+ _HEXAGON_V64_internal_union.h[1] = (h1); \
+ _HEXAGON_V64_internal_union.h[2] = (h2); \
+ _HEXAGON_V64_internal_union.h[3] = (h3); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V64_CREATE_H(h3, h2, h1, h0) \
+ ((((HEXAGON_Vect64)(h3)) << 48LL) | (((HEXAGON_Vect64)((h2) & 0xffff)) << 32LL) | \
+ (((HEXAGON_Vect64)((h1) & 0xffff)) << 16LL) | ((HEXAGON_Vect64)((h0) & 0xffff)))
+
+#endif /* !__hexagon__ */
+
+/* Create from bytes */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V64_CREATE_B(b7, b6, b5, b4, b3, b2, b1, b0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _HEXAGON_V64_internal_union; \
+ _HEXAGON_V64_internal_union.b[0] = (b0); \
+ _HEXAGON_V64_internal_union.b[1] = (b1); \
+ _HEXAGON_V64_internal_union.b[2] = (b2); \
+ _HEXAGON_V64_internal_union.b[3] = (b3); \
+ _HEXAGON_V64_internal_union.b[4] = (b4); \
+ _HEXAGON_V64_internal_union.b[5] = (b5); \
+ _HEXAGON_V64_internal_union.b[6] = (b6); \
+ _HEXAGON_V64_internal_union.b[7] = (b7); \
+ _HEXAGON_V64_internal_union.d; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V64_CREATE_B(b7, b6, b5, b4, b3, b2, b1, b0) \
+ ((((HEXAGON_Vect64)(b7)) << 56LL) | (((HEXAGON_Vect64)((b6) & 0xff)) << 48LL) | \
+ (((HEXAGON_Vect64)((b5) & 0xff)) << 40LL) | (((HEXAGON_Vect64)((b4) & 0xff)) << 32LL) | \
+ (((HEXAGON_Vect64)((b3) & 0xff)) << 24LL) | (((HEXAGON_Vect64)((b2) & 0xff)) << 16LL) | \
+ (((HEXAGON_Vect64)((b1) & 0xff)) << 8LL) | ((HEXAGON_Vect64)((b0) & 0xff)))
+
+#endif /* !__hexagon__ */
+
+#ifdef __cplusplus
+
+class HEXAGON_Vect64C {
+public:
+ // Constructors
+ HEXAGON_Vect64C(long long d = 0) : data(d) {};
+ HEXAGON_Vect64C(int w1, int w0) : data(HEXAGON_V64_CREATE_W(w1, w0)) {};
+ HEXAGON_Vect64C(short h3, short h2, short h1, short h0)
+ : data(HEXAGON_V64_CREATE_H(h3, h2, h1, h0)) {};
+ HEXAGON_Vect64C(signed char b7, signed char b6, signed char b5, signed char b4,
+ signed char b3, signed char b2, signed char b1, signed char b0)
+ : data(HEXAGON_V64_CREATE_B(b7, b6, b5, b4, b3, b2, b1, b0)) {};
+ HEXAGON_Vect64C(const HEXAGON_Vect64C &v) : data(v.data) {};
+
+ HEXAGON_Vect64C &operator=(const HEXAGON_Vect64C &v) {
+ data = v.data;
+ return *this;
+ };
+
+ operator long long() {
+ return data;
+ };
+
+ // Extract doubleword methods
+ long long D(void) {
+ return HEXAGON_V64_GET_D(data);
+ };
+ unsigned long long UD(void) {
+ return HEXAGON_V64_GET_UD(data);
+ };
+
+ // Extract word methods
+ int W0(void) {
+ return HEXAGON_V64_GET_W0(data);
+ };
+ int W1(void) {
+ return HEXAGON_V64_GET_W1(data);
+ };
+ unsigned int UW0(void) {
+ return HEXAGON_V64_GET_UW0(data);
+ };
+ unsigned int UW1(void) {
+ return HEXAGON_V64_GET_UW1(data);
+ };
+
+ // Extract half word methods
+ short H0(void) {
+ return HEXAGON_V64_GET_H0(data);
+ };
+ short H1(void) {
+ return HEXAGON_V64_GET_H1(data);
+ };
+ short H2(void) {
+ return HEXAGON_V64_GET_H2(data);
+ };
+ short H3(void) {
+ return HEXAGON_V64_GET_H3(data);
+ };
+ unsigned short UH0(void) {
+ return HEXAGON_V64_GET_UH0(data);
+ };
+ unsigned short UH1(void) {
+ return HEXAGON_V64_GET_UH1(data);
+ };
+ unsigned short UH2(void) {
+ return HEXAGON_V64_GET_UH2(data);
+ };
+ unsigned short UH3(void) {
+ return HEXAGON_V64_GET_UH3(data);
+ };
+
+ // Extract byte methods
+ signed char B0(void) {
+ return HEXAGON_V64_GET_B0(data);
+ };
+ signed char B1(void) {
+ return HEXAGON_V64_GET_B1(data);
+ };
+ signed char B2(void) {
+ return HEXAGON_V64_GET_B2(data);
+ };
+ signed char B3(void) {
+ return HEXAGON_V64_GET_B3(data);
+ };
+ signed char B4(void) {
+ return HEXAGON_V64_GET_B4(data);
+ };
+ signed char B5(void) {
+ return HEXAGON_V64_GET_B5(data);
+ };
+ signed char B6(void) {
+ return HEXAGON_V64_GET_B6(data);
+ };
+ signed char B7(void) {
+ return HEXAGON_V64_GET_B7(data);
+ };
+ unsigned char UB0(void) {
+ return HEXAGON_V64_GET_UB0(data);
+ };
+ unsigned char UB1(void) {
+ return HEXAGON_V64_GET_UB1(data);
+ };
+ unsigned char UB2(void) {
+ return HEXAGON_V64_GET_UB2(data);
+ };
+ unsigned char UB3(void) {
+ return HEXAGON_V64_GET_UB3(data);
+ };
+ unsigned char UB4(void) {
+ return HEXAGON_V64_GET_UB4(data);
+ };
+ unsigned char UB5(void) {
+ return HEXAGON_V64_GET_UB5(data);
+ };
+ unsigned char UB6(void) {
+ return HEXAGON_V64_GET_UB6(data);
+ };
+ unsigned char UB7(void) {
+ return HEXAGON_V64_GET_UB7(data);
+ };
+
+ // NOTE: All set methods return a HEXAGON_Vect64C type
+
+ // Set doubleword method
+ HEXAGON_Vect64C D(long long d) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_D(data, d));
+ };
+
+ // Set word methods
+ HEXAGON_Vect64C W0(int w) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_W0(data, w));
+ };
+ HEXAGON_Vect64C W1(int w) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_W1(data, w));
+ };
+
+ // Set half word methods
+ HEXAGON_Vect64C H0(short h) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_H0(data, h));
+ };
+ HEXAGON_Vect64C H1(short h) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_H1(data, h));
+ };
+ HEXAGON_Vect64C H2(short h) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_H2(data, h));
+ };
+ HEXAGON_Vect64C H3(short h) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_H3(data, h));
+ };
+
+ // Set byte methods
+ HEXAGON_Vect64C B0(signed char b) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_B0(data, b));
+ };
+ HEXAGON_Vect64C B1(signed char b) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_B1(data, b));
+ };
+ HEXAGON_Vect64C B2(signed char b) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_B2(data, b));
+ };
+ HEXAGON_Vect64C B3(signed char b) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_B3(data, b));
+ };
+ HEXAGON_Vect64C B4(signed char b) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_B4(data, b));
+ };
+ HEXAGON_Vect64C B5(signed char b) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_B5(data, b));
+ };
+ HEXAGON_Vect64C B6(signed char b) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_B6(data, b));
+ };
+ HEXAGON_Vect64C B7(signed char b) {
+ return HEXAGON_Vect64C(HEXAGON_V64_PUT_B7(data, b));
+ };
+
+private:
+ long long data;
+};
+
+#endif /* __cplusplus */
+
+/* 32 Bit Vectors */
+
+typedef int HEXAGON_Vect32;
+
+/* Extract word macros */
+
+#define HEXAGON_V32_GET_W(v) (v)
+#define HEXAGON_V32_GET_UW(v) ((unsigned int)(v))
+
+/* Extract half word macros */
+
+#define HEXAGON_V32_GET_H0(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ short h[2]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.h[0]; \
+ })
+#define HEXAGON_V32_GET_H1(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ short h[2]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.h[1]; \
+ })
+#define HEXAGON_V32_GET_UH0(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned short uh[2]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.uh[0]; \
+ })
+#define HEXAGON_V32_GET_UH1(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned short uh[2]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.uh[1]; \
+ })
+
+/* Extract byte macros */
+
+#define HEXAGON_V32_GET_B0(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ signed char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.b[0]; \
+ })
+#define HEXAGON_V32_GET_B1(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ signed char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.b[1]; \
+ })
+#define HEXAGON_V32_GET_B2(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ signed char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.b[2]; \
+ })
+#define HEXAGON_V32_GET_B3(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ signed char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.b[3]; \
+ })
+#define HEXAGON_V32_GET_UB0(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned char ub[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.ub[0]; \
+ })
+#define HEXAGON_V32_GET_UB1(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned char ub[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.ub[1]; \
+ })
+#define HEXAGON_V32_GET_UB2(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned char ub[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.ub[2]; \
+ })
+#define HEXAGON_V32_GET_UB3(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned char ub[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.ub[3]; \
+ })
+
+/* NOTE: All set macros return a HEXAGON_Vect32 type */
+
+/* Set word macro */
+
+#define HEXAGON_V32_PUT_W(v, new) (new)
+
+/* Set half word macros */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V32_PUT_H0(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ short h[2]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.h[0] = (new); \
+ _HEXAGON_V32_internal_union.w; \
+ })
+#define HEXAGON_V32_PUT_H1(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ short h[2]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.h[1] = (new); \
+ _HEXAGON_V32_internal_union.w; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V32_PUT_H0(v, new) \
+ (((v) & 0xffff0000) | ((HEXAGON_Vect32)((unsigned short)(new))))
+#define HEXAGON_V32_PUT_H1(v, new) (((v) & 0x0000ffff) | (((HEXAGON_Vect32)(new)) << 16))
+
+#endif /* !__hexagon__ */
+
+/* Set byte macros */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V32_PUT_B0(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.b[0] = (new); \
+ _HEXAGON_V32_internal_union.w; \
+ })
+#define HEXAGON_V32_PUT_B1(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.b[1] = (new); \
+ _HEXAGON_V32_internal_union.w; \
+ })
+#define HEXAGON_V32_PUT_B2(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.b[2] = (new); \
+ _HEXAGON_V32_internal_union.w; \
+ })
+#define HEXAGON_V32_PUT_B3(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.w = (v); \
+ _HEXAGON_V32_internal_union.b[3] = (new); \
+ _HEXAGON_V32_internal_union.w; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V32_PUT_B0(v, new) \
+ (((v) & 0xffffff00) | ((HEXAGON_Vect32)((unsigned char)(new))))
+#define HEXAGON_V32_PUT_B1(v, new) \
+ (((v) & 0xffff00ff) | (((HEXAGON_Vect32)((unsigned char)(new))) << 8))
+#define HEXAGON_V32_PUT_B2(v, new) \
+ (((v) & 0xff00ffff) | (((HEXAGON_Vect32)((unsigned char)(new))) << 16))
+#define HEXAGON_V32_PUT_B3(v, new) (((v) & 0x00ffffff) | (((HEXAGON_Vect32)(new)) << 24))
+
+#endif /* !__hexagon__ */
+
+/* NOTE: All create macros return a HEXAGON_Vect32 type */
+
+/* Create from a word */
+
+#define HEXAGON_V32_CREATE_W(w) (w)
+
+/* Create from half words */
+
+#ifdef __hexagon__
+
+#define HEXAGON_V32_CREATE_H(h1, h0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[2]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.h[0] = (h0); \
+ _HEXAGON_V32_internal_union.h[1] = (h1); \
+ _HEXAGON_V32_internal_union.d; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V32_CREATE_H(h1, h0) \
+ ((((HEXAGON_Vect32)(h1)) << 16) | ((HEXAGON_Vect32)((h0) & 0xffff)))
+
+#endif /* !__hexagon__ */
+
+/* Create from bytes */
+#ifdef __hexagon__
+
+#define HEXAGON_V32_CREATE_B(b3, b2, b1, b0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[4]; \
+ } _HEXAGON_V32_internal_union; \
+ _HEXAGON_V32_internal_union.b[0] = (b0); \
+ _HEXAGON_V32_internal_union.b[1] = (b1); \
+ _HEXAGON_V32_internal_union.b[2] = (b2); \
+ _HEXAGON_V32_internal_union.b[3] = (b3); \
+ _HEXAGON_V32_internal_union.d; \
+ })
+
+#else /* !__hexagon__ */
+
+#define HEXAGON_V32_CREATE_B(b3, b2, b1, b0) \
+ ((((HEXAGON_Vect32)(b3)) << 24) | (((HEXAGON_Vect32)((b2) & 0xff)) << 16) | \
+ (((HEXAGON_Vect32)((b1) & 0xff)) << 8) | ((HEXAGON_Vect32)((b0) & 0xff)))
+
+#endif /* !__hexagon__ */
+
+#ifdef __cplusplus
+
+class HEXAGON_Vect32C {
+public:
+ // Constructors
+ HEXAGON_Vect32C(int w = 0) : data(w) {};
+ HEXAGON_Vect32C(short h1, short h0) : data(HEXAGON_V32_CREATE_H(h1, h0)) {};
+ HEXAGON_Vect32C(signed char b3, signed char b2, signed char b1, signed char b0)
+ : data(HEXAGON_V32_CREATE_B(b3, b2, b1, b0)) {};
+ HEXAGON_Vect32C(const HEXAGON_Vect32C &v) : data(v.data) {};
+
+ HEXAGON_Vect32C &operator=(const HEXAGON_Vect32C &v) {
+ data = v.data;
+ return *this;
+ };
+
+ operator int() {
+ return data;
+ };
+
+ // Extract word methods
+ int W(void) {
+ return HEXAGON_V32_GET_W(data);
+ };
+ unsigned int UW(void) {
+ return HEXAGON_V32_GET_UW(data);
+ };
+
+ // Extract half word methods
+ short H0(void) {
+ return HEXAGON_V32_GET_H0(data);
+ };
+ short H1(void) {
+ return HEXAGON_V32_GET_H1(data);
+ };
+ unsigned short UH0(void) {
+ return HEXAGON_V32_GET_UH0(data);
+ };
+ unsigned short UH1(void) {
+ return HEXAGON_V32_GET_UH1(data);
+ };
+
+ // Extract byte methods
+ signed char B0(void) {
+ return HEXAGON_V32_GET_B0(data);
+ };
+ signed char B1(void) {
+ return HEXAGON_V32_GET_B1(data);
+ };
+ signed char B2(void) {
+ return HEXAGON_V32_GET_B2(data);
+ };
+ signed char B3(void) {
+ return HEXAGON_V32_GET_B3(data);
+ };
+ unsigned char UB0(void) {
+ return HEXAGON_V32_GET_UB0(data);
+ };
+ unsigned char UB1(void) {
+ return HEXAGON_V32_GET_UB1(data);
+ };
+ unsigned char UB2(void) {
+ return HEXAGON_V32_GET_UB2(data);
+ };
+ unsigned char UB3(void) {
+ return HEXAGON_V32_GET_UB3(data);
+ };
+
+ // NOTE: All set methods return a HEXAGON_Vect32C type
+
+ // Set word method
+ HEXAGON_Vect32C W(int w) {
+ return HEXAGON_Vect32C(HEXAGON_V32_PUT_W(data, w));
+ };
+
+ // Set half word methods
+ HEXAGON_Vect32C H0(short h) {
+ return HEXAGON_Vect32C(HEXAGON_V32_PUT_H0(data, h));
+ };
+ HEXAGON_Vect32C H1(short h) {
+ return HEXAGON_Vect32C(HEXAGON_V32_PUT_H1(data, h));
+ };
+
+ // Set byte methods
+ HEXAGON_Vect32C B0(signed char b) {
+ return HEXAGON_Vect32C(HEXAGON_V32_PUT_B0(data, b));
+ };
+ HEXAGON_Vect32C B1(signed char b) {
+ return HEXAGON_Vect32C(HEXAGON_V32_PUT_B1(data, b));
+ };
+ HEXAGON_Vect32C B2(signed char b) {
+ return HEXAGON_Vect32C(HEXAGON_V32_PUT_B2(data, b));
+ };
+ HEXAGON_Vect32C B3(signed char b) {
+ return HEXAGON_Vect32C(HEXAGON_V32_PUT_B3(data, b));
+ };
+
+private:
+ int data;
+};
+
+#endif /* __cplusplus */
+
+// V65 Silver types
+#if __Q6S_ARCH__ >= 65
+ // Silver vector types are 128 bytes, and pairs are 256. The vector predicate
+ // types are 16 bytes and 32 bytes for pairs.
+ typedef long HEXAGON_VecPred128 __attribute__((__vector_size__(16)))
+ __attribute__((aligned(128)));
+
+ typedef long HEXAGON_VecPred256 __attribute__((__vector_size__(32)))
+ __attribute__((aligned(128)));
+
+ typedef long HEXAGON_Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+
+ typedef long HEXAGON_Vect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(256)));
+
+ typedef long HEXAGON_UVect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(4)));
+
+ typedef long HEXAGON_UVect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(4)));
+
+ #define Q6S_VectorPredPair HEXAGON_VecPred256
+ #define Q6S_VectorPred HEXAGON_VecPred128
+ #define Q6S_Vector HEXAGON_Vect1024
+ #define Q6S_VectorPair HEXAGON_Vect2048
+ #define Q6S_UVector HEXAGON_UVect1024
+ #define Q6S_UVectorPair HEXAGON_UVect2048
+
+#else /* __Q6S_ARCH__ >= 65 */
+
+// V65 Vector types
+#if __HVX_ARCH__ >= 65
+#if defined __HVX__ && (__HVX_LENGTH__ == 128)
+ typedef long HEXAGON_VecPred128 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+
+ typedef long HEXAGON_Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+
+ typedef long HEXAGON_Vect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(256)));
+
+ typedef long HEXAGON_UVect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(4)));
+
+ typedef long HEXAGON_UVect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(4)));
+
+ #define HVX_VectorPred HEXAGON_VecPred128
+ #define HVX_Vector HEXAGON_Vect1024
+ #define HVX_VectorPair HEXAGON_Vect2048
+ #define HVX_UVector HEXAGON_UVect1024
+ #define HVX_UVectorPair HEXAGON_UVect2048
+#else /* defined __HVX__ && (__HVX_LENGTH__ == 128) */
+#if defined __HVX__ && (__HVX_LENGTH__ == 64)
+ typedef long HEXAGON_VecPred64 __attribute__((__vector_size__(64)))
+ __attribute__((aligned(64)));
+
+ typedef long HEXAGON_Vect512 __attribute__((__vector_size__(64)))
+ __attribute__((aligned(64)));
+
+ typedef long HEXAGON_Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+
+ typedef long HEXAGON_UVect512 __attribute__((__vector_size__(64)))
+ __attribute__((aligned(4)));
+
+ typedef long HEXAGON_UVect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(4)));
+
+ #define HVX_VectorPred HEXAGON_VecPred64
+ #define HVX_Vector HEXAGON_Vect512
+ #define HVX_VectorPair HEXAGON_Vect1024
+ #define HVX_UVector HEXAGON_UVect512
+ #define HVX_UVectorPair HEXAGON_UVect1024
+#endif /* defined __HVX__ && (__HVX_LENGTH__ == 64) */
+#endif /* defined __HVX__ && (__HVX_LENGTH__ == 128) */
+#endif /* __HVX_ARCH__ >= 65 */
+#endif /* __Q6S_ARCH__ >= 65 */
+
+/* Predicates */
+
+typedef int HEXAGON_Pred;
+
+/***
+ *** backward compatibility aliases
+ ***/
+
+/* Old names */
+#define Q6Vect Q6Vect64
+#define Q6V_GET_D Q6V64_GET_D
+#define Q6V_GET_UD Q6V64_GET_UD
+#define Q6V_GET_W0 Q6V64_GET_W0
+#define Q6V_GET_W1 Q6V64_GET_W1
+#define Q6V_GET_UW0 Q6V64_GET_UW0
+#define Q6V_GET_UW1 Q6V64_GET_UW1
+#define Q6V_GET_H0 Q6V64_GET_H0
+#define Q6V_GET_H1 Q6V64_GET_H1
+#define Q6V_GET_H2 Q6V64_GET_H2
+#define Q6V_GET_H3 Q6V64_GET_H3
+#define Q6V_GET_UH0 Q6V64_GET_UH0
+#define Q6V_GET_UH1 Q6V64_GET_UH1
+#define Q6V_GET_UH2 Q6V64_GET_UH2
+#define Q6V_GET_UH3 Q6V64_GET_UH3
+#define Q6V_GET_B0 Q6V64_GET_B0
+#define Q6V_GET_B1 Q6V64_GET_B1
+#define Q6V_GET_B2 Q6V64_GET_B2
+#define Q6V_GET_B3 Q6V64_GET_B3
+#define Q6V_GET_B4 Q6V64_GET_B4
+#define Q6V_GET_B5 Q6V64_GET_B5
+#define Q6V_GET_B6 Q6V64_GET_B6
+#define Q6V_GET_B7 Q6V64_GET_B7
+#define Q6V_GET_UB0 Q6V64_GET_UB0
+#define Q6V_GET_UB1 Q6V64_GET_UB1
+#define Q6V_GET_UB2 Q6V64_GET_UB2
+#define Q6V_GET_UB3 Q6V64_GET_UB3
+#define Q6V_GET_UB4 Q6V64_GET_UB4
+#define Q6V_GET_UB5 Q6V64_GET_UB5
+#define Q6V_GET_UB6 Q6V64_GET_UB6
+#define Q6V_GET_UB7 Q6V64_GET_UB7
+#define Q6V_PUT_D Q6V64_PUT_D
+#define Q6V_PUT_W0 Q6V64_PUT_W0
+#define Q6V_PUT_W1 Q6V64_PUT_W1
+#define Q6V_PUT_H0 Q6V64_PUT_H0
+#define Q6V_PUT_H1 Q6V64_PUT_H1
+#define Q6V_PUT_H2 Q6V64_PUT_H2
+#define Q6V_PUT_H3 Q6V64_PUT_H3
+#define Q6V_PUT_B0 Q6V64_PUT_B0
+#define Q6V_PUT_B1 Q6V64_PUT_B1
+#define Q6V_PUT_B2 Q6V64_PUT_B2
+#define Q6V_PUT_B3 Q6V64_PUT_B3
+#define Q6V_PUT_B4 Q6V64_PUT_B4
+#define Q6V_PUT_B5 Q6V64_PUT_B5
+#define Q6V_PUT_B6 Q6V64_PUT_B6
+#define Q6V_PUT_B7 Q6V64_PUT_B7
+#define Q6V_CREATE_D Q6V64_CREATE_D
+#define Q6V_CREATE_W Q6V64_CREATE_W
+#define Q6V_CREATE_H Q6V64_CREATE_H
+#define Q6V_CREATE_B Q6V64_CREATE_B
+
+#ifdef __cplusplus
+#define Q6VectC Q6Vect64C
+#endif /* __cplusplus */
+
+/* 64 Bit Vectors */
+
+typedef long long __attribute__((__may_alias__)) Q6Vect64;
+
+/* Extract doubleword macros */
+
+#define Q6V64_GET_D(v) (v)
+#define Q6V64_GET_UD(v) ((unsigned long long)(v))
+
+/* Extract word macros */
+
+#define Q6V64_GET_W0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.w[0]; \
+ })
+#define Q6V64_GET_W1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.w[1]; \
+ })
+#define Q6V64_GET_UW0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned int uw[2]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.uw[0]; \
+ })
+#define Q6V64_GET_UW1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned int uw[2]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.uw[1]; \
+ })
+
+/* Extract half word macros */
+
+#define Q6V64_GET_H0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.h[0]; \
+ })
+#define Q6V64_GET_H1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.h[1]; \
+ })
+#define Q6V64_GET_H2(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.h[2]; \
+ })
+#define Q6V64_GET_H3(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.h[3]; \
+ })
+#define Q6V64_GET_UH0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned short uh[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.uh[0]; \
+ })
+#define Q6V64_GET_UH1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned short uh[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.uh[1]; \
+ })
+#define Q6V64_GET_UH2(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned short uh[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.uh[2]; \
+ })
+#define Q6V64_GET_UH3(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned short uh[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.uh[3]; \
+ })
+
+/* Extract byte macros */
+
+#define Q6V64_GET_B0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[0]; \
+ })
+#define Q6V64_GET_B1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[1]; \
+ })
+#define Q6V64_GET_B2(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[2]; \
+ })
+#define Q6V64_GET_B3(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[3]; \
+ })
+#define Q6V64_GET_B4(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[4]; \
+ })
+#define Q6V64_GET_B5(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[5]; \
+ })
+#define Q6V64_GET_B6(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[6]; \
+ })
+#define Q6V64_GET_B7(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ signed char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[7]; \
+ })
+#define Q6V64_GET_UB0(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.ub[0]; \
+ })
+#define Q6V64_GET_UB1(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.ub[1]; \
+ })
+#define Q6V64_GET_UB2(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.ub[2]; \
+ })
+#define Q6V64_GET_UB3(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.ub[3]; \
+ })
+#define Q6V64_GET_UB4(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.ub[4]; \
+ })
+#define Q6V64_GET_UB5(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.ub[5]; \
+ })
+#define Q6V64_GET_UB6(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.ub[6]; \
+ })
+#define Q6V64_GET_UB7(v) \
+ __extension__({ \
+ union { \
+ long long d; \
+ unsigned char ub[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.ub[7]; \
+ })
+
+/* NOTE: All set macros return a Q6Vect64 type */
+
+/* Set doubleword macro */
+
+#define Q6V64_PUT_D(v, new) (new)
+
+/* Set word macros */
+
+#ifdef __qdsp6__
+
+#define Q6V64_PUT_W0(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.w[0] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_W1(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.w[1] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V64_PUT_W0(v, new) \
+ (((v) & 0xffffffff00000000LL) | ((Q6Vect64)((unsigned int)(new))))
+#define Q6V64_PUT_W1(v, new) \
+ (((v) & 0x00000000ffffffffLL) | (((Q6Vect64)(new)) << 32LL))
+
+#endif /* !__qdsp6__ */
+
+/* Set half word macros */
+
+#ifdef __qdsp6__
+
+#define Q6V64_PUT_H0(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.h[0] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_H1(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.h[1] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_H2(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.h[2] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_H3(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.h[3] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V64_PUT_H0(v, new) \
+ (((v) & 0xffffffffffff0000LL) | ((Q6Vect64)((unsigned short)(new))))
+#define Q6V64_PUT_H1(v, new) \
+ (((v) & 0xffffffff0000ffffLL) | (((Q6Vect64)((unsigned short)(new))) << 16LL))
+#define Q6V64_PUT_H2(v, new) \
+ (((v) & 0xffff0000ffffffffLL) | (((Q6Vect64)((unsigned short)(new))) << 32LL))
+#define Q6V64_PUT_H3(v, new) \
+ (((v) & 0x0000ffffffffffffLL) | (((Q6Vect64)(new)) << 48LL))
+
+#endif /* !__qdsp6__ */
+
+/* Set byte macros */
+
+#ifdef __qdsp6__
+
+#define Q6V64_PUT_B0(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[0] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_B1(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[1] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_B2(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[2] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_B3(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[3] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_B4(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[4] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_B5(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[5] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_B6(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[6] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+#define Q6V64_PUT_B7(v, new) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.d = (v); \
+ _Q6V64_internal_union.b[7] = (new); \
+ _Q6V64_internal_union.d; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V64_PUT_B0(v, new) \
+ (((v) & 0xffffffffffffff00LL) | ((Q6Vect64)((unsigned char)(new))))
+#define Q6V64_PUT_B1(v, new) \
+ (((v) & 0xffffffffffff00ffLL) | (((Q6Vect64)((unsigned char)(new))) << 8LL))
+#define Q6V64_PUT_B2(v, new) \
+ (((v) & 0xffffffffff00ffffLL) | (((Q6Vect64)((unsigned char)(new))) << 16LL))
+#define Q6V64_PUT_B3(v, new) \
+ (((v) & 0xffffffff00ffffffLL) | (((Q6Vect64)((unsigned char)(new))) << 24LL))
+#define Q6V64_PUT_B4(v, new) \
+ (((v) & 0xffffff00ffffffffLL) | (((Q6Vect64)((unsigned char)(new))) << 32LL))
+#define Q6V64_PUT_B5(v, new) \
+ (((v) & 0xffff00ffffffffffLL) | (((Q6Vect64)((unsigned char)(new))) << 40LL))
+#define Q6V64_PUT_B6(v, new) \
+ (((v) & 0xff00ffffffffffffLL) | (((Q6Vect64)((unsigned char)(new))) << 48LL))
+#define Q6V64_PUT_B7(v, new) \
+ (((v) & 0x00ffffffffffffffLL) | (((Q6Vect64)(new)) << 56LL))
+
+#endif /* !__qdsp6__ */
+
+/* NOTE: All create macros return a Q6Vect64 type */
+
+/* Create from a doubleword */
+
+#define Q6V64_CREATE_D(d) (d)
+
+/* Create from words */
+
+#ifdef __qdsp6__
+
+#define Q6V64_CREATE_W(w1, w0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ int w[2]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.w[0] = (w0); \
+ _Q6V64_internal_union.w[1] = (w1); \
+ _Q6V64_internal_union.d; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V64_CREATE_W(w1, w0) \
+ ((((Q6Vect64)(w1)) << 32LL) | ((Q6Vect64)((w0) & 0xffffffff)))
+
+#endif /* !__qdsp6__ */
+
+/* Create from half words */
+
+#ifdef __qdsp6__
+
+#define Q6V64_CREATE_H(h3, h2, h1, h0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[4]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.h[0] = (h0); \
+ _Q6V64_internal_union.h[1] = (h1); \
+ _Q6V64_internal_union.h[2] = (h2); \
+ _Q6V64_internal_union.h[3] = (h3); \
+ _Q6V64_internal_union.d; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V64_CREATE_H(h3, h2, h1, h0) \
+ ((((Q6Vect64)(h3)) << 48LL) | (((Q6Vect64)((h2) & 0xffff)) << 32LL) | \
+ (((Q6Vect64)((h1) & 0xffff)) << 16LL) | ((Q6Vect64)((h0) & 0xffff)))
+
+#endif /* !__qdsp6__ */
+
+/* Create from bytes */
+
+#ifdef __qdsp6__
+
+#define Q6V64_CREATE_B(b7, b6, b5, b4, b3, b2, b1, b0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[8]; \
+ } _Q6V64_internal_union; \
+ _Q6V64_internal_union.b[0] = (b0); \
+ _Q6V64_internal_union.b[1] = (b1); \
+ _Q6V64_internal_union.b[2] = (b2); \
+ _Q6V64_internal_union.b[3] = (b3); \
+ _Q6V64_internal_union.b[4] = (b4); \
+ _Q6V64_internal_union.b[5] = (b5); \
+ _Q6V64_internal_union.b[6] = (b6); \
+ _Q6V64_internal_union.b[7] = (b7); \
+ _Q6V64_internal_union.d; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V64_CREATE_B(b7, b6, b5, b4, b3, b2, b1, b0) \
+ ((((Q6Vect64)(b7)) << 56LL) | (((Q6Vect64)((b6) & 0xff)) << 48LL) | \
+ (((Q6Vect64)((b5) & 0xff)) << 40LL) | (((Q6Vect64)((b4) & 0xff)) << 32LL) | \
+ (((Q6Vect64)((b3) & 0xff)) << 24LL) | (((Q6Vect64)((b2) & 0xff)) << 16LL) | \
+ (((Q6Vect64)((b1) & 0xff)) << 8LL) | ((Q6Vect64)((b0) & 0xff)))
+
+#endif /* !__qdsp6__ */
+
+#ifdef __cplusplus
+
+class Q6Vect64C {
+public:
+ // Constructors
+ Q6Vect64C(long long d = 0) : data(d) {};
+ Q6Vect64C(int w1, int w0) : data(Q6V64_CREATE_W(w1, w0)) {};
+ Q6Vect64C(short h3, short h2, short h1, short h0)
+ : data(Q6V64_CREATE_H(h3, h2, h1, h0)) {};
+ Q6Vect64C(signed char b7, signed char b6, signed char b5, signed char b4,
+ signed char b3, signed char b2, signed char b1, signed char b0)
+ : data(Q6V64_CREATE_B(b7, b6, b5, b4, b3, b2, b1, b0)) {};
+ Q6Vect64C(const Q6Vect64C &v) : data(v.data) {};
+
+ Q6Vect64C &operator=(const Q6Vect64C &v) {
+ data = v.data;
+ return *this;
+ };
+
+ operator long long() {
+ return data;
+ };
+
+ // Extract doubleword methods
+ long long D(void) {
+ return Q6V64_GET_D(data);
+ };
+ unsigned long long UD(void) {
+ return Q6V64_GET_UD(data);
+ };
+
+ // Extract word methods
+ int W0(void) {
+ return Q6V64_GET_W0(data);
+ };
+ int W1(void) {
+ return Q6V64_GET_W1(data);
+ };
+ unsigned int UW0(void) {
+ return Q6V64_GET_UW0(data);
+ };
+ unsigned int UW1(void) {
+ return Q6V64_GET_UW1(data);
+ };
+
+ // Extract half word methods
+ short H0(void) {
+ return Q6V64_GET_H0(data);
+ };
+ short H1(void) {
+ return Q6V64_GET_H1(data);
+ };
+ short H2(void) {
+ return Q6V64_GET_H2(data);
+ };
+ short H3(void) {
+ return Q6V64_GET_H3(data);
+ };
+ unsigned short UH0(void) {
+ return Q6V64_GET_UH0(data);
+ };
+ unsigned short UH1(void) {
+ return Q6V64_GET_UH1(data);
+ };
+ unsigned short UH2(void) {
+ return Q6V64_GET_UH2(data);
+ };
+ unsigned short UH3(void) {
+ return Q6V64_GET_UH3(data);
+ };
+
+ // Extract byte methods
+ signed char B0(void) {
+ return Q6V64_GET_B0(data);
+ };
+ signed char B1(void) {
+ return Q6V64_GET_B1(data);
+ };
+ signed char B2(void) {
+ return Q6V64_GET_B2(data);
+ };
+ signed char B3(void) {
+ return Q6V64_GET_B3(data);
+ };
+ signed char B4(void) {
+ return Q6V64_GET_B4(data);
+ };
+ signed char B5(void) {
+ return Q6V64_GET_B5(data);
+ };
+ signed char B6(void) {
+ return Q6V64_GET_B6(data);
+ };
+ signed char B7(void) {
+ return Q6V64_GET_B7(data);
+ };
+ unsigned char UB0(void) {
+ return Q6V64_GET_UB0(data);
+ };
+ unsigned char UB1(void) {
+ return Q6V64_GET_UB1(data);
+ };
+ unsigned char UB2(void) {
+ return Q6V64_GET_UB2(data);
+ };
+ unsigned char UB3(void) {
+ return Q6V64_GET_UB3(data);
+ };
+ unsigned char UB4(void) {
+ return Q6V64_GET_UB4(data);
+ };
+ unsigned char UB5(void) {
+ return Q6V64_GET_UB5(data);
+ };
+ unsigned char UB6(void) {
+ return Q6V64_GET_UB6(data);
+ };
+ unsigned char UB7(void) {
+ return Q6V64_GET_UB7(data);
+ };
+
+ // NOTE: All set methods return a Q6Vect64C type
+
+ // Set doubleword method
+ Q6Vect64C D(long long d) {
+ return Q6Vect64C(Q6V64_PUT_D(data, d));
+ };
+
+ // Set word methods
+ Q6Vect64C W0(int w) {
+ return Q6Vect64C(Q6V64_PUT_W0(data, w));
+ };
+ Q6Vect64C W1(int w) {
+ return Q6Vect64C(Q6V64_PUT_W1(data, w));
+ };
+
+ // Set half word methods
+ Q6Vect64C H0(short h) {
+ return Q6Vect64C(Q6V64_PUT_H0(data, h));
+ };
+ Q6Vect64C H1(short h) {
+ return Q6Vect64C(Q6V64_PUT_H1(data, h));
+ };
+ Q6Vect64C H2(short h) {
+ return Q6Vect64C(Q6V64_PUT_H2(data, h));
+ };
+ Q6Vect64C H3(short h) {
+ return Q6Vect64C(Q6V64_PUT_H3(data, h));
+ };
+
+ // Set byte methods
+ Q6Vect64C B0(signed char b) {
+ return Q6Vect64C(Q6V64_PUT_B0(data, b));
+ };
+ Q6Vect64C B1(signed char b) {
+ return Q6Vect64C(Q6V64_PUT_B1(data, b));
+ };
+ Q6Vect64C B2(signed char b) {
+ return Q6Vect64C(Q6V64_PUT_B2(data, b));
+ };
+ Q6Vect64C B3(signed char b) {
+ return Q6Vect64C(Q6V64_PUT_B3(data, b));
+ };
+ Q6Vect64C B4(signed char b) {
+ return Q6Vect64C(Q6V64_PUT_B4(data, b));
+ };
+ Q6Vect64C B5(signed char b) {
+ return Q6Vect64C(Q6V64_PUT_B5(data, b));
+ };
+ Q6Vect64C B6(signed char b) {
+ return Q6Vect64C(Q6V64_PUT_B6(data, b));
+ };
+ Q6Vect64C B7(signed char b) {
+ return Q6Vect64C(Q6V64_PUT_B7(data, b));
+ };
+
+private:
+ long long data;
+};
+
+#endif /* __cplusplus */
+
+/* 32 Bit Vectors */
+
+typedef int Q6Vect32;
+
+/* Extract word macros */
+
+#define Q6V32_GET_W(v) (v)
+#define Q6V32_GET_UW(v) ((unsigned int)(v))
+
+/* Extract half word macros */
+
+#define Q6V32_GET_H0(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ short h[2]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.h[0]; \
+ })
+#define Q6V32_GET_H1(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ short h[2]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.h[1]; \
+ })
+#define Q6V32_GET_UH0(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned short uh[2]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.uh[0]; \
+ })
+#define Q6V32_GET_UH1(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned short uh[2]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.uh[1]; \
+ })
+
+/* Extract byte macros */
+
+#define Q6V32_GET_B0(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ signed char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.b[0]; \
+ })
+#define Q6V32_GET_B1(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ signed char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.b[1]; \
+ })
+#define Q6V32_GET_B2(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ signed char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.b[2]; \
+ })
+#define Q6V32_GET_B3(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ signed char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.b[3]; \
+ })
+#define Q6V32_GET_UB0(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned char ub[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.ub[0]; \
+ })
+#define Q6V32_GET_UB1(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned char ub[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.ub[1]; \
+ })
+#define Q6V32_GET_UB2(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned char ub[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.ub[2]; \
+ })
+#define Q6V32_GET_UB3(v) \
+ __extension__({ \
+ union { \
+ int w; \
+ unsigned char ub[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.ub[3]; \
+ })
+
+/* NOTE: All set macros return a Q6Vect32 type */
+
+/* Set word macro */
+
+#define Q6V32_PUT_W(v, new) (new)
+
+/* Set half word macros */
+
+#ifdef __qdsp6__
+
+#define Q6V32_PUT_H0(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ short h[2]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.h[0] = (new); \
+ _Q6V32_internal_union.w; \
+ })
+#define Q6V32_PUT_H1(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ short h[2]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.h[1] = (new); \
+ _Q6V32_internal_union.w; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V32_PUT_H0(v, new) \
+ (((v) & 0xffff0000) | ((Q6Vect32)((unsigned short)(new))))
+#define Q6V32_PUT_H1(v, new) (((v) & 0x0000ffff) | (((Q6Vect32)(new)) << 16))
+
+#endif /* !__qdsp6__ */
+
+/* Set byte macros */
+
+#ifdef __qdsp6__
+
+#define Q6V32_PUT_B0(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.b[0] = (new); \
+ _Q6V32_internal_union.w; \
+ })
+#define Q6V32_PUT_B1(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.b[1] = (new); \
+ _Q6V32_internal_union.w; \
+ })
+#define Q6V32_PUT_B2(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.b[2] = (new); \
+ _Q6V32_internal_union.w; \
+ })
+#define Q6V32_PUT_B3(v, new) \
+ __extension__({ \
+ union { \
+ int w; \
+ char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.w = (v); \
+ _Q6V32_internal_union.b[3] = (new); \
+ _Q6V32_internal_union.w; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V32_PUT_B0(v, new) \
+ (((v) & 0xffffff00) | ((Q6Vect32)((unsigned char)(new))))
+#define Q6V32_PUT_B1(v, new) \
+ (((v) & 0xffff00ff) | (((Q6Vect32)((unsigned char)(new))) << 8))
+#define Q6V32_PUT_B2(v, new) \
+ (((v) & 0xff00ffff) | (((Q6Vect32)((unsigned char)(new))) << 16))
+#define Q6V32_PUT_B3(v, new) (((v) & 0x00ffffff) | (((Q6Vect32)(new)) << 24))
+
+#endif /* !__qdsp6__ */
+
+/* NOTE: All create macros return a Q6Vect32 type */
+
+/* Create from a word */
+
+#define Q6V32_CREATE_W(w) (w)
+
+/* Create from half words */
+
+#ifdef __qdsp6__
+
+#define Q6V32_CREATE_H(h1, h0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ short h[2]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.h[0] = (h0); \
+ _Q6V32_internal_union.h[1] = (h1); \
+ _Q6V32_internal_union.d; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V32_CREATE_H(h1, h0) \
+ ((((Q6Vect32)(h1)) << 16) | ((Q6Vect32)((h0) & 0xffff)))
+
+#endif /* !__qdsp6__ */
+
+/* Create from bytes */
+#ifdef __qdsp6__
+
+#define Q6V32_CREATE_B(b3, b2, b1, b0) \
+ __extension__({ \
+ union { \
+ long long d; \
+ char b[4]; \
+ } _Q6V32_internal_union; \
+ _Q6V32_internal_union.b[0] = (b0); \
+ _Q6V32_internal_union.b[1] = (b1); \
+ _Q6V32_internal_union.b[2] = (b2); \
+ _Q6V32_internal_union.b[3] = (b3); \
+ _Q6V32_internal_union.d; \
+ })
+
+#else /* !__qdsp6__ */
+
+#define Q6V32_CREATE_B(b3, b2, b1, b0) \
+ ((((Q6Vect32)(b3)) << 24) | (((Q6Vect32)((b2) & 0xff)) << 16) | \
+ (((Q6Vect32)((b1) & 0xff)) << 8) | ((Q6Vect32)((b0) & 0xff)))
+
+#endif /* !__qdsp6__ */
+
+#ifdef __cplusplus
+
+class Q6Vect32C {
+public:
+ // Constructors
+ Q6Vect32C(int w = 0) : data(w) {};
+ Q6Vect32C(short h1, short h0) : data(Q6V32_CREATE_H(h1, h0)) {};
+ Q6Vect32C(signed char b3, signed char b2, signed char b1, signed char b0)
+ : data(Q6V32_CREATE_B(b3, b2, b1, b0)) {};
+ Q6Vect32C(const Q6Vect32C &v) : data(v.data) {};
+
+ Q6Vect32C &operator=(const Q6Vect32C &v) {
+ data = v.data;
+ return *this;
+ };
+
+ operator int() {
+ return data;
+ };
+
+ // Extract word methods
+ int W(void) {
+ return Q6V32_GET_W(data);
+ };
+ unsigned int UW(void) {
+ return Q6V32_GET_UW(data);
+ };
+
+ // Extract half word methods
+ short H0(void) {
+ return Q6V32_GET_H0(data);
+ };
+ short H1(void) {
+ return Q6V32_GET_H1(data);
+ };
+ unsigned short UH0(void) {
+ return Q6V32_GET_UH0(data);
+ };
+ unsigned short UH1(void) {
+ return Q6V32_GET_UH1(data);
+ };
+
+ // Extract byte methods
+ signed char B0(void) {
+ return Q6V32_GET_B0(data);
+ };
+ signed char B1(void) {
+ return Q6V32_GET_B1(data);
+ };
+ signed char B2(void) {
+ return Q6V32_GET_B2(data);
+ };
+ signed char B3(void) {
+ return Q6V32_GET_B3(data);
+ };
+ unsigned char UB0(void) {
+ return Q6V32_GET_UB0(data);
+ };
+ unsigned char UB1(void) {
+ return Q6V32_GET_UB1(data);
+ };
+ unsigned char UB2(void) {
+ return Q6V32_GET_UB2(data);
+ };
+ unsigned char UB3(void) {
+ return Q6V32_GET_UB3(data);
+ };
+
+ // NOTE: All set methods return a Q6Vect32C type
+
+ // Set word method
+ Q6Vect32C W(int w) {
+ return Q6Vect32C(Q6V32_PUT_W(data, w));
+ };
+
+ // Set half word methods
+ Q6Vect32C H0(short h) {
+ return Q6Vect32C(Q6V32_PUT_H0(data, h));
+ };
+ Q6Vect32C H1(short h) {
+ return Q6Vect32C(Q6V32_PUT_H1(data, h));
+ };
+
+ // Set byte methods
+ Q6Vect32C B0(signed char b) {
+ return Q6Vect32C(Q6V32_PUT_B0(data, b));
+ };
+ Q6Vect32C B1(signed char b) {
+ return Q6Vect32C(Q6V32_PUT_B1(data, b));
+ };
+ Q6Vect32C B2(signed char b) {
+ return Q6Vect32C(Q6V32_PUT_B2(data, b));
+ };
+ Q6Vect32C B3(signed char b) {
+ return Q6Vect32C(Q6V32_PUT_B3(data, b));
+ };
+
+private:
+ int data;
+};
+
+#endif /* __cplusplus */
+
+// V65 Vector types
+#if __HVX_ARCH__ >= 65
+#if defined __HVX__ && (__HVX_LENGTH__ == 128)
+typedef long Q6VecPred128 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+
+typedef long Q6Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+
+typedef long Q6Vect2048 __attribute__((__vector_size__(256)))
+ __attribute__((aligned(256)));
+
+#else /* defined __HVX__ && (__HVX_LENGTH__ == 128) */
+#if defined __HVX__ && (__HVX_LENGTH__ == 64)
+typedef long Q6VecPred64 __attribute__((__vector_size__(64)))
+ __attribute__((aligned(64)));
+
+typedef long Q6Vect512 __attribute__((__vector_size__(64)))
+ __attribute__((aligned(64)));
+
+typedef long Q6Vect1024 __attribute__((__vector_size__(128)))
+ __attribute__((aligned(128)));
+
+#endif /* defined __HVX__ && (__HVX_LENGTH__ == 64) */
+#endif /* defined __HVX__ && (__HVX_LENGTH__ == 128) */
+#endif /* __HVX_ARCH__ >= 65 */
+
+/* Predicates */
+
+typedef int Q6Pred;
+
+
+#ifdef __HVX__
+
+// Extract HVX VectorPair macro.
+#define HEXAGON_HVX_GET_W(v) (v)
+
+// Extract HVX Vector macros.
+#define HEXAGON_HVX_GET_V0(v) \
+ __extension__({ \
+ union { \
+ HVX_VectorPair W; \
+ HVX_Vector V[2]; \
+ } _HEXAGON_HVX_internal_union; \
+ _HEXAGON_HVX_internal_union.W = (v); \
+ _HEXAGON_HVX_internal_union.V[0]; \
+ })
+#define HEXAGON_HVX_GET_V1(v) \
+ __extension__({ \
+ union { \
+ HVX_VectorPair W; \
+ HVX_Vector V[2]; \
+ } _HEXAGON_HVX_internal_union; \
+ _HEXAGON_HVX_internal_union.W = (v); \
+ _HEXAGON_HVX_internal_union.V[1]; \
+ })
+#define HEXAGON_HVX_GET_P(v) \
+ __extension__({ \
+ union { \
+ HVX_VectorPair W; \
+ HVX_VectorPred P[2]; \
+ } _HEXAGON_HVX_internal_union; \
+ _HEXAGON_HVX_internal_union.W = (v); \
+ _HEXAGON_HVX_internal_union.P[0]; \
+ })
+
+// Set HVX VectorPair macro.
+#define HEXAGON_HVX_PUT_W(v, new) (new)
+
+// Set HVX Vector macros.
+#define HEXAGON_HVX_PUT_V0(v, new) \
+ __extension__({ \
+ union { \
+ HVX_VectorPair W; \
+ HVX_Vector V[2]; \
+ } _HEXAGON_HVX_internal_union; \
+ _HEXAGON_HVX_internal_union.W = (v); \
+ _HEXAGON_HVX_internal_union.V[0] = (new); \
+ _HEXAGON_HVX_internal_union.W; \
+ })
+
+#define HEXAGON_HVX_PUT_V1(v, new) \
+ __extension__({ \
+ union { \
+ HVX_VectorPair W; \
+ HVX_Vector V[2]; \
+ } _HEXAGON_HVX_internal_union; \
+ _HEXAGON_HVX_internal_union.W = (v); \
+ _HEXAGON_HVX_internal_union.V[1] = (new); \
+ _HEXAGON_HVX_internal_union.W; \
+ })
+
+#define HEXAGON_HVX_PUT_P(v, new) \
+ __extension__({ \
+ union { \
+ HVX_VectorPair W; \
+ HVX_VectorPred P[2]; \
+ } _HEXAGON_HVX_internal_union; \
+ _HEXAGON_HVX_internal_union.W = (v); \
+ _HEXAGON_HVX_internal_union.P[0] = (new); \
+ _HEXAGON_HVX_internal_union.W; \
+ })
+
+
+#define HEXAGON_HVX_CREATE_W(v1, v0) \
+ __extension__({ \
+ union { \
+ HVX_VectorPair W; \
+ HVX_Vector V[2]; \
+ } _HEXAGON_HVX_internal_union; \
+ _HEXAGON_HVX_internal_union.V[0] = (v0); \
+ _HEXAGON_HVX_internal_union.V[1] = (v1); \
+ _HEXAGON_HVX_internal_union.W; \
+ })
+
+#ifdef __cplusplus
+
+class HVX_Vect {
+public:
+ // Constructors.
+ // Default.
+ HVX_Vect() : data(Q6_W_vcombine_VV(Q6_V_vzero(), Q6_V_vzero())){};
+
+ // Custom constructors.
+ HVX_Vect(HVX_VectorPair W) : data(W){};
+ HVX_Vect(HVX_Vector v1, HVX_Vector v0) : data(HEXAGON_HVX_CREATE_W(v1, v0)){};
+
+ // Copy constructor.
+ HVX_Vect(const HVX_Vect &W) = default;
+
+ // Move constructor.
+ HVX_Vect(HVX_Vect &&W) = default;
+
+ // Assignment operator.
+ HVX_Vect &operator=(const HVX_Vect &W) = default;
+
+ operator HVX_VectorPair() { return data; };
+
+ // Extract VectorPair method.
+ HVX_VectorPair W(void) { return HEXAGON_HVX_GET_W(data); };
+
+ // Extract Vector methods.
+ HVX_Vector V0(void) { return HEXAGON_HVX_GET_V0(data); };
+ HVX_Vector V1(void) { return HEXAGON_HVX_GET_V1(data); };
+ HVX_VectorPred P(void) { return HEXAGON_HVX_GET_P(data); };
+
+ // NOTE: All set methods return a HVX_Vect type.
+ // Set HVX VectorPair method.
+ HVX_Vect W(HVX_VectorPair w) { return HVX_Vect(HEXAGON_HVX_PUT_W(data, w)); };
+
+ // Set HVX Vector methods.
+ HVX_Vect V0(HVX_Vector v) { return HVX_Vect(HEXAGON_HVX_PUT_V0(data, v)); };
+ HVX_Vect V1(HVX_Vector v) { return HVX_Vect(HEXAGON_HVX_PUT_V1(data, v)); };
+ HVX_Vect P(HVX_VectorPred p) { return HVX_Vect(HEXAGON_HVX_PUT_P(data, p)); };
+
+private:
+ HVX_VectorPair data;
+};
+
+#endif /* __cplusplus */
+#endif /* __HVX__ */
+
+#define HEXAGON_UDMA_DM0_STATUS_IDLE 0x00000000
+#define HEXAGON_UDMA_DM0_STATUS_RUN 0x00000001
+#define HEXAGON_UDMA_DM0_STATUS_ERROR 0x00000002
+#define HEXAGON_UDMA_DESC_DSTATE_INCOMPLETE 0
+#define HEXAGON_UDMA_DESC_DSTATE_COMPLETE 1
+#define HEXAGON_UDMA_DESC_ORDER_NOORDER 0
+#define HEXAGON_UDMA_DESC_ORDER_ORDER 1
+#define HEXAGON_UDMA_DESC_BYPASS_OFF 0
+#define HEXAGON_UDMA_DESC_BYPASS_ON 1
+#define HEXAGON_UDMA_DESC_COMP_NONE 0
+#define HEXAGON_UDMA_DESC_COMP_DLBC 1
+#define HEXAGON_UDMA_DESC_DESCTYPE_TYPE0 0
+#define HEXAGON_UDMA_DESC_DESCTYPE_TYPE1 1
+
+typedef struct hexagon_udma_descriptor_type0_s
+{
+ void *next;
+ unsigned int length:24;
+ unsigned int desctype:2;
+ unsigned int dstcomp:1;
+ unsigned int srccomp:1;
+ unsigned int dstbypass:1;
+ unsigned int srcbypass:1;
+ unsigned int order:1;
+ unsigned int dstate:1;
+ void *src;
+ void *dst;
+} hexagon_udma_descriptor_type0_t;
+
+typedef struct hexagon_udma_descriptor_type1_s
+{
+ void *next;
+ unsigned int length:24;
+ unsigned int desctype:2;
+ unsigned int dstcomp:1;
+ unsigned int srccomp:1;
+ unsigned int dstbypass:1;
+ unsigned int srcbypass:1;
+ unsigned int order:1;
+ unsigned int dstate:1;
+ void *src;
+ void *dst;
+ unsigned int allocation:28;
+ unsigned int padding:4;
+ unsigned int roiwidth:16;
+ unsigned int roiheight:16;
+ unsigned int srcstride:16;
+ unsigned int dststride:16;
+ unsigned int srcwidthoffset:16;
+ unsigned int dstwidthoffset:16;
+} hexagon_udma_descriptor_type1_t;
+
+#endif /* !HEXAGON_TYPES_H */
diff --git a/src/llvm-project/clang/lib/Headers/hvx_hexagon_protos.h b/src/llvm-project/clang/lib/Headers/hvx_hexagon_protos.h
new file mode 100644
index 0000000..41ce7a6
--- /dev/null
+++ b/src/llvm-project/clang/lib/Headers/hvx_hexagon_protos.h
@@ -0,0 +1,4392 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Automatically generated file, do not edit!
+//===----------------------------------------------------------------------===//
+
+
+
+#ifndef _HVX_HEXAGON_PROTOS_H_
+#define _HVX_HEXAGON_PROTOS_H_ 1
+
+#ifdef __HVX__
+#if __HVX_LENGTH__ == 128
+#define __BUILTIN_VECTOR_WRAP(a) a ## _128B
+#else
+#define __BUILTIN_VECTOR_WRAP(a) a
+#endif
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Rd32=vextract(Vu32,Rs32)
+ C Intrinsic Prototype: Word32 Q6_R_vextract_VR(HVX_Vector Vu, Word32 Rs)
+ Instruction Type: LD
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_R_vextract_VR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_extractw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=hi(Vss32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_hi_W(HVX_VectorPair Vss)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_hi_W __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_hi)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=lo(Vss32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_lo_W(HVX_VectorPair Vss)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_lo_W __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_lo)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vsplat(Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vsplat_R(Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_V_vsplat_R __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_lvsplatw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=and(Qs4,Qt4)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_and_QQ(HVX_VectorPred Qs, HVX_VectorPred Qt)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_and_QQ __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_pred_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=and(Qs4,!Qt4)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_and_QQn(HVX_VectorPred Qs, HVX_VectorPred Qt)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_and_QQn __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_pred_and_n)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=not(Qs4)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_not_Q(HVX_VectorPred Qs)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_not_Q __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_pred_not)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=or(Qs4,Qt4)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_or_QQ(HVX_VectorPred Qs, HVX_VectorPred Qt)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_or_QQ __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_pred_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=or(Qs4,!Qt4)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_or_QQn(HVX_VectorPred Qs, HVX_VectorPred Qt)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_or_QQn __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_pred_or_n)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vsetq(Rt32)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vsetq_R(Word32 Rt)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vsetq_R __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_pred_scalar2)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=xor(Qs4,Qt4)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_xor_QQ(HVX_VectorPred Qs, HVX_VectorPred Qt)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_xor_QQ __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_pred_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (!Qv4) vmem(Rt32+#s4)=Vs32
+ C Intrinsic Prototype: void Q6_vmem_QnRIV(HVX_VectorPred Qv, HVX_Vector* Rt, HVX_Vector Vs)
+ Instruction Type: CVI_VM_ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vmem_QnRIV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vS32b_nqpred_ai)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (!Qv4) vmem(Rt32+#s4):nt=Vs32
+ C Intrinsic Prototype: void Q6_vmem_QnRIV_nt(HVX_VectorPred Qv, HVX_Vector* Rt, HVX_Vector Vs)
+ Instruction Type: CVI_VM_ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vmem_QnRIV_nt __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vS32b_nt_nqpred_ai)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (Qv4) vmem(Rt32+#s4):nt=Vs32
+ C Intrinsic Prototype: void Q6_vmem_QRIV_nt(HVX_VectorPred Qv, HVX_Vector* Rt, HVX_Vector Vs)
+ Instruction Type: CVI_VM_ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vmem_QRIV_nt __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vS32b_nt_qpred_ai)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (Qv4) vmem(Rt32+#s4)=Vs32
+ C Intrinsic Prototype: void Q6_vmem_QRIV(HVX_VectorPred Qv, HVX_Vector* Rt, HVX_Vector Vs)
+ Instruction Type: CVI_VM_ST
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vmem_QRIV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vS32b_qpred_ai)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vabsdiff(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vabsdiff_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuh_vabsdiff_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsdiffh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vabsdiff(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vabsdiff_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vub_vabsdiff_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsdiffub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vabsdiff(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vabsdiff_VuhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuh_vabsdiff_VuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsdiffuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vabsdiff(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vabsdiff_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuw_vabsdiff_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsdiffw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vabs(Vu32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vabs_Vh(HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vabs_Vh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vabs(Vu32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vabs_Vh_sat(HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vabs_Vh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsh_sat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vabs(Vu32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vabs_Vw(HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vabs_Vw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vabs(Vu32.w):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vabs_Vw_sat(HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vabs_Vw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsw_sat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vadd(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vadd_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vadd_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.b=vadd(Vuu32.b,Vvv32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wb_vadd_WbWb(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wb_vadd_WbWb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddb_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (!Qv4) Vx32.b+=Vu32.b
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_condacc_QnVbVb(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_condacc_QnVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddbnq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (Qv4) Vx32.b+=Vu32.b
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_condacc_QVbVb(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_condacc_QVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddbq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vadd(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vadd_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vadd_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vadd(Vuu32.h,Vvv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vadd_WhWh(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vadd_WhWh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddh_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (!Qv4) Vx32.h+=Vu32.h
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_condacc_QnVhVh(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_condacc_QnVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddhnq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (Qv4) Vx32.h+=Vu32.h
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_condacc_QVhVh(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_condacc_QVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddhq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vadd(Vu32.h,Vv32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vadd_VhVh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vadd_VhVh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddhsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vadd(Vuu32.h,Vvv32.h):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vadd_WhWh_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vadd_WhWh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddhsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vadd(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vadd_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vadd_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddhw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vadd(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vadd_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vadd_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddubh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vadd(Vu32.ub,Vv32.ub):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vadd_VubVub_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vadd_VubVub_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddubsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.ub=vadd(Vuu32.ub,Vvv32.ub):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wub_vadd_WubWub_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wub_vadd_WubWub_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddubsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vadd(Vu32.uh,Vv32.uh):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vadd_VuhVuh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vadd_VuhVuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vadduhsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uh=vadd(Vuu32.uh,Vvv32.uh):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuh_vadd_WuhWuh_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wuh_vadd_WuhWuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vadduhsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vadd(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vadd_VuhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vadd_VuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vadduhw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vadd(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vadd_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vadd_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vadd(Vuu32.w,Vvv32.w)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vadd_WwWw(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Ww_vadd_WwWw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddw_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (!Qv4) Vx32.w+=Vu32.w
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_condacc_QnVwVw(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_condacc_QnVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddwnq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (Qv4) Vx32.w+=Vu32.w
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_condacc_QVwVw(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_condacc_QVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddwq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vadd(Vu32.w,Vv32.w):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vadd_VwVw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vadd_VwVw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddwsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vadd(Vuu32.w,Vvv32.w):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vadd_WwWw_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Ww_vadd_WwWw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddwsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=valign(Vu32,Vv32,Rt8)
+ C Intrinsic Prototype: HVX_Vector Q6_V_valign_VVR(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_valign_VVR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_valignb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=valign(Vu32,Vv32,#u3)
+ C Intrinsic Prototype: HVX_Vector Q6_V_valign_VVI(HVX_Vector Vu, HVX_Vector Vv, Word32 Iu3)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_valign_VVI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_valignbi)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vand(Vu32,Vv32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vand_VV(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vand_VV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vand)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vand(Qu4,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vand_QR(HVX_VectorPred Qu, Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_V_vand_QR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vandqrt)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32|=vand(Qu4,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vandor_VQR(HVX_Vector Vx, HVX_VectorPred Qu, Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_V_vandor_VQR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vandqrt_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vand(Vu32,Rt32)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vand_VR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Q_vand_VR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vandvrt)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vand(Vu32,Rt32)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vandor_QVR(HVX_VectorPred Qx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Q_vandor_QVR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vandvrt_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vasl(Vu32.h,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vasl_VhR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vasl_VhR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaslh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vasl(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vasl_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vasl_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaslhv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vasl(Vu32.w,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vasl_VwR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vasl_VwR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaslw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vasl(Vu32.w,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vaslacc_VwVwR(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vaslacc_VwVwR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaslw_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vasl(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vasl_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vasl_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaslwv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vasr(Vu32.h,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vasr_VhR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vasr_VhR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vasr(Vu32.h,Vv32.h,Rt8):rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vasr_VhVhR_rnd_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vasr_VhVhR_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrhbrndsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vasr(Vu32.h,Vv32.h,Rt8):rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vasr_VhVhR_rnd_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vasr_VhVhR_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrhubrndsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vasr(Vu32.h,Vv32.h,Rt8):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vasr_VhVhR_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vasr_VhVhR_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrhubsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vasr(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vasr_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vasr_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrhv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vasr(Vu32.w,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vasr_VwR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vasr_VwR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vasr(Vu32.w,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vasracc_VwVwR(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vasracc_VwVwR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrw_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vasr(Vu32.w,Vv32.w,Rt8)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vasr_VwVwR(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vasr_VwVwR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrwh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vasr(Vu32.w,Vv32.w,Rt8):rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vasr_VwVwR_rnd_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vasr_VwVwR_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrwhrndsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vasr(Vu32.w,Vv32.w,Rt8):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vasr_VwVwR_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vasr_VwVwR_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrwhsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vasr(Vu32.w,Vv32.w,Rt8):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vasr_VwVwR_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vasr_VwVwR_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrwuhsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vasr(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vasr_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vasr_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrwv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=Vu32
+ C Intrinsic Prototype: HVX_Vector Q6_V_equals_V(HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_equals_V __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vassign)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32=Vuu32
+ C Intrinsic Prototype: HVX_VectorPair Q6_W_equals_W(HVX_VectorPair Vuu)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_W_equals_W __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vassignp)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vavg(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vavg_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vavg_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavgh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vavg(Vu32.h,Vv32.h):rnd
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vavg_VhVh_rnd(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vavg_VhVh_rnd __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavghrnd)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vavg(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vavg_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vavg_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavgub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vavg(Vu32.ub,Vv32.ub):rnd
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vavg_VubVub_rnd(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vavg_VubVub_rnd __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavgubrnd)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vavg(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vavg_VuhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vavg_VuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavguh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vavg(Vu32.uh,Vv32.uh):rnd
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vavg_VuhVuh_rnd(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vavg_VuhVuh_rnd __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavguhrnd)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vavg(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vavg_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vavg_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavgw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vavg(Vu32.w,Vv32.w):rnd
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vavg_VwVw_rnd(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vavg_VwVw_rnd __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavgwrnd)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vcl0(Vu32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vcl0_Vuh(HVX_Vector Vu)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vcl0_Vuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vcl0h)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vcl0(Vu32.uw)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vcl0_Vuw(HVX_Vector Vu)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuw_vcl0_Vuw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vcl0w)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32=vcombine(Vu32,Vv32)
+ C Intrinsic Prototype: HVX_VectorPair Q6_W_vcombine_VV(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_W_vcombine_VV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vcombine)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=#0
+ C Intrinsic Prototype: HVX_Vector Q6_V_vzero()
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vzero __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vd0)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vdeal(Vu32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vdeal_Vb(HVX_Vector Vu)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vdeal_Vb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdealb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vdeale(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vdeale_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vdeale_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdealb4w)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vdeal(Vu32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vdeal_Vh(HVX_Vector Vu)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vdeal_Vh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdealh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32=vdeal(Vu32,Vv32,Rt8)
+ C Intrinsic Prototype: HVX_VectorPair Q6_W_vdeal_VVR(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_W_vdeal_VVR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdealvdd)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vdelta(Vu32,Vv32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vdelta_VV(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vdelta_VV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdelta)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vdmpy(Vu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vdmpy_VubRb(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vdmpy_VubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpybus)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.h+=vdmpy(Vu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vdmpyacc_VhVubRb(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vdmpyacc_VhVubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpybus_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vdmpy(Vuu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vdmpy_WubRb(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vdmpy_WubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpybus_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vdmpy(Vuu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vdmpyacc_WhWubRb(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vdmpyacc_WhWubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpybus_dv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vdmpy(Vu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpy_VhRb(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpy_VhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vdmpy(Vu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpyacc_VwVhRb(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpyacc_VwVhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhb_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vdmpy(Vuu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vdmpy_WhRb(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vdmpy_WhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhb_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vdmpy(Vuu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vdmpyacc_WwWhRb(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vdmpyacc_WwWhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhb_dv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vdmpy(Vuu32.h,Rt32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpy_WhRh_sat(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpy_WhRh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhisat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vdmpy(Vuu32.h,Rt32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpyacc_VwWhRh_sat(HVX_Vector Vx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpyacc_VwWhRh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhisat_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vdmpy(Vu32.h,Rt32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpy_VhRh_sat(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpy_VhRh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vdmpy(Vu32.h,Rt32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpyacc_VwVhRh_sat(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpyacc_VwVhRh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhsat_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vdmpy(Vuu32.h,Rt32.uh,#1):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpy_WhRuh_sat(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpy_WhRuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhsuisat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vdmpy(Vuu32.h,Rt32.uh,#1):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpyacc_VwWhRuh_sat(HVX_Vector Vx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpyacc_VwWhRuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhsuisat_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vdmpy(Vu32.h,Rt32.uh):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpy_VhRuh_sat(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpy_VhRuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhsusat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vdmpy(Vu32.h,Rt32.uh):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpyacc_VwVhRuh_sat(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpyacc_VwVhRuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhsusat_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vdmpy(Vu32.h,Vv32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpy_VhVh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpy_VhVh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhvsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vdmpy(Vu32.h,Vv32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vdmpyacc_VwVhVh_sat(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vdmpyacc_VwVhVh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdmpyhvsat_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vdsad(Vuu32.uh,Rt32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vdsad_WuhRuh(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vdsad_WuhRuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdsaduh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.uw+=vdsad(Vuu32.uh,Rt32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vdsadacc_WuwWuhRuh(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vdsadacc_WuwWuhRuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdsaduh_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.eq(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eq_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eq_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.eq(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqand_QVbVb(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqand_QVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqb_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.eq(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqor_QVbVb(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqor_QVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqb_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.eq(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqxacc_QVbVb(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqxacc_QVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqb_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.eq(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eq_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eq_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.eq(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqand_QVhVh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqand_QVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqh_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.eq(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqor_QVhVh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqor_QVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqh_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.eq(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqxacc_QVhVh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqxacc_QVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqh_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.eq(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eq_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eq_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.eq(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqand_QVwVw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqand_QVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqw_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.eq(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqor_QVwVw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqor_QVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqw_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.eq(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_eqxacc_QVwVw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_eqxacc_QVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_veqw_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.gt(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gt_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gt_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.gt(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtand_QVbVb(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtand_QVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtb_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.gt(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtor_QVbVb(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtor_QVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtb_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.gt(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtxacc_QVbVb(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtxacc_QVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtb_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.gt(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gt_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gt_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgth)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.gt(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtand_QVhVh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtand_QVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgth_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.gt(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtor_QVhVh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtor_QVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgth_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.gt(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtxacc_QVhVh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtxacc_QVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgth_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.gt(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gt_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gt_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.gt(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtand_QVubVub(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtand_QVubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtub_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.gt(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtor_QVubVub(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtor_QVubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtub_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.gt(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtxacc_QVubVub(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtxacc_QVubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtub_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.gt(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gt_VuhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gt_VuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.gt(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtand_QVuhVuh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtand_QVuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtuh_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.gt(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtor_QVuhVuh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtor_QVuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtuh_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.gt(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtxacc_QVuhVuh(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtxacc_QVuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtuh_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.gt(Vu32.uw,Vv32.uw)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gt_VuwVuw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gt_VuwVuw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtuw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.gt(Vu32.uw,Vv32.uw)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtand_QVuwVuw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtand_QVuwVuw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtuw_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.gt(Vu32.uw,Vv32.uw)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtor_QVuwVuw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtor_QVuwVuw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtuw_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.gt(Vu32.uw,Vv32.uw)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtxacc_QVuwVuw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtxacc_QVuwVuw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtuw_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qd4=vcmp.gt(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gt_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gt_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4&=vcmp.gt(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtand_QVwVw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtand_QVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtw_and)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4|=vcmp.gt(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtor_QVwVw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtor_QVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtw_or)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Qx4^=vcmp.gt(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vcmp_gtxacc_QVwVw(HVX_VectorPred Qx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vcmp_gtxacc_QVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgtw_xor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w=vinsert(Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vinsert_VwR(HVX_Vector Vx, Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vinsert_VwR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vinsertwr)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vlalign(Vu32,Vv32,Rt8)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vlalign_VVR(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vlalign_VVR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlalignb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vlalign(Vu32,Vv32,#u3)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vlalign_VVI(HVX_Vector Vu, HVX_Vector Vv, Word32 Iu3)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vlalign_VVI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlalignbi)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vlsr(Vu32.uh,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vlsr_VuhR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vlsr_VuhR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlsrh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vlsr(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vlsr_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vlsr_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlsrhv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vlsr(Vu32.uw,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vlsr_VuwR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuw_vlsr_VuwR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlsrw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vlsr(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vlsr_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vlsr_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlsrwv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vlut32(Vu32.b,Vv32.b,Rt8)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vlut32_VbVbR(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vlut32_VbVbR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvvb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.b|=vlut32(Vu32.b,Vv32.b,Rt8)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vlut32or_VbVbVbR(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vlut32or_VbVbVbR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvvb_oracc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vlut16(Vu32.b,Vv32.h,Rt8)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vlut16_VbVhR(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vlut16_VbVhR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvwh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h|=vlut16(Vu32.b,Vv32.h,Rt8)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vlut16or_WhVbVhR(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vlut16or_WhVbVhR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvwh_oracc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vmax(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmax_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vmax_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaxh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vmax(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vmax_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vmax_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaxub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vmax(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vmax_VuhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vmax_VuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaxuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmax(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmax_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vmax_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaxw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vmin(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmin_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vmin_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vminh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vmin(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vmin_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vmin_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vminub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vmin(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vmin_VuhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vmin_VuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vminuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmin(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmin_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vmin_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vminw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vmpa(Vuu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpa_WubRb(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpa_WubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpabus)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vmpa(Vuu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpaacc_WhWubRb(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpaacc_WhWubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpabus_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vmpa(Vuu32.ub,Vvv32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpa_WubWb(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpa_WubWb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpabusv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vmpa(Vuu32.ub,Vvv32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpa_WubWub(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpa_WubWub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpabuuv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vmpa(Vuu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpa_WhRb(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpa_WhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpahb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vmpa(Vuu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpaacc_WwWhRb(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpaacc_WwWhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpahb_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vmpy(Vu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpy_VubRb(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpy_VubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpybus)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vmpy(Vu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpyacc_WhVubRb(HVX_VectorPair Vxx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpyacc_WhVubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpybus_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vmpy(Vu32.ub,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpy_VubVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpy_VubVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpybusv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vmpy(Vu32.ub,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpyacc_WhVubVb(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpyacc_WhVubVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpybusv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vmpy(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpy_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpy_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpybv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vmpy(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpyacc_WhVbVb(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpyacc_WhVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpybv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpye(Vu32.w,Vv32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpye_VwVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpye_VwVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyewuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vmpy(Vu32.h,Rt32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpy_VhRh(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpy_VhRh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vmpy(Vu32.h,Rt32.h):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpyacc_WwVhRh_sat(HVX_VectorPair Vxx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpyacc_WwVhRh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyhsat_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vmpy(Vu32.h,Rt32.h):<<1:rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpy_VhRh_s1_rnd_sat(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vmpy_VhRh_s1_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyhsrs)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vmpy(Vu32.h,Rt32.h):<<1:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpy_VhRh_s1_sat(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vmpy_VhRh_s1_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyhss)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vmpy(Vu32.h,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpy_VhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpy_VhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyhus)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vmpy(Vu32.h,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpyacc_WwVhVuh(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpyacc_WwVhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyhus_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vmpy(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpy_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpy_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyhv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vmpy(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpyacc_WwVhVh(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpyacc_WwVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyhv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vmpy(Vu32.h,Vv32.h):<<1:rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpy_VhVh_s1_rnd_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vmpy_VhVh_s1_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyhvsrs)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpyieo(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyieo_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyieo_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyieoh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vmpyie(Vu32.w,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyieacc_VwVwVh(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyieacc_VwVwVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiewh_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpyie(Vu32.w,Vv32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyie_VwVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyie_VwVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiewuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vmpyie(Vu32.w,Vv32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyieacc_VwVwVuh(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyieacc_VwVwVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiewuh_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vmpyi(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpyi_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vmpyi_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyih)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.h+=vmpyi(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpyiacc_VhVhVh(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vmpyiacc_VhVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyih_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vmpyi(Vu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpyi_VhRb(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vmpyi_VhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyihb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.h+=vmpyi(Vu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpyiacc_VhVhRb(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vmpyiacc_VhVhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyihb_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpyio(Vu32.w,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyio_VwVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyio_VwVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiowh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpyi(Vu32.w,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyi_VwRb(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyi_VwRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiwb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vmpyi(Vu32.w,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyiacc_VwVwRb(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyiacc_VwVwRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiwb_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpyi(Vu32.w,Rt32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyi_VwRh(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyi_VwRh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiwh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vmpyi(Vu32.w,Rt32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyiacc_VwVwRh(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyiacc_VwVwRh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiwh_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpyo(Vu32.w,Vv32.h):<<1:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyo_VwVh_s1_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyo_VwVh_s1_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyowh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpyo(Vu32.w,Vv32.h):<<1:rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyo_VwVh_s1_rnd_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyo_VwVh_s1_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyowh_rnd)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vmpyo(Vu32.w,Vv32.h):<<1:rnd:sat:shift
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyoacc_VwVwVh_s1_rnd_sat_shift(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyoacc_VwVwVh_s1_rnd_sat_shift __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyowh_rnd_sacc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vmpyo(Vu32.w,Vv32.h):<<1:sat:shift
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyoacc_VwVwVh_s1_sat_shift __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyowh_sacc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uh=vmpy(Vu32.ub,Rt32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuh_vmpy_VubRub(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuh_vmpy_VubRub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.uh+=vmpy(Vu32.ub,Rt32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuh_vmpyacc_WuhVubRub(HVX_VectorPair Vxx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuh_vmpyacc_WuhVubRub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyub_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uh=vmpy(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuh_vmpy_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuh_vmpy_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyubv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.uh+=vmpy(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuh_vmpyacc_WuhVubVub(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuh_vmpyacc_WuhVubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyubv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vmpy(Vu32.uh,Rt32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vmpy_VuhRuh(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vmpy_VuhRuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.uw+=vmpy(Vu32.uh,Rt32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vmpyacc_WuwVuhRuh(HVX_VectorPair Vxx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vmpyacc_WuwVuhRuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyuh_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vmpy(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vmpy_VuhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vmpy_VuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyuhv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.uw+=vmpy(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vmpyacc_WuwVuhVuh(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vmpyacc_WuwVuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyuhv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vmux(Qt4,Vu32,Vv32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vmux_QVV(HVX_VectorPred Qt, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vmux_QVV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmux)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vnavg(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vnavg_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vnavg_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vnavgh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vnavg(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vnavg_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vnavg_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vnavgub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vnavg(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vnavg_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vnavg_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vnavgw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vnormamt(Vu32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vnormamt_Vh(HVX_Vector Vu)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vnormamt_Vh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vnormamth)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vnormamt(Vu32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vnormamt_Vw(HVX_Vector Vu)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vnormamt_Vw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vnormamtw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vnot(Vu32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vnot_V(HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vnot_V __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vnot)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vor(Vu32,Vv32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vor_VV(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vor_VV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vpacke(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vpacke_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vpacke_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpackeb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vpacke(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vpacke_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vpacke_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpackeh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vpack(Vu32.h,Vv32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vpack_VhVh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vpack_VhVh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpackhb_sat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vpack(Vu32.h,Vv32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vpack_VhVh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vpack_VhVh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpackhub_sat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vpacko(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vpacko_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vpacko_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpackob)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vpacko(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vpacko_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vpacko_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpackoh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vpack(Vu32.w,Vv32.w):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vpack_VwVw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vpack_VwVw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpackwh_sat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vpack(Vu32.w,Vv32.w):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vpack_VwVw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vpack_VwVw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpackwuh_sat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vpopcount(Vu32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vpopcount_Vh(HVX_Vector Vu)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vpopcount_Vh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vpopcounth)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vrdelta(Vu32,Vv32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vrdelta_VV(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vrdelta_VV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrdelta)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vrmpy(Vu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vrmpy_VubRb(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vrmpy_VubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpybus)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vrmpy(Vu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vrmpyacc_VwVubRb(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vrmpyacc_VwVubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpybus_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vrmpy(Vuu32.ub,Rt32.b,#u1)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vrmpy_WubRbI(HVX_VectorPair Vuu, Word32 Rt, Word32 Iu1)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vrmpy_WubRbI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpybusi)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vrmpy(Vuu32.ub,Rt32.b,#u1)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vrmpyacc_WwWubRbI(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt, Word32 Iu1)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vrmpyacc_WwWubRbI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpybusi_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vrmpy(Vu32.ub,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vrmpy_VubVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vrmpy_VubVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpybusv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vrmpy(Vu32.ub,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vrmpyacc_VwVubVb(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vrmpyacc_VwVubVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpybusv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vrmpy(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vrmpy_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vrmpy_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpybv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vrmpy(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vrmpyacc_VwVbVb(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vrmpyacc_VwVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpybv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vrmpy(Vu32.ub,Rt32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vrmpy_VubRub(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuw_vrmpy_VubRub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpyub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.uw+=vrmpy(Vu32.ub,Rt32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vrmpyacc_VuwVubRub(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuw_vrmpyacc_VuwVubRub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpyub_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vrmpy(Vuu32.ub,Rt32.ub,#u1)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vrmpy_WubRubI(HVX_VectorPair Vuu, Word32 Rt, Word32 Iu1)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vrmpy_WubRubI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpyubi)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.uw+=vrmpy(Vuu32.ub,Rt32.ub,#u1)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vrmpyacc_WuwWubRubI(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt, Word32 Iu1)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vrmpyacc_WuwWubRubI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpyubi_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vrmpy(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vrmpy_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuw_vrmpy_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpyubv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vx32.uw+=vrmpy(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vrmpyacc_VuwVubVub(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuw_vrmpyacc_VuwVubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrmpyubv_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vror(Vu32,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vror_VR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vror_VR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vror)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vround(Vu32.h,Vv32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vround_VhVh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vround_VhVh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vroundhb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vround(Vu32.h,Vv32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vround_VhVh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vround_VhVh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vroundhub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vround(Vu32.w,Vv32.w):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vround_VwVw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vround_VwVw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vroundwh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vround(Vu32.w,Vv32.w):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vround_VwVw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vround_VwVw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vroundwuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vrsad(Vuu32.ub,Rt32.ub,#u1)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vrsad_WubRubI(HVX_VectorPair Vuu, Word32 Rt, Word32 Iu1)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vrsad_WubRubI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrsadubi)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.uw+=vrsad(Vuu32.ub,Rt32.ub,#u1)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vrsadacc_WuwWubRubI(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt, Word32 Iu1)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wuw_vrsadacc_WuwWubRubI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrsadubi_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vsat(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vsat_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vsat_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsathub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vsat(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vsat_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vsat_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsatwh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vsxt(Vu32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vsxt_Vb(HVX_Vector Vu)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vsxt_Vb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vsxt(Vu32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vsxt_Vh(HVX_Vector Vu)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Ww_vsxt_Vh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vshuffe(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vshuffe_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vshuffe_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshufeh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vshuff(Vu32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vshuff_Vb(HVX_Vector Vu)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vshuff_Vb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshuffb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vshuffe(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vshuffe_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vshuffe_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshuffeb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vshuff(Vu32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vshuff_Vh(HVX_Vector Vu)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vshuff_Vh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshuffh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vshuffo(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vshuffo_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vshuffo_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshuffob)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32=vshuff(Vu32,Vv32,Rt8)
+ C Intrinsic Prototype: HVX_VectorPair Q6_W_vshuff_VVR(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_W_vshuff_VVR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshuffvdd)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.b=vshuffoe(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wb_vshuffoe_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wb_vshuffoe_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshufoeb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vshuffoe(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vshuffoe_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vshuffoe_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshufoeh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vshuffo(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vshuffo_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vshuffo_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vshufoh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vsub(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vsub_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vsub_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.b=vsub(Vuu32.b,Vvv32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wb_vsub_WbWb(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wb_vsub_WbWb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubb_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (!Qv4) Vx32.b-=Vu32.b
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_condnac_QnVbVb(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_condnac_QnVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubbnq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (Qv4) Vx32.b-=Vu32.b
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_condnac_QVbVb(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_condnac_QVbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubbq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vsub(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vsub_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vsub_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vsub(Vuu32.h,Vvv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vsub_WhWh(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vsub_WhWh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubh_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (!Qv4) Vx32.h-=Vu32.h
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_condnac_QnVhVh(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_condnac_QnVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubhnq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (Qv4) Vx32.h-=Vu32.h
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_condnac_QVhVh(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_condnac_QVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubhq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vsub(Vu32.h,Vv32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vsub_VhVh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vsub_VhVh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubhsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vsub(Vuu32.h,Vvv32.h):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vsub_WhWh_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vsub_WhWh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubhsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vsub(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vsub_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vsub_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubhw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vsub(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vsub_VubVub(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vsub_VubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsububh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vsub(Vu32.ub,Vv32.ub):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vsub_VubVub_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vsub_VubVub_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsububsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.ub=vsub(Vuu32.ub,Vvv32.ub):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wub_vsub_WubWub_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wub_vsub_WubWub_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsububsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vsub(Vu32.uh,Vv32.uh):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vsub_VuhVuh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vsub_VuhVuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubuhsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uh=vsub(Vuu32.uh,Vvv32.uh):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuh_vsub_WuhWuh_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wuh_vsub_WuhWuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubuhsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vsub(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vsub_VuhVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vsub_VuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubuhw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vsub(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vsub_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vsub_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubw)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vsub(Vuu32.w,Vvv32.w)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vsub_WwWw(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Ww_vsub_WwWw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubw_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (!Qv4) Vx32.w-=Vu32.w
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_condnac_QnVwVw(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_condnac_QnVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubwnq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: if (Qv4) Vx32.w-=Vu32.w
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_condnac_QVwVw(HVX_VectorPred Qv, HVX_Vector Vx, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_condnac_QVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubwq)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vsub(Vu32.w,Vv32.w):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vsub_VwVw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vsub_VwVw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubwsat)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vsub(Vuu32.w,Vvv32.w):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vsub_WwWw_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Ww_vsub_WwWw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubwsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32=vswap(Qt4,Vu32,Vv32)
+ C Intrinsic Prototype: HVX_VectorPair Q6_W_vswap_QVV(HVX_VectorPred Qt, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_W_vswap_QVV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vswap)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vtmpy(Vuu32.b,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vtmpy_WbRb(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vtmpy_WbRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vtmpyb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vtmpy(Vuu32.b,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vtmpyacc_WhWbRb(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vtmpyacc_WhWbRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vtmpyb_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vtmpy(Vuu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vtmpy_WubRb(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vtmpy_WubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vtmpybus)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vtmpy(Vuu32.ub,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vtmpyacc_WhWubRb(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vtmpyacc_WhWubRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vtmpybus_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vtmpy(Vuu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vtmpy_WhRb(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vtmpy_WhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vtmpyhb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vtmpy(Vuu32.h,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vtmpyacc_WwWhRb(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vtmpyacc_WwWhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vtmpyhb_acc)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vunpack(Vu32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vunpack_Vb(HVX_Vector Vu)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vunpack_Vb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vunpackb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vunpack(Vu32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vunpack_Vh(HVX_Vector Vu)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Ww_vunpack_Vh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vunpackh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h|=vunpacko(Vu32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vunpackoor_WhVb(HVX_VectorPair Vxx, HVX_Vector Vu)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vunpackoor_WhVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vunpackob)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w|=vunpacko(Vu32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vunpackoor_WwVh(HVX_VectorPair Vxx, HVX_Vector Vu)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Ww_vunpackoor_WwVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vunpackoh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uh=vunpack(Vu32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuh_vunpack_Vub(HVX_Vector Vu)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wuh_vunpack_Vub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vunpackub)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vunpack(Vu32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vunpack_Vuh(HVX_Vector Vu)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wuw_vunpack_Vuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vunpackuh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vd32=vxor(Vu32,Vv32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vxor_VV(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vxor_VV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vxor)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uh=vzxt(Vu32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuh_vzxt_Vub(HVX_Vector Vu)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wuh_vzxt_Vub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vzb)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 60
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vzxt(Vu32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vzxt_Vuh(HVX_Vector Vu)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wuw_vzxt_Vuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vzh)
+#endif /* __HEXAGON_ARCH___ >= 60 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vsplat(Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vsplat_R(Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vb_vsplat_R __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_lvsplatb)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vsplat(Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vsplat_R(Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vh_vsplat_R __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_lvsplath)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Qd4=vsetq2(Rt32)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Q_vsetq2_R(Word32 Rt)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Q_vsetq2_R __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_pred_scalar2v2)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Qd4.b=vshuffe(Qs4.h,Qt4.h)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Qb_vshuffe_QhQh(HVX_VectorPred Qs, HVX_VectorPred Qt)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Qb_vshuffe_QhQh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_shuffeqh)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Qd4.h=vshuffe(Qs4.w,Qt4.w)
+ C Intrinsic Prototype: HVX_VectorPred Q6_Qh_vshuffe_QwQw(HVX_VectorPred Qs, HVX_VectorPred Qt)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Qh_vshuffe_QwQw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_shuffeqw)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vadd(Vu32.b,Vv32.b):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vadd_VbVb_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vadd_VbVb_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddbsat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vdd32.b=vadd(Vuu32.b,Vvv32.b):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wb_vadd_WbWb_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wb_vadd_WbWb_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddbsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vadd(Vu32.w,Vv32.w,Qx4):carry
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vadd_VwVwQ_carry(HVX_Vector Vu, HVX_Vector Vv, HVX_VectorPred* Qx)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vadd_VwVwQ_carry __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddcarry)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vadd(vclb(Vu32.h),Vv32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vadd_vclb_VhVh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vadd_vclb_VhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddclbh)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vadd(vclb(Vu32.w),Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vadd_vclb_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vadd_vclb_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddclbw)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vadd(Vu32.h,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vaddacc_WwVhVh(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vaddacc_WwVhVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddhw_acc)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vadd(Vu32.ub,Vv32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vaddacc_WhVubVub(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vaddacc_WhVubVub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddubh_acc)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vadd(Vu32.ub,Vv32.b):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vadd_VubVb_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vadd_VubVb_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddububb_sat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vadd(Vu32.uh,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vaddacc_WwVuhVuh(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vaddacc_WwVuhVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vadduhw_acc)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vadd(Vu32.uw,Vv32.uw):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vadd_VuwVuw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuw_vadd_VuwVuw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vadduwsat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vadd(Vuu32.uw,Vvv32.uw):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vadd_WuwWuw_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wuw_vadd_WuwWuw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vadduwsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32=vand(!Qu4,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vand_QnR(HVX_VectorPred Qu, Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_V_vand_QnR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vandnqrt)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vx32|=vand(!Qu4,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vandor_VQnR(HVX_Vector Vx, HVX_VectorPred Qu, Word32 Rt)
+ Instruction Type: CVI_VX_LATE
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_V_vandor_VQnR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vandnqrt_acc)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32=vand(!Qv4,Vu32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vand_QnV(HVX_VectorPred Qv, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vand_QnV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vandvnqv)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32=vand(Qv4,Vu32)
+ C Intrinsic Prototype: HVX_Vector Q6_V_vand_QV(HVX_VectorPred Qv, HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_V_vand_QV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vandvqv)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vasr(Vu32.h,Vv32.h,Rt8):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vasr_VhVhR_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vasr_VhVhR_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrhbsat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vasr(Vu32.uw,Vv32.uw,Rt8):rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vasr_VuwVuwR_rnd_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vasr_VuwVuwR_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasruwuhrndsat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vasr(Vu32.w,Vv32.w,Rt8):rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vasr_VwVwR_rnd_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vasr_VwVwR_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrwuhrndsat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vlsr(Vu32.ub,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vlsr_VubR(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vlsr_VubR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlsrb)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vlut32(Vu32.b,Vv32.b,Rt8):nomatch
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vlut32_VbVbR_nomatch(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vlut32_VbVbR_nomatch __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvvb_nm)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vx32.b|=vlut32(Vu32.b,Vv32.b,#u3)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vlut32or_VbVbVbI(HVX_Vector Vx, HVX_Vector Vu, HVX_Vector Vv, Word32 Iu3)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vlut32or_VbVbVbI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvvb_oracci)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vlut32(Vu32.b,Vv32.b,#u3)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vlut32_VbVbI(HVX_Vector Vu, HVX_Vector Vv, Word32 Iu3)
+ Instruction Type: CVI_VP
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vlut32_VbVbI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvvbi)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vlut16(Vu32.b,Vv32.h,Rt8):nomatch
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vlut16_VbVhR_nomatch(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vlut16_VbVhR_nomatch __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvwh_nm)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h|=vlut16(Vu32.b,Vv32.h,#u3)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vlut16or_WhVbVhI(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv, Word32 Iu3)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vlut16or_WhVbVhI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvwh_oracci)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vlut16(Vu32.b,Vv32.h,#u3)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vlut16_VbVhI(HVX_Vector Vu, HVX_Vector Vv, Word32 Iu3)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wh_vlut16_VbVhI __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlutvwhi)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vmax(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vmax_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vmax_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmaxb)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vmin(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vmin_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vmin_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vminb)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=vmpa(Vuu32.uh,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpa_WuhRb(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpa_WuhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpauhb)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vmpa(Vuu32.uh,Rt32.b)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpaacc_WwWuhRb(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpaacc_WwWuhRb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpauhb_acc)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vdd32=vmpye(Vu32.w,Vv32.uh)
+ C Intrinsic Prototype: HVX_VectorPair Q6_W_vmpye_VwVuh(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_W_vmpye_VwVuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyewuh_64)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vmpyi(Vu32.w,Rt32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyi_VwRub(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyi_VwRub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiwub)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vx32.w+=vmpyi(Vu32.w,Rt32.ub)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vmpyiacc_VwVwRub(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vw_vmpyiacc_VwVwRub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyiwub_acc)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vxx32+=vmpyo(Vu32.w,Vv32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_W_vmpyoacc_WVwVh(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_W_vmpyoacc_WVwVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyowh_64_acc)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vround(Vu32.uh,Vv32.uh):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vround_VuhVuh_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vround_VuhVuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrounduhub)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vround(Vu32.uw,Vv32.uw):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vround_VuwVuw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vround_VuwVuw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrounduwuh)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vsat(Vu32.uw,Vv32.uw)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vsat_VuwVuw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vsat_VuwVuw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsatuwuh)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vsub(Vu32.b,Vv32.b):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vsub_VbVb_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vsub_VbVb_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubbsat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vdd32.b=vsub(Vuu32.b,Vvv32.b):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wb_vsub_WbWb_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wb_vsub_WbWb_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubbsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vsub(Vu32.w,Vv32.w,Qx4):carry
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vsub_VwVwQ_carry(HVX_Vector Vu, HVX_Vector Vv, HVX_VectorPred* Qx)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vsub_VwVwQ_carry __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubcarry)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vsub(Vu32.ub,Vv32.b):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vsub_VubVb_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vsub_VubVb_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubububb_sat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vsub(Vu32.uw,Vv32.uw):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vsub_VuwVuw_sat(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuw_vsub_VuwVuw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubuwsat)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 62
+/* ==========================================================================
+ Assembly Syntax: Vdd32.uw=vsub(Vuu32.uw,Vvv32.uw):sat
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wuw_vsub_WuwWuw_sat(HVX_VectorPair Vuu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_VA_DV
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Wuw_vsub_WuwWuw_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsubuwsat_dv)
+#endif /* __HEXAGON_ARCH___ >= 62 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vabs(Vu32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vabs_Vb(HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vabs_Vb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsb)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vabs(Vu32.b):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vabs_Vb_sat(HVX_Vector Vu)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vabs_Vb_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vabsb_sat)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vx32.h+=vasl(Vu32.h,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vaslacc_VhVhR(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vaslacc_VhVhR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaslh_acc)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vx32.h+=vasr(Vu32.h,Rt32)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vasracc_VhVhR(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_vasracc_VhVhR __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasrh_acc)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vasr(Vu32.uh,Vv32.uh,Rt8):rnd:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vasr_VuhVuhR_rnd_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vasr_VuhVuhR_rnd_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasruhubrndsat)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.ub=vasr(Vu32.uh,Vv32.uh,Rt8):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vub_vasr_VuhVuhR_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vub_vasr_VuhVuhR_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasruhubsat)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.uh=vasr(Vu32.uw,Vv32.uw,Rt8):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vuh_vasr_VuwVuwR_sat(HVX_Vector Vu, HVX_Vector Vv, Word32 Rt)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuh_vasr_VuwVuwR_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasruwuhsat)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vavg(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vavg_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vavg_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavgb)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vavg(Vu32.b,Vv32.b):rnd
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vavg_VbVb_rnd(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vavg_VbVb_rnd __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavgbrnd)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vavg(Vu32.uw,Vv32.uw)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vavg_VuwVuw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuw_vavg_VuwVuw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavguw)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vavg(Vu32.uw,Vv32.uw):rnd
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vavg_VuwVuw_rnd(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuw_vavg_VuwVuw_rnd __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vavguwrnd)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vdd32=#0
+ C Intrinsic Prototype: HVX_VectorPair Q6_W_vzero()
+ Instruction Type: MAPPING
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_W_vzero __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vdd0)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vtmp.h=vgather(Rt32,Mu2,Vv32.h).h
+ C Intrinsic Prototype: void Q6_vgather_ARMVh(HVX_Vector* Rs, Word32 Rt, Word32 Mu, HVX_Vector Vv)
+ Instruction Type: CVI_GATHER
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_vgather_ARMVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgathermh)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: if (Qs4) vtmp.h=vgather(Rt32,Mu2,Vv32.h).h
+ C Intrinsic Prototype: void Q6_vgather_AQRMVh(HVX_Vector* Rs, HVX_VectorPred Qs, Word32 Rt, Word32 Mu, HVX_Vector Vv)
+ Instruction Type: CVI_GATHER
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_vgather_AQRMVh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgathermhq)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vtmp.h=vgather(Rt32,Mu2,Vvv32.w).h
+ C Intrinsic Prototype: void Q6_vgather_ARMWw(HVX_Vector* Rs, Word32 Rt, Word32 Mu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_GATHER_DV
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_vgather_ARMWw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgathermhw)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: if (Qs4) vtmp.h=vgather(Rt32,Mu2,Vvv32.w).h
+ C Intrinsic Prototype: void Q6_vgather_AQRMWw(HVX_Vector* Rs, HVX_VectorPred Qs, Word32 Rt, Word32 Mu, HVX_VectorPair Vvv)
+ Instruction Type: CVI_GATHER_DV
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_vgather_AQRMWw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgathermhwq)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vtmp.w=vgather(Rt32,Mu2,Vv32.w).w
+ C Intrinsic Prototype: void Q6_vgather_ARMVw(HVX_Vector* Rs, Word32 Rt, Word32 Mu, HVX_Vector Vv)
+ Instruction Type: CVI_GATHER
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_vgather_ARMVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgathermw)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: if (Qs4) vtmp.w=vgather(Rt32,Mu2,Vv32.w).w
+ C Intrinsic Prototype: void Q6_vgather_AQRMVw(HVX_Vector* Rs, HVX_VectorPred Qs, Word32 Rt, Word32 Mu, HVX_Vector Vv)
+ Instruction Type: CVI_GATHER
+ Execution Slots: SLOT01
+ ========================================================================== */
+
+#define Q6_vgather_AQRMVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vgathermwq)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=vlut4(Vu32.uh,Rtt32.h)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vlut4_VuhPh(HVX_Vector Vu, Word64 Rtt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT2
+ ========================================================================== */
+
+#define Q6_Vh_vlut4_VuhPh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vlut4)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vdd32.h=vmpa(Vuu32.ub,Rt32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpa_WubRub(HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpa_WubRub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpabuu)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vxx32.h+=vmpa(Vuu32.ub,Rt32.ub)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Wh_vmpaacc_WhWubRub(HVX_VectorPair Vxx, HVX_VectorPair Vuu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Wh_vmpaacc_WhWubRub __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpabuu_acc)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vx32.h=vmpa(Vx32.h,Vu32.h,Rtt32.h):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpa_VhVhVhPh_sat(HVX_Vector Vx, HVX_Vector Vu, Word64 Rtt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT2
+ ========================================================================== */
+
+#define Q6_Vh_vmpa_VhVhVhPh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpahhsat)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vx32.h=vmpa(Vx32.h,Vu32.uh,Rtt32.uh):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmpa_VhVhVuhPuh_sat(HVX_Vector Vx, HVX_Vector Vu, Word64 Rtt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT2
+ ========================================================================== */
+
+#define Q6_Vh_vmpa_VhVhVuhPuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpauhuhsat)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vx32.h=vmps(Vx32.h,Vu32.uh,Rtt32.uh):sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_vmps_VhVhVuhPuh_sat(HVX_Vector Vx, HVX_Vector Vu, Word64 Rtt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT2
+ ========================================================================== */
+
+#define Q6_Vh_vmps_VhVhVuhPuh_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpsuhuhsat)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=vmpy(Vu32.h,Rt32.h)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vmpyacc_WwVhRh(HVX_VectorPair Vxx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_vmpyacc_WwVhRh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyh_acc)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vmpye(Vu32.uh,Rt32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vmpye_VuhRuh(HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuw_vmpye_VuhRuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyuhe)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vx32.uw+=vmpye(Vu32.uh,Rt32.uh)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vmpyeacc_VuwVuhRuh(HVX_Vector Vx, HVX_Vector Vu, Word32 Rt)
+ Instruction Type: CVI_VX
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Vuw_vmpyeacc_VuwVuhRuh __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vmpyuhe_acc)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=vnavg(Vu32.b,Vv32.b)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_vnavg_VbVb(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_vnavg_VbVb __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vnavgb)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.b=prefixsum(Qv4)
+ C Intrinsic Prototype: HVX_Vector Q6_Vb_prefixsum_Q(HVX_VectorPred Qv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vb_prefixsum_Q __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vprefixqb)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.h=prefixsum(Qv4)
+ C Intrinsic Prototype: HVX_Vector Q6_Vh_prefixsum_Q(HVX_VectorPred Qv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vh_prefixsum_Q __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vprefixqh)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=prefixsum(Qv4)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_prefixsum_Q(HVX_VectorPred Qv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_prefixsum_Q __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vprefixqw)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vscatter(Rt32,Mu2,Vv32.h).h=Vw32
+ C Intrinsic Prototype: void Q6_vscatter_RMVhV(Word32 Rt, Word32 Mu, HVX_Vector Vv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatter_RMVhV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermh)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vscatter(Rt32,Mu2,Vv32.h).h+=Vw32
+ C Intrinsic Prototype: void Q6_vscatteracc_RMVhV(Word32 Rt, Word32 Mu, HVX_Vector Vv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatteracc_RMVhV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermh_add)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: if (Qs4) vscatter(Rt32,Mu2,Vv32.h).h=Vw32
+ C Intrinsic Prototype: void Q6_vscatter_QRMVhV(HVX_VectorPred Qs, Word32 Rt, Word32 Mu, HVX_Vector Vv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatter_QRMVhV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermhq)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vscatter(Rt32,Mu2,Vvv32.w).h=Vw32
+ C Intrinsic Prototype: void Q6_vscatter_RMWwV(Word32 Rt, Word32 Mu, HVX_VectorPair Vvv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER_DV
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatter_RMWwV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermhw)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vscatter(Rt32,Mu2,Vvv32.w).h+=Vw32
+ C Intrinsic Prototype: void Q6_vscatteracc_RMWwV(Word32 Rt, Word32 Mu, HVX_VectorPair Vvv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER_DV
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatteracc_RMWwV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermhw_add)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: if (Qs4) vscatter(Rt32,Mu2,Vvv32.w).h=Vw32
+ C Intrinsic Prototype: void Q6_vscatter_QRMWwV(HVX_VectorPred Qs, Word32 Rt, Word32 Mu, HVX_VectorPair Vvv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER_DV
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatter_QRMWwV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermhwq)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vscatter(Rt32,Mu2,Vv32.w).w=Vw32
+ C Intrinsic Prototype: void Q6_vscatter_RMVwV(Word32 Rt, Word32 Mu, HVX_Vector Vv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatter_RMVwV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermw)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: vscatter(Rt32,Mu2,Vv32.w).w+=Vw32
+ C Intrinsic Prototype: void Q6_vscatteracc_RMVwV(Word32 Rt, Word32 Mu, HVX_Vector Vv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatteracc_RMVwV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermw_add)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 65
+/* ==========================================================================
+ Assembly Syntax: if (Qs4) vscatter(Rt32,Mu2,Vv32.w).w=Vw32
+ C Intrinsic Prototype: void Q6_vscatter_QRMVwV(HVX_VectorPred Qs, Word32 Rt, Word32 Mu, HVX_Vector Vv, HVX_Vector Vw)
+ Instruction Type: CVI_SCATTER
+ Execution Slots: SLOT0
+ ========================================================================== */
+
+#define Q6_vscatter_QRMVwV __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vscattermwq)
+#endif /* __HEXAGON_ARCH___ >= 65 */
+
+#if __HVX_ARCH__ >= 66
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vadd(Vu32.w,Vv32.w,Qs4):carry:sat
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vadd_VwVwQ_carry_sat(HVX_Vector Vu, HVX_Vector Vv, HVX_VectorPred Qs)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vadd_VwVwQ_carry_sat __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vaddcarrysat)
+#endif /* __HEXAGON_ARCH___ >= 66 */
+
+#if __HVX_ARCH__ >= 66
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w=vasrinto(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_vasrinto_WwVwVw(HVX_VectorPair Vxx, HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VP_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Ww_vasrinto_WwVwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vasr_into)
+#endif /* __HEXAGON_ARCH___ >= 66 */
+
+#if __HVX_ARCH__ >= 66
+/* ==========================================================================
+ Assembly Syntax: Vd32.uw=vrotr(Vu32.uw,Vv32.uw)
+ C Intrinsic Prototype: HVX_Vector Q6_Vuw_vrotr_VuwVuw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VS
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vuw_vrotr_VuwVuw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vrotr)
+#endif /* __HEXAGON_ARCH___ >= 66 */
+
+#if __HVX_ARCH__ >= 66
+/* ==========================================================================
+ Assembly Syntax: Vd32.w=vsatdw(Vu32.w,Vv32.w)
+ C Intrinsic Prototype: HVX_Vector Q6_Vw_vsatdw_VwVw(HVX_Vector Vu, HVX_Vector Vv)
+ Instruction Type: CVI_VA
+ Execution Slots: SLOT0123
+ ========================================================================== */
+
+#define Q6_Vw_vsatdw_VwVw __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_vsatdw)
+#endif /* __HEXAGON_ARCH___ >= 66 */
+
+#if __HVX_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=v6mpy(Vuu32.ub,Vvv32.b,#u2):h
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_v6mpy_WubWbI_h(HVX_VectorPair Vuu, HVX_VectorPair Vvv, Word32 Iu2)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_v6mpy_WubWbI_h __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_v6mpyhubs10)
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#if __HVX_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=v6mpy(Vuu32.ub,Vvv32.b,#u2):h
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_v6mpyacc_WwWubWbI_h(HVX_VectorPair Vxx, HVX_VectorPair Vuu, HVX_VectorPair Vvv, Word32 Iu2)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_v6mpyacc_WwWubWbI_h __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_v6mpyhubs10_vxx)
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#if __HVX_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: Vdd32.w=v6mpy(Vuu32.ub,Vvv32.b,#u2):v
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_v6mpy_WubWbI_v(HVX_VectorPair Vuu, HVX_VectorPair Vvv, Word32 Iu2)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_v6mpy_WubWbI_v __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_v6mpyvubs10)
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#if __HVX_ARCH__ >= 68
+/* ==========================================================================
+ Assembly Syntax: Vxx32.w+=v6mpy(Vuu32.ub,Vvv32.b,#u2):v
+ C Intrinsic Prototype: HVX_VectorPair Q6_Ww_v6mpyacc_WwWubWbI_v(HVX_VectorPair Vxx, HVX_VectorPair Vuu, HVX_VectorPair Vvv, Word32 Iu2)
+ Instruction Type: CVI_VX_DV
+ Execution Slots: SLOT23
+ ========================================================================== */
+
+#define Q6_Ww_v6mpyacc_WwWubWbI_v __BUILTIN_VECTOR_WRAP(__builtin_HEXAGON_V6_v6mpyvubs10_vxx)
+#endif /* __HEXAGON_ARCH___ >= 68 */
+
+#endif /* __HVX__ */
+
+#endif
diff --git a/src/llvm-project/clang/lib/Headers/immintrin.h b/src/llvm-project/clang/lib/Headers/immintrin.h
index 22f7a52..56d3dad 100644
--- a/src/llvm-project/clang/lib/Headers/immintrin.h
+++ b/src/llvm-project/clang/lib/Headers/immintrin.h
@@ -72,11 +72,6 @@
#include <f16cintrin.h>
#endif
-#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
- defined(__VPCLMULQDQ__)
-#include <vpclmulqdqintrin.h>
-#endif
-
/* No feature check desired due to internal checks */
#include <bmiintrin.h>
@@ -231,6 +226,11 @@
#endif
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
+ defined(__VPCLMULQDQ__)
+#include <vpclmulqdqintrin.h>
+#endif
+
+#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
defined(__VAES__)
#include <vaesintrin.h>
#endif
diff --git a/src/llvm-project/clang/lib/Headers/intrin.h b/src/llvm-project/clang/lib/Headers/intrin.h
index a78b969..ff8eb8f 100644
--- a/src/llvm-project/clang/lib/Headers/intrin.h
+++ b/src/llvm-project/clang/lib/Headers/intrin.h
@@ -451,24 +451,47 @@
static __inline__ void __DEFAULT_FN_ATTRS __movsb(unsigned char *__dst,
unsigned char const *__src,
size_t __n) {
- __asm__ __volatile__("rep movsb" : "+D"(__dst), "+S"(__src), "+c"(__n)
- : : "memory");
+#if defined(__x86_64__)
+ __asm__ __volatile__("rep movsb"
+ : "+D"(__dst), "+S"(__src), "+c"(__n)
+ :
+ : "memory");
+#else
+ __asm__ __volatile__("xchg %%esi, %1\nrep movsb\nxchg %%esi, %1"
+ : "+D"(__dst), "+r"(__src), "+c"(__n)
+ :
+ : "memory");
+#endif
}
static __inline__ void __DEFAULT_FN_ATTRS __movsd(unsigned long *__dst,
unsigned long const *__src,
size_t __n) {
+#if defined(__x86_64__)
__asm__ __volatile__("rep movsl"
: "+D"(__dst), "+S"(__src), "+c"(__n)
:
: "memory");
+#else
+ __asm__ __volatile__("xchg %%esi, %1\nrep movsl\nxchg %%esi, %1"
+ : "+D"(__dst), "+r"(__src), "+c"(__n)
+ :
+ : "memory");
+#endif
}
static __inline__ void __DEFAULT_FN_ATTRS __movsw(unsigned short *__dst,
unsigned short const *__src,
size_t __n) {
+#if defined(__x86_64__)
__asm__ __volatile__("rep movsw"
: "+D"(__dst), "+S"(__src), "+c"(__n)
:
: "memory");
+#else
+ __asm__ __volatile__("xchg %%esi, %1\nrep movsw\nxchg %%esi, %1"
+ : "+D"(__dst), "+r"(__src), "+c"(__n)
+ :
+ : "memory");
+#endif
}
static __inline__ void __DEFAULT_FN_ATTRS __stosd(unsigned long *__dst,
unsigned long __x,
@@ -507,16 +530,26 @@
|* Misc
\*----------------------------------------------------------------------------*/
#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
+#define __cpuid_count(__leaf, __count, __eax, __ebx, __ecx, __edx) \
+ __asm("cpuid" \
+ : "=a"(__eax), "=b"(__ebx), "=c"(__ecx), "=d"(__edx) \
+ : "0"(__leaf), "2"(__count))
+#else
+/* x86-64 uses %rbx as the base register, so preserve it. */
+#define __cpuid_count(__leaf, __count, __eax, __ebx, __ecx, __edx) \
+ __asm("xchgq %%rbx,%q1\n" \
+ "cpuid\n" \
+ "xchgq %%rbx,%q1" \
+ : "=a"(__eax), "=r"(__ebx), "=c"(__ecx), "=d"(__edx) \
+ : "0"(__leaf), "2"(__count))
+#endif
static __inline__ void __DEFAULT_FN_ATTRS __cpuid(int __info[4], int __level) {
- __asm__("cpuid"
- : "=a"(__info[0]), "=b"(__info[1]), "=c"(__info[2]), "=d"(__info[3])
- : "a"(__level), "c"(0));
+ __cpuid_count(__level, 0, __info[0], __info[1], __info[2], __info[3]);
}
static __inline__ void __DEFAULT_FN_ATTRS __cpuidex(int __info[4], int __level,
int __ecx) {
- __asm__("cpuid"
- : "=a"(__info[0]), "=b"(__info[1]), "=c"(__info[2]), "=d"(__info[3])
- : "a"(__level), "c"(__ecx));
+ __cpuid_count(__level, __ecx, __info[0], __info[1], __info[2], __info[3]);
}
static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
__asm__ volatile("hlt");
diff --git a/src/llvm-project/clang/lib/Headers/keylockerintrin.h b/src/llvm-project/clang/lib/Headers/keylockerintrin.h
index c15d39c..68b0a56 100644
--- a/src/llvm-project/clang/lib/Headers/keylockerintrin.h
+++ b/src/llvm-project/clang/lib/Headers/keylockerintrin.h
@@ -230,10 +230,12 @@
/// HandleKeyType (Handle[511:0]) != HANDLE_KEY_TYPE_AES256 )
/// IF (IllegalHandle)
/// ZF := 1
+/// MEM[__odata+127:__odata] := 0
/// ELSE
/// (UnwrappedKey, Authentic) := UnwrapKeyAndAuthenticate512 (Handle[511:0], IWKey)
/// IF (Authentic == 0)
/// ZF := 1
+/// MEM[__odata+127:__odata] := 0
/// ELSE
/// MEM[__odata+127:__odata] := AES256Encrypt (__idata[127:0], UnwrappedKey)
/// ZF := 0
@@ -267,10 +269,12 @@
/// HandleKeyType (Handle[383:0]) != HANDLE_KEY_TYPE_AES128)
/// IF (IllegalHandle)
/// ZF := 1
+/// MEM[__odata+127:__odata] := 0
/// ELSE
/// (UnwrappedKey, Authentic) := UnwrapKeyAndAuthenticate384 (Handle[383:0], IWKey)
/// IF (Authentic == 0)
/// ZF := 1
+/// MEM[__odata+127:__odata] := 0
/// ELSE
/// MEM[__odata+127:__odata] := AES128Decrypt (__idata[127:0], UnwrappedKey)
/// ZF := 0
@@ -304,10 +308,12 @@
/// HandleKeyType (Handle[511:0]) != HANDLE_KEY_TYPE_AES256)
/// IF (IllegalHandle)
/// ZF := 1
+/// MEM[__odata+127:__odata] := 0
/// ELSE
/// (UnwrappedKey, Authentic) := UnwrapKeyAndAuthenticate512 (Handle[511:0], IWKey)
/// IF (Authentic == 0)
/// ZF := 1
+/// MEM[__odata+127:__odata] := 0
/// ELSE
/// MEM[__odata+127:__odata] := AES256Decrypt (__idata[127:0], UnwrappedKey)
/// ZF := 0
@@ -354,10 +360,16 @@
/// HandleKeyType (Handle[383:0]) != HANDLE_KEY_TYPE_AES128 )
/// IF (IllegalHandle)
/// ZF := 1
+/// FOR i := 0 to 7
+/// __odata[i] := 0
+/// ENDFOR
/// ELSE
/// (UnwrappedKey, Authentic) := UnwrapKeyAndAuthenticate384 (Handle[383:0], IWKey)
/// IF Authentic == 0
/// ZF := 1
+/// FOR i := 0 to 7
+/// __odata[i] := 0
+/// ENDFOR
/// ELSE
/// FOR i := 0 to 7
/// __odata[i] := AES128Encrypt (__idata[i], UnwrappedKey)
@@ -394,10 +406,16 @@
/// HandleKeyType (Handle[511:0]) != HANDLE_KEY_TYPE_AES512 )
/// IF (IllegalHandle)
/// ZF := 1
+/// FOR i := 0 to 7
+/// __odata[i] := 0
+/// ENDFOR
/// ELSE
/// (UnwrappedKey, Authentic) := UnwrapKeyAndAuthenticate512 (Handle[511:0], IWKey)
/// IF Authentic == 0
/// ZF := 1
+/// FOR i := 0 to 7
+/// __odata[i] := 0
+/// ENDFOR
/// ELSE
/// FOR i := 0 to 7
/// __odata[i] := AES256Encrypt (__idata[i], UnwrappedKey)
@@ -434,10 +452,16 @@
/// HandleKeyType (Handle) != HANDLE_KEY_TYPE_AES128 )
/// IF (IllegalHandle)
/// ZF := 1
+/// FOR i := 0 to 7
+/// __odata[i] := 0
+/// ENDFOR
/// ELSE
/// (UnwrappedKey, Authentic) := UnwrapKeyAndAuthenticate384 (Handle[383:0], IWKey)
/// IF Authentic == 0
/// ZF := 1
+/// FOR i := 0 to 7
+/// __odata[i] := 0
+/// ENDFOR
/// ELSE
/// FOR i := 0 to 7
/// __odata[i] := AES128Decrypt (__idata[i], UnwrappedKey)
@@ -474,10 +498,16 @@
/// HandleKeyType (Handle) != HANDLE_KEY_TYPE_AES512 )
/// If (IllegalHandle)
/// ZF := 1
+/// FOR i := 0 to 7
+/// __odata[i] := 0
+/// ENDFOR
/// ELSE
/// (UnwrappedKey, Authentic) := UnwrapKeyAndAuthenticate512 (Handle[511:0], IWKey)
/// IF Authentic == 0
/// ZF := 1
+/// FOR i := 0 to 7
+/// __odata[i] := 0
+/// ENDFOR
/// ELSE
/// FOR i := 0 to 7
/// __odata[i] := AES256Decrypt (__idata[i], UnwrappedKey)
diff --git a/src/llvm-project/clang/lib/Headers/opencl-c-base.h b/src/llvm-project/clang/lib/Headers/opencl-c-base.h
index e8dcd70..3c5e2c9 100644
--- a/src/llvm-project/clang/lib/Headers/opencl-c-base.h
+++ b/src/llvm-project/clang/lib/Headers/opencl-c-base.h
@@ -21,9 +21,37 @@
#define cl_khr_subgroup_shuffle 1
#define cl_khr_subgroup_shuffle_relative 1
#define cl_khr_subgroup_clustered_reduce 1
+#define cl_khr_extended_bit_ops 1
+#define cl_khr_integer_dot_product 1
+#define __opencl_c_integer_dot_product_input_4x8bit 1
+#define __opencl_c_integer_dot_product_input_4x8bit_packed 1
+
#endif // defined(__SPIR__)
#endif // (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200)
+// Define feature macros for OpenCL C 2.0
+#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ == 200)
+#define __opencl_c_pipes 1
+#define __opencl_c_generic_address_space 1
+#define __opencl_c_work_group_collective_functions 1
+#define __opencl_c_atomic_order_acq_rel 1
+#define __opencl_c_atomic_order_seq_cst 1
+#define __opencl_c_atomic_scope_device 1
+#define __opencl_c_atomic_scope_all_devices 1
+#define __opencl_c_device_enqueue 1
+#define __opencl_c_read_write_images 1
+#define __opencl_c_program_scope_global_variables 1
+#define __opencl_c_images 1
+#endif
+
+// Define header-only feature macros for OpenCL C 3.0.
+#if (__OPENCL_C_VERSION__ == 300)
+// For the SPIR target all features are supported.
+#if defined(__SPIR__)
+#define __opencl_c_atomic_scope_all_devices 1
+#endif // defined(__SPIR__)
+#endif // (__OPENCL_C_VERSION__ == 300)
+
// built-in scalar data types:
/**
@@ -141,7 +169,9 @@
typedef double double16 __attribute__((ext_vector_type(16)));
#endif
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__OPENCL_CPP_VERSION__)
+#define NULL nullptr
+#elif defined(__OPENCL_C_VERSION__)
#define NULL ((void*)0)
#endif
@@ -297,7 +327,12 @@
memory_scope_work_item = __OPENCL_MEMORY_SCOPE_WORK_ITEM,
memory_scope_work_group = __OPENCL_MEMORY_SCOPE_WORK_GROUP,
memory_scope_device = __OPENCL_MEMORY_SCOPE_DEVICE,
+#if defined(__opencl_c_atomic_scope_all_devices)
memory_scope_all_svm_devices = __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES,
+#if (__OPENCL_C_VERSION__ >= CL_VERSION_3_0)
+ memory_scope_all_devices = memory_scope_all_svm_devices,
+#endif // __OPENCL_C_VERSION__ >= CL_VERSION_3_0
+#endif // defined(__opencl_c_atomic_scope_all_devices)
#if defined(cl_intel_subgroups) || defined(cl_khr_subgroups)
memory_scope_sub_group = __OPENCL_MEMORY_SCOPE_SUB_GROUP
#endif
@@ -322,7 +357,9 @@
memory_order_acquire = __ATOMIC_ACQUIRE,
memory_order_release = __ATOMIC_RELEASE,
memory_order_acq_rel = __ATOMIC_ACQ_REL,
+#if defined(__opencl_c_atomic_order_seq_cst)
memory_order_seq_cst = __ATOMIC_SEQ_CST
+#endif
} memory_order;
#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
@@ -445,8 +482,113 @@
#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+/**
+ * OpenCL v1.1/1.2/2.0 s6.2.4.2 - as_type operators
+ * Reinterprets a data type as another data type of the same size
+ */
+#define as_char(x) __builtin_astype((x), char)
+#define as_char2(x) __builtin_astype((x), char2)
+#define as_char3(x) __builtin_astype((x), char3)
+#define as_char4(x) __builtin_astype((x), char4)
+#define as_char8(x) __builtin_astype((x), char8)
+#define as_char16(x) __builtin_astype((x), char16)
+
+#define as_uchar(x) __builtin_astype((x), uchar)
+#define as_uchar2(x) __builtin_astype((x), uchar2)
+#define as_uchar3(x) __builtin_astype((x), uchar3)
+#define as_uchar4(x) __builtin_astype((x), uchar4)
+#define as_uchar8(x) __builtin_astype((x), uchar8)
+#define as_uchar16(x) __builtin_astype((x), uchar16)
+
+#define as_short(x) __builtin_astype((x), short)
+#define as_short2(x) __builtin_astype((x), short2)
+#define as_short3(x) __builtin_astype((x), short3)
+#define as_short4(x) __builtin_astype((x), short4)
+#define as_short8(x) __builtin_astype((x), short8)
+#define as_short16(x) __builtin_astype((x), short16)
+
+#define as_ushort(x) __builtin_astype((x), ushort)
+#define as_ushort2(x) __builtin_astype((x), ushort2)
+#define as_ushort3(x) __builtin_astype((x), ushort3)
+#define as_ushort4(x) __builtin_astype((x), ushort4)
+#define as_ushort8(x) __builtin_astype((x), ushort8)
+#define as_ushort16(x) __builtin_astype((x), ushort16)
+
+#define as_int(x) __builtin_astype((x), int)
+#define as_int2(x) __builtin_astype((x), int2)
+#define as_int3(x) __builtin_astype((x), int3)
+#define as_int4(x) __builtin_astype((x), int4)
+#define as_int8(x) __builtin_astype((x), int8)
+#define as_int16(x) __builtin_astype((x), int16)
+
+#define as_uint(x) __builtin_astype((x), uint)
+#define as_uint2(x) __builtin_astype((x), uint2)
+#define as_uint3(x) __builtin_astype((x), uint3)
+#define as_uint4(x) __builtin_astype((x), uint4)
+#define as_uint8(x) __builtin_astype((x), uint8)
+#define as_uint16(x) __builtin_astype((x), uint16)
+
+#define as_long(x) __builtin_astype((x), long)
+#define as_long2(x) __builtin_astype((x), long2)
+#define as_long3(x) __builtin_astype((x), long3)
+#define as_long4(x) __builtin_astype((x), long4)
+#define as_long8(x) __builtin_astype((x), long8)
+#define as_long16(x) __builtin_astype((x), long16)
+
+#define as_ulong(x) __builtin_astype((x), ulong)
+#define as_ulong2(x) __builtin_astype((x), ulong2)
+#define as_ulong3(x) __builtin_astype((x), ulong3)
+#define as_ulong4(x) __builtin_astype((x), ulong4)
+#define as_ulong8(x) __builtin_astype((x), ulong8)
+#define as_ulong16(x) __builtin_astype((x), ulong16)
+
+#define as_float(x) __builtin_astype((x), float)
+#define as_float2(x) __builtin_astype((x), float2)
+#define as_float3(x) __builtin_astype((x), float3)
+#define as_float4(x) __builtin_astype((x), float4)
+#define as_float8(x) __builtin_astype((x), float8)
+#define as_float16(x) __builtin_astype((x), float16)
+
+#ifdef cl_khr_fp64
+#define as_double(x) __builtin_astype((x), double)
+#define as_double2(x) __builtin_astype((x), double2)
+#define as_double3(x) __builtin_astype((x), double3)
+#define as_double4(x) __builtin_astype((x), double4)
+#define as_double8(x) __builtin_astype((x), double8)
+#define as_double16(x) __builtin_astype((x), double16)
+#endif // cl_khr_fp64
+
+#ifdef cl_khr_fp16
+#define as_half(x) __builtin_astype((x), half)
+#define as_half2(x) __builtin_astype((x), half2)
+#define as_half3(x) __builtin_astype((x), half3)
+#define as_half4(x) __builtin_astype((x), half4)
+#define as_half8(x) __builtin_astype((x), half8)
+#define as_half16(x) __builtin_astype((x), half16)
+#endif // cl_khr_fp16
+
+#define as_size_t(x) __builtin_astype((x), size_t)
+#define as_ptrdiff_t(x) __builtin_astype((x), ptrdiff_t)
+#define as_intptr_t(x) __builtin_astype((x), intptr_t)
+#define as_uintptr_t(x) __builtin_astype((x), uintptr_t)
+
+// OpenCL v1.1 s6.9, v1.2/2.0 s6.10 - Function qualifiers
+
+#define __kernel_exec(X, typen) __kernel \
+ __attribute__((work_group_size_hint(X, 1, 1))) \
+ __attribute__((vec_type_hint(typen)))
+
+#define kernel_exec(X, typen) __kernel \
+ __attribute__((work_group_size_hint(X, 1, 1))) \
+ __attribute__((vec_type_hint(typen)))
+
+#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
+// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
+
+int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
+#endif
+
#ifdef cl_intel_device_side_avc_motion_estimation
-#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : begin
#define CLK_AVC_ME_MAJOR_16x16_INTEL 0x0
#define CLK_AVC_ME_MAJOR_16x8_INTEL 0x1
@@ -580,7 +722,6 @@
#define CLK_AVC_IME_RESULT_DUAL_REFERENCE_STREAMOUT_INITIALIZE_INTEL 0x0
#define CLK_AVC_IME_RESULT_DUAL_REFERENCE_STREAMIN_INITIALIZE_INTEL 0x0
-#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : end
#endif // cl_intel_device_side_avc_motion_estimation
// Disable any extensions we may have enabled previously.
diff --git a/src/llvm-project/clang/lib/Headers/opencl-c.h b/src/llvm-project/clang/lib/Headers/opencl-c.h
index ab66562..fc50dd7 100644
--- a/src/llvm-project/clang/lib/Headers/opencl-c.h
+++ b/src/llvm-project/clang/lib/Headers/opencl-c.h
@@ -23,10 +23,11 @@
#endif //cl_khr_3d_image_writes
#endif //__OPENCL_C_VERSION__ < CL_VERSION_2_0
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
+
+#if (defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)) && defined(__SPIR__)
#pragma OPENCL EXTENSION cl_intel_planar_yuv : begin
#pragma OPENCL EXTENSION cl_intel_planar_yuv : end
-#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
+#endif // (defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)) && defined(__SPIR__)
#define __ovld __attribute__((overloadable))
#define __conv __attribute__((convergent))
@@ -6339,101 +6340,6 @@
#endif // cl_khr_fp16
-/**
- * OpenCL v1.1/1.2/2.0 s6.2.4.2 - as_type operators
- * Reinterprets a data type as another data type of the same size
- */
-#define as_char(x) __builtin_astype((x), char)
-#define as_char2(x) __builtin_astype((x), char2)
-#define as_char3(x) __builtin_astype((x), char3)
-#define as_char4(x) __builtin_astype((x), char4)
-#define as_char8(x) __builtin_astype((x), char8)
-#define as_char16(x) __builtin_astype((x), char16)
-
-#define as_uchar(x) __builtin_astype((x), uchar)
-#define as_uchar2(x) __builtin_astype((x), uchar2)
-#define as_uchar3(x) __builtin_astype((x), uchar3)
-#define as_uchar4(x) __builtin_astype((x), uchar4)
-#define as_uchar8(x) __builtin_astype((x), uchar8)
-#define as_uchar16(x) __builtin_astype((x), uchar16)
-
-#define as_short(x) __builtin_astype((x), short)
-#define as_short2(x) __builtin_astype((x), short2)
-#define as_short3(x) __builtin_astype((x), short3)
-#define as_short4(x) __builtin_astype((x), short4)
-#define as_short8(x) __builtin_astype((x), short8)
-#define as_short16(x) __builtin_astype((x), short16)
-
-#define as_ushort(x) __builtin_astype((x), ushort)
-#define as_ushort2(x) __builtin_astype((x), ushort2)
-#define as_ushort3(x) __builtin_astype((x), ushort3)
-#define as_ushort4(x) __builtin_astype((x), ushort4)
-#define as_ushort8(x) __builtin_astype((x), ushort8)
-#define as_ushort16(x) __builtin_astype((x), ushort16)
-
-#define as_int(x) __builtin_astype((x), int)
-#define as_int2(x) __builtin_astype((x), int2)
-#define as_int3(x) __builtin_astype((x), int3)
-#define as_int4(x) __builtin_astype((x), int4)
-#define as_int8(x) __builtin_astype((x), int8)
-#define as_int16(x) __builtin_astype((x), int16)
-
-#define as_uint(x) __builtin_astype((x), uint)
-#define as_uint2(x) __builtin_astype((x), uint2)
-#define as_uint3(x) __builtin_astype((x), uint3)
-#define as_uint4(x) __builtin_astype((x), uint4)
-#define as_uint8(x) __builtin_astype((x), uint8)
-#define as_uint16(x) __builtin_astype((x), uint16)
-
-#define as_long(x) __builtin_astype((x), long)
-#define as_long2(x) __builtin_astype((x), long2)
-#define as_long3(x) __builtin_astype((x), long3)
-#define as_long4(x) __builtin_astype((x), long4)
-#define as_long8(x) __builtin_astype((x), long8)
-#define as_long16(x) __builtin_astype((x), long16)
-
-#define as_ulong(x) __builtin_astype((x), ulong)
-#define as_ulong2(x) __builtin_astype((x), ulong2)
-#define as_ulong3(x) __builtin_astype((x), ulong3)
-#define as_ulong4(x) __builtin_astype((x), ulong4)
-#define as_ulong8(x) __builtin_astype((x), ulong8)
-#define as_ulong16(x) __builtin_astype((x), ulong16)
-
-#define as_float(x) __builtin_astype((x), float)
-#define as_float2(x) __builtin_astype((x), float2)
-#define as_float3(x) __builtin_astype((x), float3)
-#define as_float4(x) __builtin_astype((x), float4)
-#define as_float8(x) __builtin_astype((x), float8)
-#define as_float16(x) __builtin_astype((x), float16)
-
-#ifdef cl_khr_fp64
-#define as_double(x) __builtin_astype((x), double)
-#define as_double2(x) __builtin_astype((x), double2)
-#define as_double3(x) __builtin_astype((x), double3)
-#define as_double4(x) __builtin_astype((x), double4)
-#define as_double8(x) __builtin_astype((x), double8)
-#define as_double16(x) __builtin_astype((x), double16)
-#endif //cl_khr_fp64
-
-#ifdef cl_khr_fp16
-#define as_half(x) __builtin_astype((x), half)
-#define as_half2(x) __builtin_astype((x), half2)
-#define as_half3(x) __builtin_astype((x), half3)
-#define as_half4(x) __builtin_astype((x), half4)
-#define as_half8(x) __builtin_astype((x), half8)
-#define as_half16(x) __builtin_astype((x), half16)
-#endif //cl_khr_fp16
-
-// OpenCL v1.1 s6.9, v1.2/2.0 s6.10 - Function qualifiers
-
-#define __kernel_exec(X, typen) __kernel \
- __attribute__((work_group_size_hint(X, 1, 1))) \
- __attribute__((vec_type_hint(typen)))
-
-#define kernel_exec(X, typen) __kernel \
- __attribute__((work_group_size_hint(X, 1, 1))) \
- __attribute__((vec_type_hint(typen)))
-
// OpenCL v1.1 s6.11.1, v1.2 s6.12.1, v2.0 s6.13.1 - Work-item Functions
/**
@@ -6494,8 +6400,7 @@
* Returns the number of work-groups that will execute a
* kernel for dimension identified by dimindx.
* Valid values of dimindx are 0 to get_work_dim() - 1.
- * For other values of dimindx, get_num_groups () returns
- * 1.
+ * For other values of dimindx, get_num_groups() returns 1.
* For clEnqueueTask, this always returns 1.
*/
size_t __ovld __cnfn get_num_groups(uint dimindx);
@@ -7354,7 +7259,7 @@
* Returns fmin(x - floor (x), 0x1.fffffep-1f ).
* floor(x) is returned in iptr.
*/
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float __ovld fract(float x, float *iptr);
float2 __ovld fract(float2 x, float2 *iptr);
float3 __ovld fract(float3 x, float3 *iptr);
@@ -7436,7 +7341,7 @@
half8 __ovld fract(half8 x, __private half8 *iptr);
half16 __ovld fract(half16 x, __private half16 *iptr);
#endif //cl_khr_fp16
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* Extract mantissa and exponent from x. For each
@@ -7444,7 +7349,7 @@
* magnitude in the interval [1/2, 1) or 0. Each
* component of x equals mantissa returned * 2^exp.
*/
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float __ovld frexp(float x, int *exp);
float2 __ovld frexp(float2 x, int2 *exp);
float3 __ovld frexp(float3 x, int3 *exp);
@@ -7526,7 +7431,7 @@
half8 __ovld frexp(half8 x, __private int8 *exp);
half16 __ovld frexp(half16 x, __private int16 *exp);
#endif //cl_khr_fp16
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* Compute the value of the square root of x^2 + y^2
@@ -7651,7 +7556,7 @@
half16 __ovld __cnfn lgamma(half16 x);
#endif //cl_khr_fp16
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float __ovld lgamma_r(float x, int *signp);
float2 __ovld lgamma_r(float2 x, int2 *signp);
float3 __ovld lgamma_r(float3 x, int3 *signp);
@@ -7733,7 +7638,7 @@
half8 __ovld lgamma_r(half8 x, __private int8 *signp);
half16 __ovld lgamma_r(half16 x, __private int16 *signp);
#endif //cl_khr_fp16
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* Compute natural logarithm.
@@ -7957,7 +7862,7 @@
* the argument. It stores the integral part in the object
* pointed to by iptr.
*/
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float __ovld modf(float x, float *iptr);
float2 __ovld modf(float2 x, float2 *iptr);
float3 __ovld modf(float3 x, float3 *iptr);
@@ -8039,7 +7944,7 @@
half8 __ovld modf(half8 x, __private half8 *iptr);
half16 __ovld modf(half16 x, __private half16 *iptr);
#endif //cl_khr_fp16
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* Returns a quiet NaN. The nancode may be placed
@@ -8217,7 +8122,7 @@
* sign as x/y. It stores this signed value in the object
* pointed to by quo.
*/
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float __ovld remquo(float x, float y, int *quo);
float2 __ovld remquo(float2 x, float2 y, int2 *quo);
float3 __ovld remquo(float3 x, float3 y, int3 *quo);
@@ -8300,7 +8205,7 @@
half8 __ovld remquo(half8 x, half8 y, __private int8 *quo);
half16 __ovld remquo(half16 x, half16 y, __private int16 *quo);
#endif //cl_khr_fp16
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* Round to integral value (using round to nearest
* even rounding mode) in floating-point format.
@@ -8441,7 +8346,7 @@
* is the return value and computed cosine is returned
* in cosval.
*/
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float __ovld sincos(float x, float *cosval);
float2 __ovld sincos(float2 x, float2 *cosval);
float3 __ovld sincos(float3 x, float3 *cosval);
@@ -8523,7 +8428,7 @@
half8 __ovld sincos(half8 x, __private half8 *cosval);
half16 __ovld sincos(half16 x, __private half16 *cosval);
#endif //cl_khr_fp16
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* Compute hyperbolic sine.
@@ -9449,54 +9354,54 @@
* component type of x, if x is a vector.
*/
#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
-char __ovld ctz(char x);
-uchar __ovld ctz(uchar x);
-char2 __ovld ctz(char2 x);
-uchar2 __ovld ctz(uchar2 x);
-char3 __ovld ctz(char3 x);
-uchar3 __ovld ctz(uchar3 x);
-char4 __ovld ctz(char4 x);
-uchar4 __ovld ctz(uchar4 x);
-char8 __ovld ctz(char8 x);
-uchar8 __ovld ctz(uchar8 x);
-char16 __ovld ctz(char16 x);
-uchar16 __ovld ctz(uchar16 x);
-short __ovld ctz(short x);
-ushort __ovld ctz(ushort x);
-short2 __ovld ctz(short2 x);
-ushort2 __ovld ctz(ushort2 x);
-short3 __ovld ctz(short3 x);
-ushort3 __ovld ctz(ushort3 x);
-short4 __ovld ctz(short4 x);
-ushort4 __ovld ctz(ushort4 x);
-short8 __ovld ctz(short8 x);
-ushort8 __ovld ctz(ushort8 x);
-short16 __ovld ctz(short16 x);
-ushort16 __ovld ctz(ushort16 x);
-int __ovld ctz(int x);
-uint __ovld ctz(uint x);
-int2 __ovld ctz(int2 x);
-uint2 __ovld ctz(uint2 x);
-int3 __ovld ctz(int3 x);
-uint3 __ovld ctz(uint3 x);
-int4 __ovld ctz(int4 x);
-uint4 __ovld ctz(uint4 x);
-int8 __ovld ctz(int8 x);
-uint8 __ovld ctz(uint8 x);
-int16 __ovld ctz(int16 x);
-uint16 __ovld ctz(uint16 x);
-long __ovld ctz(long x);
-ulong __ovld ctz(ulong x);
-long2 __ovld ctz(long2 x);
-ulong2 __ovld ctz(ulong2 x);
-long3 __ovld ctz(long3 x);
-ulong3 __ovld ctz(ulong3 x);
-long4 __ovld ctz(long4 x);
-ulong4 __ovld ctz(ulong4 x);
-long8 __ovld ctz(long8 x);
-ulong8 __ovld ctz(ulong8 x);
-long16 __ovld ctz(long16 x);
-ulong16 __ovld ctz(ulong16 x);
+char __ovld __cnfn ctz(char x);
+uchar __ovld __cnfn ctz(uchar x);
+char2 __ovld __cnfn ctz(char2 x);
+uchar2 __ovld __cnfn ctz(uchar2 x);
+char3 __ovld __cnfn ctz(char3 x);
+uchar3 __ovld __cnfn ctz(uchar3 x);
+char4 __ovld __cnfn ctz(char4 x);
+uchar4 __ovld __cnfn ctz(uchar4 x);
+char8 __ovld __cnfn ctz(char8 x);
+uchar8 __ovld __cnfn ctz(uchar8 x);
+char16 __ovld __cnfn ctz(char16 x);
+uchar16 __ovld __cnfn ctz(uchar16 x);
+short __ovld __cnfn ctz(short x);
+ushort __ovld __cnfn ctz(ushort x);
+short2 __ovld __cnfn ctz(short2 x);
+ushort2 __ovld __cnfn ctz(ushort2 x);
+short3 __ovld __cnfn ctz(short3 x);
+ushort3 __ovld __cnfn ctz(ushort3 x);
+short4 __ovld __cnfn ctz(short4 x);
+ushort4 __ovld __cnfn ctz(ushort4 x);
+short8 __ovld __cnfn ctz(short8 x);
+ushort8 __ovld __cnfn ctz(ushort8 x);
+short16 __ovld __cnfn ctz(short16 x);
+ushort16 __ovld __cnfn ctz(ushort16 x);
+int __ovld __cnfn ctz(int x);
+uint __ovld __cnfn ctz(uint x);
+int2 __ovld __cnfn ctz(int2 x);
+uint2 __ovld __cnfn ctz(uint2 x);
+int3 __ovld __cnfn ctz(int3 x);
+uint3 __ovld __cnfn ctz(uint3 x);
+int4 __ovld __cnfn ctz(int4 x);
+uint4 __ovld __cnfn ctz(uint4 x);
+int8 __ovld __cnfn ctz(int8 x);
+uint8 __ovld __cnfn ctz(uint8 x);
+int16 __ovld __cnfn ctz(int16 x);
+uint16 __ovld __cnfn ctz(uint16 x);
+long __ovld __cnfn ctz(long x);
+ulong __ovld __cnfn ctz(ulong x);
+long2 __ovld __cnfn ctz(long2 x);
+ulong2 __ovld __cnfn ctz(ulong2 x);
+long3 __ovld __cnfn ctz(long3 x);
+ulong3 __ovld __cnfn ctz(ulong3 x);
+long4 __ovld __cnfn ctz(long4 x);
+ulong4 __ovld __cnfn ctz(ulong4 x);
+long8 __ovld __cnfn ctz(long8 x);
+ulong8 __ovld __cnfn ctz(ulong8 x);
+long16 __ovld __cnfn ctz(long16 x);
+ulong16 __ovld __cnfn ctz(ulong16 x);
#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
/**
@@ -10002,6 +9907,7 @@
/*
* popcount(x): returns the number of set bit in x
*/
+#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
char __ovld __cnfn popcount(char x);
uchar __ovld __cnfn popcount(uchar x);
char2 __ovld __cnfn popcount(char2 x);
@@ -10050,6 +9956,7 @@
ulong8 __ovld __cnfn popcount(ulong8 x);
long16 __ovld __cnfn popcount(long16 x);
ulong16 __ovld __cnfn popcount(ulong16 x);
+#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
/**
* Multiply two 24-bit integer values x and y and add
@@ -11342,7 +11249,7 @@
half16 __ovld vload16(size_t offset, const __constant half *p);
#endif //cl_khr_fp16
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
char2 __ovld vload2(size_t offset, const char *p);
uchar2 __ovld vload2(size_t offset, const uchar *p);
short2 __ovld vload2(size_t offset, const short *p);
@@ -11580,9 +11487,9 @@
half8 __ovld vload8(size_t offset, const __private half *p);
half16 __ovld vload16(size_t offset, const __private half *p);
#endif //cl_khr_fp16
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
void __ovld vstore2(char2 data, size_t offset, char *p);
void __ovld vstore2(uchar2 data, size_t offset, uchar *p);
void __ovld vstore2(short2 data, size_t offset, short *p);
@@ -11816,7 +11723,7 @@
void __ovld vstore8(half8 data, size_t offset, __private half *p);
void __ovld vstore16(half16 data, size_t offset, __private half *p);
#endif //cl_khr_fp16
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* Read sizeof (half) bytes of data from address
@@ -11827,13 +11734,13 @@
* must be 16-bit aligned.
*/
float __ovld vload_half(size_t offset, const __constant half *p);
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float __ovld vload_half(size_t offset, const half *p);
#else
float __ovld vload_half(size_t offset, const __global half *p);
float __ovld vload_half(size_t offset, const __local half *p);
float __ovld vload_half(size_t offset, const __private half *p);
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* Read sizeof (halfn) bytes of data from address
@@ -11848,7 +11755,7 @@
float4 __ovld vload_half4(size_t offset, const __constant half *p);
float8 __ovld vload_half8(size_t offset, const __constant half *p);
float16 __ovld vload_half16(size_t offset, const __constant half *p);
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float2 __ovld vload_half2(size_t offset, const half *p);
float3 __ovld vload_half3(size_t offset, const half *p);
float4 __ovld vload_half4(size_t offset, const half *p);
@@ -11870,7 +11777,7 @@
float4 __ovld vload_half4(size_t offset, const __private half *p);
float8 __ovld vload_half8(size_t offset, const __private half *p);
float16 __ovld vload_half16(size_t offset, const __private half *p);
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* The float value given by data is first
@@ -11883,7 +11790,7 @@
* The default current rounding mode is round to
* nearest even.
*/
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
void __ovld vstore_half(float data, size_t offset, half *p);
void __ovld vstore_half_rte(float data, size_t offset, half *p);
void __ovld vstore_half_rtz(float data, size_t offset, half *p);
@@ -11929,7 +11836,7 @@
void __ovld vstore_half_rtp(double data, size_t offset, __private half *p);
void __ovld vstore_half_rtn(double data, size_t offset, __private half *p);
#endif //cl_khr_fp64
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* The floatn value given by data is converted to
@@ -11942,7 +11849,7 @@
* The default current rounding mode is round to
* nearest even.
*/
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
void __ovld vstore_half2(float2 data, size_t offset, half *p);
void __ovld vstore_half3(float3 data, size_t offset, half *p);
void __ovld vstore_half4(float4 data, size_t offset, half *p);
@@ -12148,7 +12055,7 @@
void __ovld vstore_half8_rtn(double8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rtn(double16 data, size_t offset, __private half *p);
#endif //cl_khr_fp64
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* For n = 1, 2, 4, 8 and 16 read sizeof (halfn)
@@ -12169,7 +12076,7 @@
float4 __ovld vloada_half4(size_t offset, const __constant half *p);
float8 __ovld vloada_half8(size_t offset, const __constant half *p);
float16 __ovld vloada_half16(size_t offset, const __constant half *p);
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
float __ovld vloada_half(size_t offset, const half *p);
float2 __ovld vloada_half2(size_t offset, const half *p);
float3 __ovld vloada_half3(size_t offset, const half *p);
@@ -12195,7 +12102,7 @@
float4 __ovld vloada_half4(size_t offset, const __private half *p);
float8 __ovld vloada_half8(size_t offset, const __private half *p);
float16 __ovld vloada_half16(size_t offset, const __private half *p);
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
/**
* The floatn value given by data is converted to
@@ -12213,7 +12120,7 @@
* mode. The default current rounding mode is
* round to nearest even.
*/
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
void __ovld vstorea_half(float data, size_t offset, half *p);
void __ovld vstorea_half2(float2 data, size_t offset, half *p);
void __ovld vstorea_half3(float3 data, size_t offset, half *p);
@@ -12498,7 +12405,7 @@
void __ovld vstorea_half8_rtn(double8 data,size_t offset, __private half *p);
void __ovld vstorea_half16_rtn(double16 data,size_t offset, __private half *p);
#endif //cl_khr_fp64
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
// OpenCL v1.1 s6.11.8, v1.2 s6.12.8, v2.0 s6.13.8 - Synchronization Functions
@@ -12582,7 +12489,7 @@
// OpenCL v2.0 s6.13.9 - Address Space Qualifier Functions
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#if defined(__opencl_c_generic_address_space)
cl_mem_fence_flags __ovld get_fence(const void *ptr);
cl_mem_fence_flags __ovld get_fence(void *ptr);
@@ -12593,7 +12500,7 @@
* where gentype is builtin type or user defined type.
*/
-#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
+#endif //defined(__opencl_c_generic_address_space)
// OpenCL v1.1 s6.11.10, v1.2 s6.12.10, v2.0 s6.13.10 - Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch
@@ -13397,291 +13304,324 @@
void __ovld atomic_work_item_fence(cl_mem_fence_flags flags, memory_order order, memory_scope scope);
// atomic_fetch()
+// OpenCL v2.0 s6.13.11.7.5:
+// add/sub: atomic type argument can be uintptr_t/intptr_t, value type argument can be ptrdiff_t.
+#if defined(__opencl_c_atomic_order_seq_cst) && defined(__opencl_c_atomic_scope_device)
int __ovld atomic_fetch_add(volatile atomic_int *object, int operand);
-int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order);
-int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_add(volatile atomic_uint *object, uint operand);
-uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order);
-uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_sub(volatile atomic_int *object, int operand);
-int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order);
-int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_sub(volatile atomic_uint *object, uint operand);
-uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order);
-uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_or(volatile atomic_int *object, int operand);
-int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order);
-int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_or(volatile atomic_uint *object, uint operand);
-uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order);
-uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_xor(volatile atomic_int *object, int operand);
-int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order);
-int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_xor(volatile atomic_uint *object, uint operand);
-uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order);
-uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_and(volatile atomic_int *object, int operand);
-int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order);
-int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_and(volatile atomic_uint *object, uint operand);
-uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order);
-uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_min(volatile atomic_int *object, int operand);
-int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order);
-int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_min(volatile atomic_uint *object, uint operand);
-uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order);
-uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_max(volatile atomic_int *object, int operand);
-int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order);
-int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_max(volatile atomic_uint *object, uint operand);
-uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order);
-uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
long __ovld atomic_fetch_add(volatile atomic_long *object, long operand);
-long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order);
-long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_add(volatile atomic_ulong *object, ulong operand);
-ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
-ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_sub(volatile atomic_long *object, long operand);
-long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order);
-long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_sub(volatile atomic_ulong *object, ulong operand);
-ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
-ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_or(volatile atomic_long *object, long operand);
-long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order);
-long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_or(volatile atomic_ulong *object, ulong operand);
-ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
-ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_xor(volatile atomic_long *object, long operand);
-long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order);
-long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_xor(volatile atomic_ulong *object, ulong operand);
-ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
-ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_and(volatile atomic_long *object, long operand);
-long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order);
-long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_and(volatile atomic_ulong *object, ulong operand);
-ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
-ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_min(volatile atomic_long *object, long operand);
-long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order);
-long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_min(volatile atomic_ulong *object, ulong operand);
-ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
-ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_max(volatile atomic_long *object, long operand);
-long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order);
-long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_max(volatile atomic_ulong *object, ulong operand);
+uintptr_t __ovld atomic_fetch_add(volatile atomic_uintptr_t *object, ptrdiff_t operand);
+uintptr_t __ovld atomic_fetch_sub(volatile atomic_uintptr_t *object, ptrdiff_t operand);
+#endif //defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#endif
+
+#if defined(__opencl_c_atomic_scope_device)
+int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order);
+uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order);
+int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order);
+uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order);
+int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order);
+uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order);
+int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order);
+uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order);
+int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order);
+uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order);
+int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order);
+uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order);
+int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order);
+uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order);
+ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
+long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order);
+ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
+long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order);
+ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
+long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order);
+ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
+long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order);
+ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
+long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order);
+ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
+long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order);
ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
+uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order);
+uintptr_t __ovld atomic_fetch_sub_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order);
+#endif //defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#endif
+
+int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
+uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
+int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
+uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
+int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
+uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
+int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
+uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
+int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
+uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
+int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
+uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
+int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
+uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
+ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
+long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
+ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
+long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
+ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
+long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
+ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
+long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
+ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
+long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
+ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
+long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
#endif //defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
-
-// OpenCL v2.0 s6.13.11.7.5:
-// add/sub: atomic type argument can be uintptr_t/intptr_t, value type argument can be ptrdiff_t.
-// or/xor/and/min/max: atomic type argument can be intptr_t/uintptr_t, value type argument can be intptr_t/uintptr_t.
-
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
-uintptr_t __ovld atomic_fetch_add(volatile atomic_uintptr_t *object, ptrdiff_t operand);
-uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order);
uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order, memory_scope scope);
-uintptr_t __ovld atomic_fetch_sub(volatile atomic_uintptr_t *object, ptrdiff_t operand);
-uintptr_t __ovld atomic_fetch_sub_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order);
uintptr_t __ovld atomic_fetch_sub_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order, memory_scope scope);
-
-uintptr_t __ovld atomic_fetch_or(volatile atomic_uintptr_t *object, intptr_t operand);
-uintptr_t __ovld atomic_fetch_or_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order);
-uintptr_t __ovld atomic_fetch_or_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order, memory_scope scope);
-uintptr_t __ovld atomic_fetch_xor(volatile atomic_uintptr_t *object, intptr_t operand);
-uintptr_t __ovld atomic_fetch_xor_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order);
-uintptr_t __ovld atomic_fetch_xor_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order, memory_scope scope);
-uintptr_t __ovld atomic_fetch_and(volatile atomic_uintptr_t *object, intptr_t operand);
-uintptr_t __ovld atomic_fetch_and_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order);
-uintptr_t __ovld atomic_fetch_and_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order, memory_scope scope);
-uintptr_t __ovld atomic_fetch_min(volatile atomic_uintptr_t *object, intptr_t opermax);
-uintptr_t __ovld atomic_fetch_min_explicit(volatile atomic_uintptr_t *object, intptr_t opermax, memory_order minder);
-uintptr_t __ovld atomic_fetch_min_explicit(volatile atomic_uintptr_t *object, intptr_t opermax, memory_order minder, memory_scope scope);
-uintptr_t __ovld atomic_fetch_max(volatile atomic_uintptr_t *object, intptr_t opermax);
-uintptr_t __ovld atomic_fetch_max_explicit(volatile atomic_uintptr_t *object, intptr_t opermax, memory_order minder);
-uintptr_t __ovld atomic_fetch_max_explicit(volatile atomic_uintptr_t *object, intptr_t opermax, memory_order minder, memory_scope scope);
-
-intptr_t __ovld atomic_fetch_or(volatile atomic_intptr_t *object, uintptr_t operand);
-intptr_t __ovld atomic_fetch_or_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order);
-intptr_t __ovld atomic_fetch_or_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order, memory_scope scope);
-intptr_t __ovld atomic_fetch_xor(volatile atomic_intptr_t *object, uintptr_t operand);
-intptr_t __ovld atomic_fetch_xor_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order);
-intptr_t __ovld atomic_fetch_xor_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order, memory_scope scope);
-intptr_t __ovld atomic_fetch_and(volatile atomic_intptr_t *object, uintptr_t operand);
-intptr_t __ovld atomic_fetch_and_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order);
-intptr_t __ovld atomic_fetch_and_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order, memory_scope scope);
-intptr_t __ovld atomic_fetch_min(volatile atomic_intptr_t *object, uintptr_t opermax);
-intptr_t __ovld atomic_fetch_min_explicit(volatile atomic_intptr_t *object, uintptr_t opermax, memory_order minder);
-intptr_t __ovld atomic_fetch_min_explicit(volatile atomic_intptr_t *object, uintptr_t opermax, memory_order minder, memory_scope scope);
-intptr_t __ovld atomic_fetch_max(volatile atomic_intptr_t *object, uintptr_t opermax);
-intptr_t __ovld atomic_fetch_max_explicit(volatile atomic_intptr_t *object, uintptr_t opermax, memory_order minder);
-intptr_t __ovld atomic_fetch_max_explicit(volatile atomic_intptr_t *object, uintptr_t opermax, memory_order minder, memory_scope scope);
#endif
// atomic_store()
+#if defined(__opencl_c_atomic_order_seq_cst) && defined(__opencl_c_atomic_scope_device)
void __ovld atomic_store(volatile atomic_int *object, int desired);
-void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order);
-void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope);
void __ovld atomic_store(volatile atomic_uint *object, uint desired);
-void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order);
-void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope);
void __ovld atomic_store(volatile atomic_float *object, float desired);
-void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order);
-void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope);
+
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#ifdef cl_khr_fp64
void __ovld atomic_store(volatile atomic_double *object, double desired);
-void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order);
-void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope);
#endif //cl_khr_fp64
void __ovld atomic_store(volatile atomic_long *object, long desired);
-void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order);
-void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope);
void __ovld atomic_store(volatile atomic_ulong *object, ulong desired);
+#endif
+#endif
+
+#if defined(__opencl_c_atomic_scope_device)
+void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order);
+void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order);
+void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#ifdef cl_khr_fp64
+void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order);
+#endif //cl_khr_fp64
+void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order);
void __ovld atomic_store_explicit(volatile atomic_ulong *object, ulong desired, memory_order order);
+#endif
+#endif
+
+void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope);
+void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope);
+void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#ifdef cl_khr_fp64
+void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope);
+#endif //cl_khr_fp64
+void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope);
void __ovld atomic_store_explicit(volatile atomic_ulong *object, ulong desired, memory_order order, memory_scope scope);
#endif
// atomic_load()
-
+#if defined(__opencl_c_atomic_order_seq_cst) && defined(__opencl_c_atomic_scope_device)
int __ovld atomic_load(volatile atomic_int *object);
-int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order);
-int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order, memory_scope scope);
uint __ovld atomic_load(volatile atomic_uint *object);
-uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order);
-uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order, memory_scope scope);
float __ovld atomic_load(volatile atomic_float *object);
-float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order);
-float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#ifdef cl_khr_fp64
double __ovld atomic_load(volatile atomic_double *object);
-double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order);
-double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order, memory_scope scope);
#endif //cl_khr_fp64
long __ovld atomic_load(volatile atomic_long *object);
-long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order);
-long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order, memory_scope scope);
ulong __ovld atomic_load(volatile atomic_ulong *object);
+#endif
+#endif
+
+#if defined(__opencl_c_atomic_scope_device)
+int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order);
+uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order);
+float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#ifdef cl_khr_fp64
+double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order);
+#endif //cl_khr_fp64
+long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order);
ulong __ovld atomic_load_explicit(volatile atomic_ulong *object, memory_order order);
+#endif
+#endif
+
+int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order, memory_scope scope);
+uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order, memory_scope scope);
+float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order, memory_scope scope);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#ifdef cl_khr_fp64
+double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order, memory_scope scope);
+#endif //cl_khr_fp64
+long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order, memory_scope scope);
ulong __ovld atomic_load_explicit(volatile atomic_ulong *object, memory_order order, memory_scope scope);
#endif
// atomic_exchange()
+#if defined(__opencl_c_atomic_order_seq_cst) && defined(__opencl_c_atomic_scope_device)
int __ovld atomic_exchange(volatile atomic_int *object, int desired);
-int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order);
-int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope);
uint __ovld atomic_exchange(volatile atomic_uint *object, uint desired);
-uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order);
-uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope);
float __ovld atomic_exchange(volatile atomic_float *object, float desired);
-float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order);
-float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#ifdef cl_khr_fp64
double __ovld atomic_exchange(volatile atomic_double *object, double desired);
-double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order);
-double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope);
#endif //cl_khr_fp64
long __ovld atomic_exchange(volatile atomic_long *object, long desired);
-long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order);
-long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope);
ulong __ovld atomic_exchange(volatile atomic_ulong *object, ulong desired);
+#endif
+#endif
+
+#if defined(__opencl_c_atomic_scope_device)
+int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order);
+uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order);
+float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#ifdef cl_khr_fp64
+double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order);
+#endif //cl_khr_fp64
+long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order);
ulong __ovld atomic_exchange_explicit(volatile atomic_ulong *object, ulong desired, memory_order order);
+#endif
+#endif
+
+int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope);
+uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope);
+float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#ifdef cl_khr_fp64
+double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope);
+#endif //cl_khr_fp64
+long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope);
ulong __ovld atomic_exchange_explicit(volatile atomic_ulong *object, ulong desired, memory_order order, memory_scope scope);
#endif
// atomic_compare_exchange_strong() and atomic_compare_exchange_weak()
-
+#if defined(__opencl_c_atomic_order_seq_cst) && defined(__opencl_c_atomic_scope_device)
bool __ovld atomic_compare_exchange_strong(volatile atomic_int *object, int *expected, int desired);
-bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected,
- int desired, memory_order success, memory_order failure);
-bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected,
- int desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_strong(volatile atomic_uint *object, uint *expected, uint desired);
+bool __ovld atomic_compare_exchange_weak(volatile atomic_int *object, int *expected, int desired);
+bool __ovld atomic_compare_exchange_weak(volatile atomic_uint *object, uint *expected, uint desired);
+bool __ovld atomic_compare_exchange_strong(volatile atomic_float *object, float *expected, float desired);
+bool __ovld atomic_compare_exchange_weak(volatile atomic_float *object, float *expected, float desired);
+
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#ifdef cl_khr_fp64
+bool __ovld atomic_compare_exchange_strong(volatile atomic_double *object, double *expected, double desired);
+bool __ovld atomic_compare_exchange_weak(volatile atomic_double *object, double *expected, double desired);
+#endif //cl_khr_fp64
+bool __ovld atomic_compare_exchange_strong(volatile atomic_long *object, long *expected, long desired);
+bool __ovld atomic_compare_exchange_weak(volatile atomic_long *object, long *expected, long desired);
+bool __ovld atomic_compare_exchange_strong(volatile atomic_ulong *object, ulong *expected, ulong desired);
+bool __ovld atomic_compare_exchange_weak(volatile atomic_ulong *object, ulong *expected, ulong desired);
+#endif
+#endif
+
+bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected,
+ int desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_uint *object, uint *expected,
uint desired, memory_order success, memory_order failure);
-bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_uint *object, uint *expected,
- uint desired, memory_order success, memory_order failure, memory_scope scope);
-bool __ovld atomic_compare_exchange_weak(volatile atomic_int *object, int *expected, int desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_int *object, int *expected,
int desired, memory_order success, memory_order failure);
-bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_int *object, int *expected,
- int desired, memory_order success, memory_order failure, memory_scope scope);
-bool __ovld atomic_compare_exchange_weak(volatile atomic_uint *object, uint *expected, uint desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_uint *object, uint *expected,
uint desired, memory_order success, memory_order failure);
-bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_uint *object, uint *expected,
- uint desired, memory_order success, memory_order failure, memory_scope scope);
-bool __ovld atomic_compare_exchange_strong(volatile atomic_float *object, float *expected, float desired);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_float *object, float *expected,
float desired, memory_order success, memory_order failure);
-bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_float *object, float *expected,
- float desired, memory_order success, memory_order failure, memory_scope scope);
-bool __ovld atomic_compare_exchange_weak(volatile atomic_float *object, float *expected, float desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_float *object, float *expected,
float desired, memory_order success, memory_order failure);
+#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
+#ifdef cl_khr_fp64
+bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_double *object, double *expected,
+ double desired, memory_order success, memory_order failure);
+bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_double *object, double *expected,
+ double desired, memory_order success, memory_order failure);
+#endif //cl_khr_fp64
+bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_long *object, long *expected,
+ long desired, memory_order success, memory_order failure);
+bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_long *object, long *expected,
+ long desired, memory_order success, memory_order failure);
+bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_ulong *object, ulong *expected,
+ ulong desired, memory_order success, memory_order failure);
+bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_ulong *object, ulong *expected,
+ ulong desired, memory_order success, memory_order failure);
+#endif
+
+bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected,
+ int desired, memory_order success, memory_order failure, memory_scope scope);
+bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_uint *object, uint *expected,
+ uint desired, memory_order success, memory_order failure, memory_scope scope);
+bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_int *object, int *expected,
+ int desired, memory_order success, memory_order failure, memory_scope scope);
+bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_uint *object, uint *expected,
+ uint desired, memory_order success, memory_order failure, memory_scope scope);
+bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_float *object, float *expected,
+ float desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_float *object, float *expected,
float desired, memory_order success, memory_order failure, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#ifdef cl_khr_fp64
-bool __ovld atomic_compare_exchange_strong(volatile atomic_double *object, double *expected, double desired);
-bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_double *object, double *expected,
- double desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_double *object, double *expected,
double desired, memory_order success, memory_order failure, memory_scope scope);
-bool __ovld atomic_compare_exchange_weak(volatile atomic_double *object, double *expected, double desired);
-bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_double *object, double *expected,
- double desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_double *object, double *expected,
double desired, memory_order success, memory_order failure, memory_scope scope);
#endif //cl_khr_fp64
-bool __ovld atomic_compare_exchange_strong(volatile atomic_long *object, long *expected, long desired);
-bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_long *object, long *expected,
- long desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_long *object, long *expected,
long desired, memory_order success, memory_order failure, memory_scope scope);
-bool __ovld atomic_compare_exchange_weak(volatile atomic_long *object, long *expected, long desired);
-bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_long *object, long *expected,
- long desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_long *object, long *expected,
long desired, memory_order success, memory_order failure, memory_scope scope);
-bool __ovld atomic_compare_exchange_strong(volatile atomic_ulong *object, ulong *expected, ulong desired);
-bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_ulong *object, ulong *expected,
- ulong desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_ulong *object, ulong *expected,
ulong desired, memory_order success, memory_order failure, memory_scope scope);
-bool __ovld atomic_compare_exchange_weak(volatile atomic_ulong *object, ulong *expected, ulong desired);
-bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_ulong *object, ulong *expected,
- ulong desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_ulong *object, ulong *expected,
ulong desired, memory_order success, memory_order failure, memory_scope scope);
#endif
// atomic_flag_test_and_set() and atomic_flag_clear()
-
+#if defined(__opencl_c_atomic_order_seq_cst) && defined(__opencl_c_atomic_scope_device)
bool __ovld atomic_flag_test_and_set(volatile atomic_flag *object);
-bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order);
-bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope);
void __ovld atomic_flag_clear(volatile atomic_flag *object);
-void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order);
-void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope);
+#endif
+#if defined(__opencl_c_atomic_scope_device)
+bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order);
+void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order);
+#endif
+
+bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope);
+void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope);
#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
// OpenCL v1.1 s6.11.12, v1.2 s6.12.12, v2.0 s6.13.12 - Miscellaneous Vector Functions
@@ -14176,12 +14116,6 @@
half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask);
#endif //cl_khr_fp16
-#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2)
-// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
-
-int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
-#endif
-
// OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions
#ifdef cl_khr_gl_msaa_sharing
@@ -16130,6 +16064,230 @@
#endif // cl_khr_subgroup_clustered_reduce
+#if defined(cl_khr_extended_bit_ops)
+char __ovld __cnfn bitfield_insert(char, char, uint, uint);
+uchar __ovld __cnfn bitfield_insert(uchar, uchar, uint, uint);
+short __ovld __cnfn bitfield_insert(short, short, uint, uint);
+ushort __ovld __cnfn bitfield_insert(ushort, ushort, uint, uint);
+int __ovld __cnfn bitfield_insert(int, int, uint, uint);
+uint __ovld __cnfn bitfield_insert(uint, uint, uint, uint);
+long __ovld __cnfn bitfield_insert(long, long, uint, uint);
+ulong __ovld __cnfn bitfield_insert(ulong, ulong, uint, uint);
+char2 __ovld __cnfn bitfield_insert(char2, char2, uint, uint);
+uchar2 __ovld __cnfn bitfield_insert(uchar2, uchar2, uint, uint);
+short2 __ovld __cnfn bitfield_insert(short2, short2, uint, uint);
+ushort2 __ovld __cnfn bitfield_insert(ushort2, ushort2, uint, uint);
+int2 __ovld __cnfn bitfield_insert(int2, int2, uint, uint);
+uint2 __ovld __cnfn bitfield_insert(uint2, uint2, uint, uint);
+long2 __ovld __cnfn bitfield_insert(long2, long2, uint, uint);
+ulong2 __ovld __cnfn bitfield_insert(ulong2, ulong2, uint, uint);
+char3 __ovld __cnfn bitfield_insert(char3, char3, uint, uint);
+uchar3 __ovld __cnfn bitfield_insert(uchar3, uchar3, uint, uint);
+short3 __ovld __cnfn bitfield_insert(short3, short3, uint, uint);
+ushort3 __ovld __cnfn bitfield_insert(ushort3, ushort3, uint, uint);
+int3 __ovld __cnfn bitfield_insert(int3, int3, uint, uint);
+uint3 __ovld __cnfn bitfield_insert(uint3, uint3, uint, uint);
+long3 __ovld __cnfn bitfield_insert(long3, long3, uint, uint);
+ulong3 __ovld __cnfn bitfield_insert(ulong3, ulong3, uint, uint);
+char4 __ovld __cnfn bitfield_insert(char4, char4, uint, uint);
+uchar4 __ovld __cnfn bitfield_insert(uchar4, uchar4, uint, uint);
+short4 __ovld __cnfn bitfield_insert(short4, short4, uint, uint);
+ushort4 __ovld __cnfn bitfield_insert(ushort4, ushort4, uint, uint);
+int4 __ovld __cnfn bitfield_insert(int4, int4, uint, uint);
+uint4 __ovld __cnfn bitfield_insert(uint4, uint4, uint, uint);
+long4 __ovld __cnfn bitfield_insert(long4, long4, uint, uint);
+ulong4 __ovld __cnfn bitfield_insert(ulong4, ulong4, uint, uint);
+char8 __ovld __cnfn bitfield_insert(char8, char8, uint, uint);
+uchar8 __ovld __cnfn bitfield_insert(uchar8, uchar8, uint, uint);
+short8 __ovld __cnfn bitfield_insert(short8, short8, uint, uint);
+ushort8 __ovld __cnfn bitfield_insert(ushort8, ushort8, uint, uint);
+int8 __ovld __cnfn bitfield_insert(int8, int8, uint, uint);
+uint8 __ovld __cnfn bitfield_insert(uint8, uint8, uint, uint);
+long8 __ovld __cnfn bitfield_insert(long8, long8, uint, uint);
+ulong8 __ovld __cnfn bitfield_insert(ulong8, ulong8, uint, uint);
+char16 __ovld __cnfn bitfield_insert(char16, char16, uint, uint);
+uchar16 __ovld __cnfn bitfield_insert(uchar16, uchar16, uint, uint);
+short16 __ovld __cnfn bitfield_insert(short16, short16, uint, uint);
+ushort16 __ovld __cnfn bitfield_insert(ushort16, ushort16, uint, uint);
+int16 __ovld __cnfn bitfield_insert(int16, int16, uint, uint);
+uint16 __ovld __cnfn bitfield_insert(uint16, uint16, uint, uint);
+long16 __ovld __cnfn bitfield_insert(long16, long16, uint, uint);
+ulong16 __ovld __cnfn bitfield_insert(ulong16, ulong16, uint, uint);
+
+char __ovld __cnfn bitfield_extract_signed(char, uint, uint);
+short __ovld __cnfn bitfield_extract_signed(short, uint, uint);
+int __ovld __cnfn bitfield_extract_signed(int, uint, uint);
+long __ovld __cnfn bitfield_extract_signed(long, uint, uint);
+char2 __ovld __cnfn bitfield_extract_signed(char2, uint, uint);
+short2 __ovld __cnfn bitfield_extract_signed(short2, uint, uint);
+int2 __ovld __cnfn bitfield_extract_signed(int2, uint, uint);
+long2 __ovld __cnfn bitfield_extract_signed(long2, uint, uint);
+char3 __ovld __cnfn bitfield_extract_signed(char3, uint, uint);
+short3 __ovld __cnfn bitfield_extract_signed(short3, uint, uint);
+int3 __ovld __cnfn bitfield_extract_signed(int3, uint, uint);
+long3 __ovld __cnfn bitfield_extract_signed(long3, uint, uint);
+char4 __ovld __cnfn bitfield_extract_signed(char4, uint, uint);
+short4 __ovld __cnfn bitfield_extract_signed(short4, uint, uint);
+int4 __ovld __cnfn bitfield_extract_signed(int4, uint, uint);
+long4 __ovld __cnfn bitfield_extract_signed(long4, uint, uint);
+char8 __ovld __cnfn bitfield_extract_signed(char8, uint, uint);
+short8 __ovld __cnfn bitfield_extract_signed(short8, uint, uint);
+int8 __ovld __cnfn bitfield_extract_signed(int8, uint, uint);
+long8 __ovld __cnfn bitfield_extract_signed(long8, uint, uint);
+char16 __ovld __cnfn bitfield_extract_signed(char16, uint, uint);
+short16 __ovld __cnfn bitfield_extract_signed(short16, uint, uint);
+int16 __ovld __cnfn bitfield_extract_signed(int16, uint, uint);
+long16 __ovld __cnfn bitfield_extract_signed(long16, uint, uint);
+
+char __ovld __cnfn bitfield_extract_signed(uchar, uint, uint);
+short __ovld __cnfn bitfield_extract_signed(ushort, uint, uint);
+int __ovld __cnfn bitfield_extract_signed(uint, uint, uint);
+long __ovld __cnfn bitfield_extract_signed(ulong, uint, uint);
+char2 __ovld __cnfn bitfield_extract_signed(uchar2, uint, uint);
+short2 __ovld __cnfn bitfield_extract_signed(ushort2, uint, uint);
+int2 __ovld __cnfn bitfield_extract_signed(uint2, uint, uint);
+long2 __ovld __cnfn bitfield_extract_signed(ulong2, uint, uint);
+char3 __ovld __cnfn bitfield_extract_signed(uchar3, uint, uint);
+short3 __ovld __cnfn bitfield_extract_signed(ushort3, uint, uint);
+int3 __ovld __cnfn bitfield_extract_signed(uint3, uint, uint);
+long3 __ovld __cnfn bitfield_extract_signed(ulong3, uint, uint);
+char4 __ovld __cnfn bitfield_extract_signed(uchar4, uint, uint);
+short4 __ovld __cnfn bitfield_extract_signed(ushort4, uint, uint);
+int4 __ovld __cnfn bitfield_extract_signed(uint4, uint, uint);
+long4 __ovld __cnfn bitfield_extract_signed(ulong4, uint, uint);
+char8 __ovld __cnfn bitfield_extract_signed(uchar8, uint, uint);
+short8 __ovld __cnfn bitfield_extract_signed(ushort8, uint, uint);
+int8 __ovld __cnfn bitfield_extract_signed(uint8, uint, uint);
+long8 __ovld __cnfn bitfield_extract_signed(ulong8, uint, uint);
+char16 __ovld __cnfn bitfield_extract_signed(uchar16, uint, uint);
+short16 __ovld __cnfn bitfield_extract_signed(ushort16, uint, uint);
+int16 __ovld __cnfn bitfield_extract_signed(uint16, uint, uint);
+long16 __ovld __cnfn bitfield_extract_signed(ulong16, uint, uint);
+
+uchar __ovld __cnfn bitfield_extract_unsigned(char, uint, uint);
+ushort __ovld __cnfn bitfield_extract_unsigned(short, uint, uint);
+uint __ovld __cnfn bitfield_extract_unsigned(int, uint, uint);
+ulong __ovld __cnfn bitfield_extract_unsigned(long, uint, uint);
+uchar2 __ovld __cnfn bitfield_extract_unsigned(char2, uint, uint);
+ushort2 __ovld __cnfn bitfield_extract_unsigned(short2, uint, uint);
+uint2 __ovld __cnfn bitfield_extract_unsigned(int2, uint, uint);
+ulong2 __ovld __cnfn bitfield_extract_unsigned(long2, uint, uint);
+uchar3 __ovld __cnfn bitfield_extract_unsigned(char3, uint, uint);
+ushort3 __ovld __cnfn bitfield_extract_unsigned(short3, uint, uint);
+uint3 __ovld __cnfn bitfield_extract_unsigned(int3, uint, uint);
+ulong3 __ovld __cnfn bitfield_extract_unsigned(long3, uint, uint);
+uchar4 __ovld __cnfn bitfield_extract_unsigned(char4, uint, uint);
+ushort4 __ovld __cnfn bitfield_extract_unsigned(short4, uint, uint);
+uint4 __ovld __cnfn bitfield_extract_unsigned(int4, uint, uint);
+ulong4 __ovld __cnfn bitfield_extract_unsigned(long4, uint, uint);
+uchar8 __ovld __cnfn bitfield_extract_unsigned(char8, uint, uint);
+ushort8 __ovld __cnfn bitfield_extract_unsigned(short8, uint, uint);
+uint8 __ovld __cnfn bitfield_extract_unsigned(int8, uint, uint);
+ulong8 __ovld __cnfn bitfield_extract_unsigned(long8, uint, uint);
+uchar16 __ovld __cnfn bitfield_extract_unsigned(char16, uint, uint);
+ushort16 __ovld __cnfn bitfield_extract_unsigned(short16, uint, uint);
+uint16 __ovld __cnfn bitfield_extract_unsigned(int16, uint, uint);
+ulong16 __ovld __cnfn bitfield_extract_unsigned(long16, uint, uint);
+
+uchar __ovld __cnfn bitfield_extract_unsigned(uchar, uint, uint);
+ushort __ovld __cnfn bitfield_extract_unsigned(ushort, uint, uint);
+uint __ovld __cnfn bitfield_extract_unsigned(uint, uint, uint);
+ulong __ovld __cnfn bitfield_extract_unsigned(ulong, uint, uint);
+uchar2 __ovld __cnfn bitfield_extract_unsigned(uchar2, uint, uint);
+ushort2 __ovld __cnfn bitfield_extract_unsigned(ushort2, uint, uint);
+uint2 __ovld __cnfn bitfield_extract_unsigned(uint2, uint, uint);
+ulong2 __ovld __cnfn bitfield_extract_unsigned(ulong2, uint, uint);
+uchar3 __ovld __cnfn bitfield_extract_unsigned(uchar3, uint, uint);
+ushort3 __ovld __cnfn bitfield_extract_unsigned(ushort3, uint, uint);
+uint3 __ovld __cnfn bitfield_extract_unsigned(uint3, uint, uint);
+ulong3 __ovld __cnfn bitfield_extract_unsigned(ulong3, uint, uint);
+uchar4 __ovld __cnfn bitfield_extract_unsigned(uchar4, uint, uint);
+ushort4 __ovld __cnfn bitfield_extract_unsigned(ushort4, uint, uint);
+uint4 __ovld __cnfn bitfield_extract_unsigned(uint4, uint, uint);
+ulong4 __ovld __cnfn bitfield_extract_unsigned(ulong4, uint, uint);
+uchar8 __ovld __cnfn bitfield_extract_unsigned(uchar8, uint, uint);
+ushort8 __ovld __cnfn bitfield_extract_unsigned(ushort8, uint, uint);
+uint8 __ovld __cnfn bitfield_extract_unsigned(uint8, uint, uint);
+ulong8 __ovld __cnfn bitfield_extract_unsigned(ulong8, uint, uint);
+uchar16 __ovld __cnfn bitfield_extract_unsigned(uchar16, uint, uint);
+ushort16 __ovld __cnfn bitfield_extract_unsigned(ushort16, uint, uint);
+uint16 __ovld __cnfn bitfield_extract_unsigned(uint16, uint, uint);
+ulong16 __ovld __cnfn bitfield_extract_unsigned(ulong16, uint, uint);
+
+char __ovld __cnfn bit_reverse(char);
+uchar __ovld __cnfn bit_reverse(uchar);
+short __ovld __cnfn bit_reverse(short);
+ushort __ovld __cnfn bit_reverse(ushort);
+int __ovld __cnfn bit_reverse(int);
+uint __ovld __cnfn bit_reverse(uint);
+long __ovld __cnfn bit_reverse(long);
+ulong __ovld __cnfn bit_reverse(ulong);
+char2 __ovld __cnfn bit_reverse(char2);
+uchar2 __ovld __cnfn bit_reverse(uchar2);
+short2 __ovld __cnfn bit_reverse(short2);
+ushort2 __ovld __cnfn bit_reverse(ushort2);
+int2 __ovld __cnfn bit_reverse(int2);
+uint2 __ovld __cnfn bit_reverse(uint2);
+long2 __ovld __cnfn bit_reverse(long2);
+ulong2 __ovld __cnfn bit_reverse(ulong2);
+char3 __ovld __cnfn bit_reverse(char3);
+uchar3 __ovld __cnfn bit_reverse(uchar3);
+short3 __ovld __cnfn bit_reverse(short3);
+ushort3 __ovld __cnfn bit_reverse(ushort3);
+int3 __ovld __cnfn bit_reverse(int3);
+uint3 __ovld __cnfn bit_reverse(uint3);
+long3 __ovld __cnfn bit_reverse(long3);
+ulong3 __ovld __cnfn bit_reverse(ulong3);
+char4 __ovld __cnfn bit_reverse(char4);
+uchar4 __ovld __cnfn bit_reverse(uchar4);
+short4 __ovld __cnfn bit_reverse(short4);
+ushort4 __ovld __cnfn bit_reverse(ushort4);
+int4 __ovld __cnfn bit_reverse(int4);
+uint4 __ovld __cnfn bit_reverse(uint4);
+long4 __ovld __cnfn bit_reverse(long4);
+ulong4 __ovld __cnfn bit_reverse(ulong4);
+char8 __ovld __cnfn bit_reverse(char8);
+uchar8 __ovld __cnfn bit_reverse(uchar8);
+short8 __ovld __cnfn bit_reverse(short8);
+ushort8 __ovld __cnfn bit_reverse(ushort8);
+int8 __ovld __cnfn bit_reverse(int8);
+uint8 __ovld __cnfn bit_reverse(uint8);
+long8 __ovld __cnfn bit_reverse(long8);
+ulong8 __ovld __cnfn bit_reverse(ulong8);
+char16 __ovld __cnfn bit_reverse(char16);
+uchar16 __ovld __cnfn bit_reverse(uchar16);
+short16 __ovld __cnfn bit_reverse(short16);
+ushort16 __ovld __cnfn bit_reverse(ushort16);
+int16 __ovld __cnfn bit_reverse(int16);
+uint16 __ovld __cnfn bit_reverse(uint16);
+long16 __ovld __cnfn bit_reverse(long16);
+ulong16 __ovld __cnfn bit_reverse(ulong16);
+#endif // cl_khr_extended_bit_ops
+
+#if defined(__opencl_c_integer_dot_product_input_4x8bit)
+uint __ovld __cnfn dot(uchar4, uchar4);
+int __ovld __cnfn dot(char4, char4);
+int __ovld __cnfn dot(uchar4, char4);
+int __ovld __cnfn dot(char4, uchar4);
+
+uint __ovld __cnfn dot_acc_sat(uchar4, uchar4, uint);
+int __ovld __cnfn dot_acc_sat(char4, char4, int);
+int __ovld __cnfn dot_acc_sat(uchar4, char4, int);
+int __ovld __cnfn dot_acc_sat(char4, uchar4, int);
+#endif // __opencl_c_integer_dot_product_input_4x8bit
+
+#if defined(__opencl_c_integer_dot_product_input_4x8bit_packed)
+uint __ovld __cnfn dot_4x8packed_uu_uint(uint, uint);
+int __ovld __cnfn dot_4x8packed_ss_int(uint, uint);
+int __ovld __cnfn dot_4x8packed_us_int(uint, uint);
+int __ovld __cnfn dot_4x8packed_su_int(uint, uint);
+
+uint __ovld __cnfn dot_acc_sat_4x8packed_uu_uint(uint, uint, uint);
+int __ovld __cnfn dot_acc_sat_4x8packed_ss_int(uint, uint, int);
+int __ovld __cnfn dot_acc_sat_4x8packed_us_int(uint, uint, int);
+int __ovld __cnfn dot_acc_sat_4x8packed_su_int(uint, uint, int);
+#endif // __opencl_c_integer_dot_product_input_4x8bit_packed
+
#if defined(cl_intel_subgroups)
// Intel-Specific Sub Group Functions
float __ovld __conv intel_sub_group_shuffle( float x, uint c );
@@ -17127,31 +17285,23 @@
#endif // cl_amd_media_ops2
#if defined(cl_arm_integer_dot_product_int8)
-#pragma OPENCL EXTENSION cl_arm_integer_dot_product_int8 : begin
uint __ovld arm_dot(uchar4 a, uchar4 b);
int __ovld arm_dot(char4 a, char4 b);
-#pragma OPENCL EXTENSION cl_arm_integer_dot_product_int8 : end
#endif // defined(cl_arm_integer_dot_product_int8)
#if defined(cl_arm_integer_dot_product_accumulate_int8)
-#pragma OPENCL EXTENSION cl_arm_integer_dot_product_accumulate_int8 : begin
uint __ovld arm_dot_acc(uchar4 a, uchar4 b, uint c);
int __ovld arm_dot_acc(char4 a, char4 b, int c);
-#pragma OPENCL EXTENSION cl_arm_integer_dot_product_accumulate_int8 : end
#endif // defined(cl_arm_integer_dot_product_accumulate_int8)
#if defined(cl_arm_integer_dot_product_accumulate_int16)
-#pragma OPENCL EXTENSION cl_arm_integer_dot_product_accumulate_int16 : begin
uint __ovld arm_dot_acc(ushort2 a, ushort2 b, uint c);
int __ovld arm_dot_acc(short2 a, short2 b, int c);
-#pragma OPENCL EXTENSION cl_arm_integer_dot_product_accumulate_int16 : end
#endif // defined(cl_arm_integer_dot_product_accumulate_int16)
#if defined(cl_arm_integer_dot_product_accumulate_saturate_int8)
-#pragma OPENCL EXTENSION cl_arm_integer_dot_product_accumulate_saturate_int8 : begin
uint __ovld arm_dot_acc_sat(uchar4 a, uchar4 b, uint c);
int __ovld arm_dot_acc_sat(char4 a, char4 b, int c);
-#pragma OPENCL EXTENSION cl_arm_integer_dot_product_accumulate_saturate_int8 : end
#endif // defined(cl_arm_integer_dot_product_accumulate_saturate_int8)
// Disable any extensions we may have enabled previously.
diff --git a/src/llvm-project/clang/lib/Headers/openmp_wrappers/__clang_openmp_device_functions.h b/src/llvm-project/clang/lib/Headers/openmp_wrappers/__clang_openmp_device_functions.h
index 406c974..953857b 100644
--- a/src/llvm-project/clang/lib/Headers/openmp_wrappers/__clang_openmp_device_functions.h
+++ b/src/llvm-project/clang/lib/Headers/openmp_wrappers/__clang_openmp_device_functions.h
@@ -39,4 +39,46 @@
#pragma omp end declare variant
+// Ensure we make `_ZdlPv`, aka. `operator delete(void*)` available without the
+// need to `include <new>` in C++ mode.
+#ifdef __cplusplus
+
+// We require malloc/free.
+#include <cstdlib>
+
+#pragma push_macro("OPENMP_NOEXCEPT")
+#if __cplusplus >= 201103L
+#define OPENMP_NOEXCEPT noexcept
+#else
+#define OPENMP_NOEXCEPT
+#endif
+
+// Device overrides for non-placement new and delete.
+inline void *operator new(__SIZE_TYPE__ size) {
+ if (size == 0)
+ size = 1;
+ return ::malloc(size);
+}
+
+inline void *operator new[](__SIZE_TYPE__ size) { return ::operator new(size); }
+
+inline void operator delete(void *ptr)OPENMP_NOEXCEPT { ::free(ptr); }
+
+inline void operator delete[](void *ptr) OPENMP_NOEXCEPT {
+ ::operator delete(ptr);
+}
+
+// Sized delete, C++14 only.
+#if __cplusplus >= 201402L
+inline void operator delete(void *ptr, __SIZE_TYPE__ size)OPENMP_NOEXCEPT {
+ ::operator delete(ptr);
+}
+inline void operator delete[](void *ptr, __SIZE_TYPE__ size) OPENMP_NOEXCEPT {
+ ::operator delete(ptr);
+}
+#endif
+
+#pragma pop_macro("OPENMP_NOEXCEPT")
+#endif
+
#endif
diff --git a/src/llvm-project/clang/lib/Headers/openmp_wrappers/complex b/src/llvm-project/clang/lib/Headers/openmp_wrappers/complex
index 142e526..dfd6193 100644
--- a/src/llvm-project/clang/lib/Headers/openmp_wrappers/complex
+++ b/src/llvm-project/clang/lib/Headers/openmp_wrappers/complex
@@ -17,7 +17,6 @@
// We require std::math functions in the complex builtins below.
#include <cmath>
-#define __CUDA__
#define __OPENMP_NVPTX__
#include <__clang_cuda_complex_builtins.h>
#undef __OPENMP_NVPTX__
@@ -26,9 +25,6 @@
// Grab the host header too.
#include_next <complex>
-
-#ifdef __cplusplus
-
// If we are compiling against libc++, the macro _LIBCPP_STD_VER should be set
// after including <cmath> above. Since the complex header we use is a
// simplified version of the libc++, we don't need it in this case. If we
@@ -48,5 +44,3 @@
#pragma omp end declare variant
#endif
-
-#endif
diff --git a/src/llvm-project/clang/lib/Headers/openmp_wrappers/complex.h b/src/llvm-project/clang/lib/Headers/openmp_wrappers/complex.h
index 00d2785..15dc415 100644
--- a/src/llvm-project/clang/lib/Headers/openmp_wrappers/complex.h
+++ b/src/llvm-project/clang/lib/Headers/openmp_wrappers/complex.h
@@ -17,7 +17,6 @@
// We require math functions in the complex builtins below.
#include <math.h>
-#define __CUDA__
#define __OPENMP_NVPTX__
#include <__clang_cuda_complex_builtins.h>
#undef __OPENMP_NVPTX__
diff --git a/src/llvm-project/clang/lib/Headers/openmp_wrappers/new b/src/llvm-project/clang/lib/Headers/openmp_wrappers/new
index 1387d92..985ddc5 100644
--- a/src/llvm-project/clang/lib/Headers/openmp_wrappers/new
+++ b/src/llvm-project/clang/lib/Headers/openmp_wrappers/new
@@ -9,6 +9,8 @@
#ifndef __CLANG_OPENMP_WRAPPERS_NEW
#define __CLANG_OPENMP_WRAPPERS_NEW
+// We need the system <new> for the std::nothrow_t. The new/delete operators
+// which do not use nothrow_t are provided without the <new> header.
#include_next <new>
#if defined(__NVPTX__) && defined(_OPENMP)
@@ -22,48 +24,24 @@
#define OPENMP_NOEXCEPT
#endif
-// Device overrides for non-placement new and delete.
-inline void *operator new(__SIZE_TYPE__ size) {
- if (size == 0)
- size = 1;
- return ::malloc(size);
-}
inline void *operator new(__SIZE_TYPE__ size,
const std::nothrow_t &) OPENMP_NOEXCEPT {
return ::operator new(size);
}
-inline void *operator new[](__SIZE_TYPE__ size) { return ::operator new(size); }
inline void *operator new[](__SIZE_TYPE__ size, const std::nothrow_t &) {
return ::operator new(size);
}
-inline void operator delete(void *ptr)OPENMP_NOEXCEPT {
- if (ptr)
- ::free(ptr);
-}
inline void operator delete(void *ptr, const std::nothrow_t &)OPENMP_NOEXCEPT {
::operator delete(ptr);
}
-inline void operator delete[](void *ptr) OPENMP_NOEXCEPT {
- ::operator delete(ptr);
-}
inline void operator delete[](void *ptr,
const std::nothrow_t &) OPENMP_NOEXCEPT {
::operator delete(ptr);
}
-// Sized delete, C++14 only.
-#if __cplusplus >= 201402L
-inline void operator delete(void *ptr, __SIZE_TYPE__ size)OPENMP_NOEXCEPT {
- ::operator delete(ptr);
-}
-inline void operator delete[](void *ptr, __SIZE_TYPE__ size) OPENMP_NOEXCEPT {
- ::operator delete(ptr);
-}
-#endif
-
#pragma pop_macro("OPENMP_NOEXCEPT")
#endif
diff --git a/src/llvm-project/clang/lib/Headers/uintrintrin.h b/src/llvm-project/clang/lib/Headers/uintrintrin.h
index 78aa877..e3839dc 100644
--- a/src/llvm-project/clang/lib/Headers/uintrintrin.h
+++ b/src/llvm-project/clang/lib/Headers/uintrintrin.h
@@ -20,6 +20,13 @@
#ifdef __x86_64__
+struct __uintr_frame
+{
+ unsigned long long rip;
+ unsigned long long rflags;
+ unsigned long long rsp;
+};
+
/// Clears the user interrupt flag (UIF). Its effect takes place immediately: a
/// user interrupt cannot be delivered on the instruction boundary following
/// CLUI. Can be executed only if CR4.UINT = 1, the logical processor is in
diff --git a/src/llvm-project/clang/lib/Headers/vaesintrin.h b/src/llvm-project/clang/lib/Headers/vaesintrin.h
index c4d5c3e..f3c0807 100644
--- a/src/llvm-project/clang/lib/Headers/vaesintrin.h
+++ b/src/llvm-project/clang/lib/Headers/vaesintrin.h
@@ -28,13 +28,6 @@
(__v4di) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS_F
- _mm512_aesenc_epi128(__m512i __A, __m512i __B)
-{
- return (__m512i) __builtin_ia32_aesenc512((__v8di) __A,
- (__v8di) __B);
-}
-
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_aesdec_epi128(__m256i __A, __m256i __B)
{
@@ -42,13 +35,6 @@
(__v4di) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS_F
- _mm512_aesdec_epi128(__m512i __A, __m512i __B)
-{
- return (__m512i) __builtin_ia32_aesdec512((__v8di) __A,
- (__v8di) __B);
-}
-
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_aesenclast_epi128(__m256i __A, __m256i __B)
{
@@ -56,13 +42,6 @@
(__v4di) __B);
}
-static __inline__ __m512i __DEFAULT_FN_ATTRS_F
- _mm512_aesenclast_epi128(__m512i __A, __m512i __B)
-{
- return (__m512i) __builtin_ia32_aesenclast512((__v8di) __A,
- (__v8di) __B);
-}
-
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_aesdeclast_epi128(__m256i __A, __m256i __B)
{
@@ -70,13 +49,35 @@
(__v4di) __B);
}
+#ifdef __AVX512FINTRIN_H
+static __inline__ __m512i __DEFAULT_FN_ATTRS_F
+ _mm512_aesenc_epi128(__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_aesenc512((__v8di) __A,
+ (__v8di) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS_F
+ _mm512_aesdec_epi128(__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_aesdec512((__v8di) __A,
+ (__v8di) __B);
+}
+
+static __inline__ __m512i __DEFAULT_FN_ATTRS_F
+ _mm512_aesenclast_epi128(__m512i __A, __m512i __B)
+{
+ return (__m512i) __builtin_ia32_aesenclast512((__v8di) __A,
+ (__v8di) __B);
+}
+
static __inline__ __m512i __DEFAULT_FN_ATTRS_F
_mm512_aesdeclast_epi128(__m512i __A, __m512i __B)
{
return (__m512i) __builtin_ia32_aesdeclast512((__v8di) __A,
(__v8di) __B);
}
-
+#endif // __AVX512FINTRIN_H
#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS_F
diff --git a/src/llvm-project/clang/lib/Headers/vecintrin.h b/src/llvm-project/clang/lib/Headers/vecintrin.h
index e58c976..ec1dbfd 100644
--- a/src/llvm-project/clang/lib/Headers/vecintrin.h
+++ b/src/llvm-project/clang/lib/Headers/vecintrin.h
@@ -1016,64 +1016,84 @@
static inline __ATTRS_o_ai __vector signed char
vec_xl(long __offset, const signed char *__ptr) {
- return *(const __vector signed char *)
- ((const char *)__ptr + __offset);
+ __vector signed char V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed char));
+ return V;
}
static inline __ATTRS_o_ai __vector unsigned char
vec_xl(long __offset, const unsigned char *__ptr) {
- return *(const __vector unsigned char *)
- ((const char *)__ptr + __offset);
+ __vector unsigned char V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned char));
+ return V;
}
static inline __ATTRS_o_ai __vector signed short
vec_xl(long __offset, const signed short *__ptr) {
- return *(const __vector signed short *)
- ((const char *)__ptr + __offset);
+ __vector signed short V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed short));
+ return V;
}
static inline __ATTRS_o_ai __vector unsigned short
vec_xl(long __offset, const unsigned short *__ptr) {
- return *(const __vector unsigned short *)
- ((const char *)__ptr + __offset);
+ __vector unsigned short V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned short));
+ return V;
}
static inline __ATTRS_o_ai __vector signed int
vec_xl(long __offset, const signed int *__ptr) {
- return *(const __vector signed int *)
- ((const char *)__ptr + __offset);
+ __vector signed int V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed int));
+ return V;
}
static inline __ATTRS_o_ai __vector unsigned int
vec_xl(long __offset, const unsigned int *__ptr) {
- return *(const __vector unsigned int *)
- ((const char *)__ptr + __offset);
+ __vector unsigned int V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned int));
+ return V;
}
static inline __ATTRS_o_ai __vector signed long long
vec_xl(long __offset, const signed long long *__ptr) {
- return *(const __vector signed long long *)
- ((const char *)__ptr + __offset);
+ __vector signed long long V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed long long));
+ return V;
}
static inline __ATTRS_o_ai __vector unsigned long long
vec_xl(long __offset, const unsigned long long *__ptr) {
- return *(const __vector unsigned long long *)
- ((const char *)__ptr + __offset);
+ __vector unsigned long long V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned long long));
+ return V;
}
#if __ARCH__ >= 12
static inline __ATTRS_o_ai __vector float
vec_xl(long __offset, const float *__ptr) {
- return *(const __vector float *)
- ((const char *)__ptr + __offset);
+ __vector float V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector float));
+ return V;
}
#endif
static inline __ATTRS_o_ai __vector double
vec_xl(long __offset, const double *__ptr) {
- return *(const __vector double *)
- ((const char *)__ptr + __offset);
+ __vector double V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector double));
+ return V;
}
/*-- vec_xld2 ---------------------------------------------------------------*/
@@ -1081,64 +1101,82 @@
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector signed char
vec_xld2(long __offset, const signed char *__ptr) {
- return *(const __vector signed char *)
- ((const char *)__ptr + __offset);
+ __vector signed char V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed char));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector unsigned char
vec_xld2(long __offset, const unsigned char *__ptr) {
- return *(const __vector unsigned char *)
- ((const char *)__ptr + __offset);
+ __vector unsigned char V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned char));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector signed short
vec_xld2(long __offset, const signed short *__ptr) {
- return *(const __vector signed short *)
- ((const char *)__ptr + __offset);
+ __vector signed short V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed short));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector unsigned short
vec_xld2(long __offset, const unsigned short *__ptr) {
- return *(const __vector unsigned short *)
- ((const char *)__ptr + __offset);
+ __vector unsigned short V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned short));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector signed int
vec_xld2(long __offset, const signed int *__ptr) {
- return *(const __vector signed int *)
- ((const char *)__ptr + __offset);
+ __vector signed int V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed int));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector unsigned int
vec_xld2(long __offset, const unsigned int *__ptr) {
- return *(const __vector unsigned int *)
- ((const char *)__ptr + __offset);
+ __vector unsigned int V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned int));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector signed long long
vec_xld2(long __offset, const signed long long *__ptr) {
- return *(const __vector signed long long *)
- ((const char *)__ptr + __offset);
+ __vector signed long long V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed long long));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector unsigned long long
vec_xld2(long __offset, const unsigned long long *__ptr) {
- return *(const __vector unsigned long long *)
- ((const char *)__ptr + __offset);
+ __vector unsigned long long V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned long long));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector double
vec_xld2(long __offset, const double *__ptr) {
- return *(const __vector double *)
- ((const char *)__ptr + __offset);
+ __vector double V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector double));
+ return V;
}
/*-- vec_xlw4 ---------------------------------------------------------------*/
@@ -1146,99 +1184,128 @@
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector signed char
vec_xlw4(long __offset, const signed char *__ptr) {
- return *(const __vector signed char *)
- ((const char *)__ptr + __offset);
+ __vector signed char V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed char));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector unsigned char
vec_xlw4(long __offset, const unsigned char *__ptr) {
- return *(const __vector unsigned char *)
- ((const char *)__ptr + __offset);
+ __vector unsigned char V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned char));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector signed short
vec_xlw4(long __offset, const signed short *__ptr) {
- return *(const __vector signed short *)
- ((const char *)__ptr + __offset);
+ __vector signed short V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed short));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector unsigned short
vec_xlw4(long __offset, const unsigned short *__ptr) {
- return *(const __vector unsigned short *)
- ((const char *)__ptr + __offset);
+ __vector unsigned short V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned short));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector signed int
vec_xlw4(long __offset, const signed int *__ptr) {
- return *(const __vector signed int *)
- ((const char *)__ptr + __offset);
+ __vector signed int V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector signed int));
+ return V;
}
// This prototype is deprecated.
static inline __ATTRS_o_ai __vector unsigned int
vec_xlw4(long __offset, const unsigned int *__ptr) {
- return *(const __vector unsigned int *)
- ((const char *)__ptr + __offset);
+ __vector unsigned int V;
+ __builtin_memcpy(&V, ((const char *)__ptr + __offset),
+ sizeof(__vector unsigned int));
+ return V;
}
/*-- vec_xst ----------------------------------------------------------------*/
static inline __ATTRS_o_ai void
vec_xst(__vector signed char __vec, long __offset, signed char *__ptr) {
- *(__vector signed char *)((char *)__ptr + __offset) = __vec;
+ __vector signed char V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector signed char));
}
static inline __ATTRS_o_ai void
vec_xst(__vector unsigned char __vec, long __offset, unsigned char *__ptr) {
- *(__vector unsigned char *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned char V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned char));
}
static inline __ATTRS_o_ai void
vec_xst(__vector signed short __vec, long __offset, signed short *__ptr) {
- *(__vector signed short *)((char *)__ptr + __offset) = __vec;
+ __vector signed short V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector signed short));
}
static inline __ATTRS_o_ai void
vec_xst(__vector unsigned short __vec, long __offset, unsigned short *__ptr) {
- *(__vector unsigned short *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned short V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned short));
}
static inline __ATTRS_o_ai void
vec_xst(__vector signed int __vec, long __offset, signed int *__ptr) {
- *(__vector signed int *)((char *)__ptr + __offset) = __vec;
+ __vector signed int V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V, sizeof(__vector signed int));
}
static inline __ATTRS_o_ai void
vec_xst(__vector unsigned int __vec, long __offset, unsigned int *__ptr) {
- *(__vector unsigned int *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned int V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned int));
}
static inline __ATTRS_o_ai void
vec_xst(__vector signed long long __vec, long __offset,
- signed long long *__ptr) {
- *(__vector signed long long *)((char *)__ptr + __offset) = __vec;
+ signed long long *__ptr) {
+ __vector signed long long V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector signed long long));
}
static inline __ATTRS_o_ai void
vec_xst(__vector unsigned long long __vec, long __offset,
- unsigned long long *__ptr) {
- *(__vector unsigned long long *)((char *)__ptr + __offset) = __vec;
+ unsigned long long *__ptr) {
+ __vector unsigned long long V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned long long));
}
#if __ARCH__ >= 12
static inline __ATTRS_o_ai void
vec_xst(__vector float __vec, long __offset, float *__ptr) {
- *(__vector float *)((char *)__ptr + __offset) = __vec;
+ __vector float V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V, sizeof(__vector float));
}
#endif
static inline __ATTRS_o_ai void
vec_xst(__vector double __vec, long __offset, double *__ptr) {
- *(__vector double *)((char *)__ptr + __offset) = __vec;
+ __vector double V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V, sizeof(__vector double));
}
/*-- vec_xstd2 --------------------------------------------------------------*/
@@ -1246,57 +1313,73 @@
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector signed char __vec, long __offset, signed char *__ptr) {
- *(__vector signed char *)((char *)__ptr + __offset) = __vec;
+ __vector signed char V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector signed char));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector unsigned char __vec, long __offset, unsigned char *__ptr) {
- *(__vector unsigned char *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned char V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned char));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector signed short __vec, long __offset, signed short *__ptr) {
- *(__vector signed short *)((char *)__ptr + __offset) = __vec;
+ __vector signed short V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector signed short));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector unsigned short __vec, long __offset, unsigned short *__ptr) {
- *(__vector unsigned short *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned short V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned short));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector signed int __vec, long __offset, signed int *__ptr) {
- *(__vector signed int *)((char *)__ptr + __offset) = __vec;
+ __vector signed int V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V, sizeof(__vector signed int));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector unsigned int __vec, long __offset, unsigned int *__ptr) {
- *(__vector unsigned int *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned int V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned int));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector signed long long __vec, long __offset,
signed long long *__ptr) {
- *(__vector signed long long *)((char *)__ptr + __offset) = __vec;
+ __vector signed long long V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector signed long long));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector unsigned long long __vec, long __offset,
unsigned long long *__ptr) {
- *(__vector unsigned long long *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned long long V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned long long));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstd2(__vector double __vec, long __offset, double *__ptr) {
- *(__vector double *)((char *)__ptr + __offset) = __vec;
+ __vector double V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V, sizeof(__vector double));
}
/*-- vec_xstw4 --------------------------------------------------------------*/
@@ -1304,37 +1387,48 @@
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstw4(__vector signed char __vec, long __offset, signed char *__ptr) {
- *(__vector signed char *)((char *)__ptr + __offset) = __vec;
+ __vector signed char V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector signed char));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstw4(__vector unsigned char __vec, long __offset, unsigned char *__ptr) {
- *(__vector unsigned char *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned char V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned char));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstw4(__vector signed short __vec, long __offset, signed short *__ptr) {
- *(__vector signed short *)((char *)__ptr + __offset) = __vec;
+ __vector signed short V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector signed short));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstw4(__vector unsigned short __vec, long __offset, unsigned short *__ptr) {
- *(__vector unsigned short *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned short V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned short));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstw4(__vector signed int __vec, long __offset, signed int *__ptr) {
- *(__vector signed int *)((char *)__ptr + __offset) = __vec;
+ __vector signed int V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V, sizeof(__vector signed int));
}
// This prototype is deprecated.
static inline __ATTRS_o_ai void
vec_xstw4(__vector unsigned int __vec, long __offset, unsigned int *__ptr) {
- *(__vector unsigned int *)((char *)__ptr + __offset) = __vec;
+ __vector unsigned int V = __vec;
+ __builtin_memcpy(((char *)__ptr + __offset), &V,
+ sizeof(__vector unsigned int));
}
/*-- vec_load_bndry ---------------------------------------------------------*/
@@ -9259,6 +9353,41 @@
__VEC_CLASS_FP_ZERO | \
__VEC_CLASS_FP_INFINITY)
+/*-- vec_extend_to_fp32_hi --------------------------------------------------*/
+
+#if __ARCH__ >= 14
+#define vec_extend_to_fp32_hi(X, W) \
+ ((__vector float)__builtin_s390_vclfnhs((X), (W)));
+#endif
+
+/*-- vec_extend_to_fp32_hi --------------------------------------------------*/
+
+#if __ARCH__ >= 14
+#define vec_extend_to_fp32_lo(X, W) \
+ ((__vector float)__builtin_s390_vclfnls((X), (W)));
+#endif
+
+/*-- vec_round_from_fp32 ----------------------------------------------------*/
+
+#if __ARCH__ >= 14
+#define vec_round_from_fp32(X, Y, W) \
+ ((__vector unsigned short)__builtin_s390_vcrnfs((X), (Y), (W)));
+#endif
+
+/*-- vec_convert_to_fp16 ----------------------------------------------------*/
+
+#if __ARCH__ >= 14
+#define vec_convert_to_fp16(X, W) \
+ ((__vector unsigned short)__builtin_s390_vcfn((X), (W)));
+#endif
+
+/*-- vec_convert_from_fp16 --------------------------------------------------*/
+
+#if __ARCH__ >= 14
+#define vec_convert_from_fp16(X, W) \
+ ((__vector unsigned short)__builtin_s390_vcnf((X), (W)));
+#endif
+
/*-- vec_cp_until_zero ------------------------------------------------------*/
static inline __ATTRS_o_ai __vector signed char
diff --git a/src/llvm-project/clang/lib/Headers/vpclmulqdqintrin.h b/src/llvm-project/clang/lib/Headers/vpclmulqdqintrin.h
index 470d832..44daadb 100644
--- a/src/llvm-project/clang/lib/Headers/vpclmulqdqintrin.h
+++ b/src/llvm-project/clang/lib/Headers/vpclmulqdqintrin.h
@@ -19,10 +19,12 @@
(__v4di)(__m256i)(B), \
(char)(I))
+#ifdef __AVX512FINTRIN_H
#define _mm512_clmulepi64_epi128(A, B, I) \
(__m512i)__builtin_ia32_pclmulqdq512((__v8di)(__m512i)(A), \
(__v8di)(__m512i)(B), \
(char)(I))
+#endif // __AVX512FINTRIN_H
#endif /* __VPCLMULQDQINTRIN_H */
diff --git a/src/llvm-project/clang/lib/Headers/wasm_simd128.h b/src/llvm-project/clang/lib/Headers/wasm_simd128.h
index 20f5a85..712fa03 100644
--- a/src/llvm-project/clang/lib/Headers/wasm_simd128.h
+++ b/src/llvm-project/clang/lib/Headers/wasm_simd128.h
@@ -40,13 +40,18 @@
typedef short __i16x4 __attribute__((__vector_size__(8), __aligned__(8)));
typedef unsigned short __u16x4
__attribute__((__vector_size__(8), __aligned__(8)));
+typedef int __i32x2 __attribute__((__vector_size__(8), __aligned__(8)));
+typedef unsigned int __u32x2
+ __attribute__((__vector_size__(8), __aligned__(8)));
+typedef float __f32x2 __attribute__((__vector_size__(8), __aligned__(8)));
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __target__("simd128"), \
__min_vector_width__(128)))
-#define __REQUIRE_CONSTANT(e) \
- _Static_assert(__builtin_constant_p(e), "Expected constant")
+#define __REQUIRE_CONSTANT(c) \
+ __attribute__((__diagnose_if__(!__builtin_constant_p(c), \
+ #c " must be constant", "error")))
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load(const void *__mem) {
// UB-free unaligned access copied from xmmintrin.h
@@ -57,102 +62,158 @@
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_v8x16_load_splat(const void *__mem) {
- struct __wasm_v8x16_load_splat_struct {
+wasm_v128_load8_splat(const void *__mem) {
+ struct __wasm_v128_load8_splat_struct {
uint8_t __v;
} __attribute__((__packed__, __may_alias__));
- uint8_t __v = ((const struct __wasm_v8x16_load_splat_struct *)__mem)->__v;
+ uint8_t __v = ((const struct __wasm_v128_load8_splat_struct *)__mem)->__v;
return (v128_t)(__u8x16){__v, __v, __v, __v, __v, __v, __v, __v,
__v, __v, __v, __v, __v, __v, __v, __v};
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_v16x8_load_splat(const void *__mem) {
- struct __wasm_v16x8_load_splat_struct {
+wasm_v128_load16_splat(const void *__mem) {
+ struct __wasm_v128_load16_splat_struct {
uint16_t __v;
} __attribute__((__packed__, __may_alias__));
- uint16_t __v = ((const struct __wasm_v16x8_load_splat_struct *)__mem)->__v;
+ uint16_t __v = ((const struct __wasm_v128_load16_splat_struct *)__mem)->__v;
return (v128_t)(__u16x8){__v, __v, __v, __v, __v, __v, __v, __v};
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_v32x4_load_splat(const void *__mem) {
- struct __wasm_v32x4_load_splat_struct {
+wasm_v128_load32_splat(const void *__mem) {
+ struct __wasm_v128_load32_splat_struct {
uint32_t __v;
} __attribute__((__packed__, __may_alias__));
- uint32_t __v = ((const struct __wasm_v32x4_load_splat_struct *)__mem)->__v;
+ uint32_t __v = ((const struct __wasm_v128_load32_splat_struct *)__mem)->__v;
return (v128_t)(__u32x4){__v, __v, __v, __v};
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_v64x2_load_splat(const void *__mem) {
- struct __wasm_v64x2_load_splat_struct {
+wasm_v128_load64_splat(const void *__mem) {
+ struct __wasm_v128_load64_splat_struct {
uint64_t __v;
} __attribute__((__packed__, __may_alias__));
- uint64_t __v = ((const struct __wasm_v64x2_load_splat_struct *)__mem)->__v;
+ uint64_t __v = ((const struct __wasm_v128_load64_splat_struct *)__mem)->__v;
return (v128_t)(__u64x2){__v, __v};
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i16x8_load_8x8(const void *__mem) {
- typedef int8_t __i8x8 __attribute__((__vector_size__(8), __aligned__(8)));
- struct __wasm_i16x8_load_8x8_struct {
+wasm_i16x8_load8x8(const void *__mem) {
+ struct __wasm_i16x8_load8x8_struct {
__i8x8 __v;
} __attribute__((__packed__, __may_alias__));
- __i8x8 __v = ((const struct __wasm_i16x8_load_8x8_struct *)__mem)->__v;
+ __i8x8 __v = ((const struct __wasm_i16x8_load8x8_struct *)__mem)->__v;
return (v128_t) __builtin_convertvector(__v, __i16x8);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_u16x8_load_8x8(const void *__mem) {
- typedef uint8_t __u8x8 __attribute__((__vector_size__(8), __aligned__(8)));
- struct __wasm_u16x8_load_8x8_struct {
+wasm_u16x8_load8x8(const void *__mem) {
+ struct __wasm_u16x8_load8x8_struct {
__u8x8 __v;
} __attribute__((__packed__, __may_alias__));
- __u8x8 __v = ((const struct __wasm_u16x8_load_8x8_struct *)__mem)->__v;
+ __u8x8 __v = ((const struct __wasm_u16x8_load8x8_struct *)__mem)->__v;
return (v128_t) __builtin_convertvector(__v, __u16x8);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i32x4_load_16x4(const void *__mem) {
- typedef int16_t __i16x4 __attribute__((__vector_size__(8), __aligned__(8)));
- struct __wasm_i32x4_load_16x4_struct {
+wasm_i32x4_load16x4(const void *__mem) {
+ struct __wasm_i32x4_load16x4_struct {
__i16x4 __v;
} __attribute__((__packed__, __may_alias__));
- __i16x4 __v = ((const struct __wasm_i32x4_load_16x4_struct *)__mem)->__v;
+ __i16x4 __v = ((const struct __wasm_i32x4_load16x4_struct *)__mem)->__v;
return (v128_t) __builtin_convertvector(__v, __i32x4);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_u32x4_load_16x4(const void *__mem) {
- typedef uint16_t __u16x4 __attribute__((__vector_size__(8), __aligned__(8)));
- struct __wasm_u32x4_load_16x4_struct {
+wasm_u32x4_load16x4(const void *__mem) {
+ struct __wasm_u32x4_load16x4_struct {
__u16x4 __v;
} __attribute__((__packed__, __may_alias__));
- __u16x4 __v = ((const struct __wasm_u32x4_load_16x4_struct *)__mem)->__v;
+ __u16x4 __v = ((const struct __wasm_u32x4_load16x4_struct *)__mem)->__v;
return (v128_t) __builtin_convertvector(__v, __u32x4);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i64x2_load_32x2(const void *__mem) {
- typedef int32_t __i32x2 __attribute__((__vector_size__(8), __aligned__(8)));
- struct __wasm_i64x2_load_32x2_struct {
+wasm_i64x2_load32x2(const void *__mem) {
+ struct __wasm_i64x2_load32x2_struct {
__i32x2 __v;
} __attribute__((__packed__, __may_alias__));
- __i32x2 __v = ((const struct __wasm_i64x2_load_32x2_struct *)__mem)->__v;
+ __i32x2 __v = ((const struct __wasm_i64x2_load32x2_struct *)__mem)->__v;
return (v128_t) __builtin_convertvector(__v, __i64x2);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_u64x2_load_32x2(const void *__mem) {
- typedef uint32_t __u32x2 __attribute__((__vector_size__(8), __aligned__(8)));
- struct __wasm_u64x2_load_32x2_struct {
+wasm_u64x2_load32x2(const void *__mem) {
+ struct __wasm_u64x2_load32x2_struct {
__u32x2 __v;
} __attribute__((__packed__, __may_alias__));
- __u32x2 __v = ((const struct __wasm_u64x2_load_32x2_struct *)__mem)->__v;
+ __u32x2 __v = ((const struct __wasm_u64x2_load32x2_struct *)__mem)->__v;
return (v128_t) __builtin_convertvector(__v, __u64x2);
}
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_v128_load32_zero(const void *__mem) {
+ struct __wasm_v128_load32_zero_struct {
+ int32_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ int32_t __v = ((const struct __wasm_v128_load32_zero_struct *)__mem)->__v;
+ return (v128_t)(__i32x4){__v, 0, 0, 0};
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_v128_load64_zero(const void *__mem) {
+ struct __wasm_v128_load64_zero_struct {
+ int64_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ int64_t __v = ((const struct __wasm_v128_load64_zero_struct *)__mem)->__v;
+ return (v128_t)(__i64x2){__v, 0};
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load8_lane(
+ const void *__mem, v128_t __vec, int __i) __REQUIRE_CONSTANT(__i) {
+ struct __wasm_v128_load8_lane_struct {
+ int8_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ int8_t __v = ((const struct __wasm_v128_load8_lane_struct *)__mem)->__v;
+ __i8x16 __ret = (__i8x16)__vec;
+ __ret[__i] = __v;
+ return (v128_t)__ret;
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load16_lane(
+ const void *__mem, v128_t __vec, int __i) __REQUIRE_CONSTANT(__i) {
+ struct __wasm_v128_load16_lane_struct {
+ int16_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ int16_t __v = ((const struct __wasm_v128_load16_lane_struct *)__mem)->__v;
+ __i16x8 __ret = (__i16x8)__vec;
+ __ret[__i] = __v;
+ return (v128_t)__ret;
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load32_lane(
+ const void *__mem, v128_t __vec, int __i) __REQUIRE_CONSTANT(__i) {
+ struct __wasm_v128_load32_lane_struct {
+ int32_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ int32_t __v = ((const struct __wasm_v128_load32_lane_struct *)__mem)->__v;
+ __i32x4 __ret = (__i32x4)__vec;
+ __ret[__i] = __v;
+ return (v128_t)__ret;
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_load64_lane(
+ const void *__mem, v128_t __vec, int __i) __REQUIRE_CONSTANT(__i) {
+ struct __wasm_v128_load64_lane_struct {
+ int64_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ int64_t __v = ((const struct __wasm_v128_load64_lane_struct *)__mem)->__v;
+ __i64x2 __ret = (__i64x2)__vec;
+ __ret[__i] = __v;
+ return (v128_t)__ret;
+}
+
static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store(void *__mem,
v128_t __a) {
// UB-free unaligned access copied from xmmintrin.h
@@ -162,6 +223,49 @@
((struct __wasm_v128_store_struct *)__mem)->__v = __a;
}
+static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store8_lane(void *__mem,
+ v128_t __vec,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ struct __wasm_v128_store8_lane_struct {
+ int8_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __wasm_v128_store8_lane_struct *)__mem)->__v = ((__i8x16)__vec)[__i];
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store16_lane(void *__mem,
+ v128_t __vec,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ struct __wasm_v128_store16_lane_struct {
+ int16_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __wasm_v128_store16_lane_struct *)__mem)->__v =
+ ((__i16x8)__vec)[__i];
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store32_lane(void *__mem,
+ v128_t __vec,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ struct __wasm_v128_store32_lane_struct {
+ int32_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __wasm_v128_store32_lane_struct *)__mem)->__v =
+ ((__i32x4)__vec)[__i];
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS wasm_v128_store64_lane(void *__mem,
+ v128_t __vec,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ struct __wasm_v128_store64_lane_struct {
+ int64_t __v;
+ } __attribute__((__packed__, __may_alias__));
+ ((struct __wasm_v128_store64_lane_struct *)__mem)->__v =
+ ((__i64x2)__vec)[__i];
+}
+
static __inline__ v128_t __DEFAULT_FN_ATTRS
wasm_i8x16_make(int8_t __c0, int8_t __c1, int8_t __c2, int8_t __c3, int8_t __c4,
int8_t __c5, int8_t __c6, int8_t __c7, int8_t __c8, int8_t __c9,
@@ -185,6 +289,11 @@
return (v128_t)(__i32x4){__c0, __c1, __c2, __c3};
}
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_make(int64_t __c0,
+ int64_t __c1) {
+ return (v128_t)(__i64x2){__c0, __c1};
+}
+
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_make(float __c0,
float __c1,
float __c2,
@@ -192,150 +301,221 @@
return (v128_t)(__f32x4){__c0, __c1, __c2, __c3};
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_make(int64_t __c0,
- int64_t __c1) {
- return (v128_t)(__i64x2){__c0, __c1};
-}
-
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_make(double __c0,
double __c1) {
return (v128_t)(__f64x2){__c0, __c1};
}
-#define wasm_i8x16_const(__c0, __c1, __c2, __c3, __c4, __c5, __c6, __c7, __c8, \
- __c9, __c10, __c11, __c12, __c13, __c14, __c15) \
- __extension__({ \
- __REQUIRE_CONSTANT(__c0); \
- __REQUIRE_CONSTANT(__c1); \
- __REQUIRE_CONSTANT(__c2); \
- __REQUIRE_CONSTANT(__c3); \
- __REQUIRE_CONSTANT(__c4); \
- __REQUIRE_CONSTANT(__c5); \
- __REQUIRE_CONSTANT(__c6); \
- __REQUIRE_CONSTANT(__c7); \
- __REQUIRE_CONSTANT(__c8); \
- __REQUIRE_CONSTANT(__c9); \
- __REQUIRE_CONSTANT(__c10); \
- __REQUIRE_CONSTANT(__c11); \
- __REQUIRE_CONSTANT(__c12); \
- __REQUIRE_CONSTANT(__c13); \
- __REQUIRE_CONSTANT(__c14); \
- __REQUIRE_CONSTANT(__c15); \
- (v128_t)(__i8x16){__c0, __c1, __c2, __c3, __c4, __c5, __c6, __c7, \
- __c8, __c9, __c10, __c11, __c12, __c13, __c14, __c15}; \
- })
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i8x16_const(int8_t __c0, int8_t __c1, int8_t __c2, int8_t __c3,
+ int8_t __c4, int8_t __c5, int8_t __c6, int8_t __c7,
+ int8_t __c8, int8_t __c9, int8_t __c10, int8_t __c11,
+ int8_t __c12, int8_t __c13, int8_t __c14, int8_t __c15)
+ __REQUIRE_CONSTANT(__c0) __REQUIRE_CONSTANT(__c1) __REQUIRE_CONSTANT(__c2)
+ __REQUIRE_CONSTANT(__c3) __REQUIRE_CONSTANT(__c4)
+ __REQUIRE_CONSTANT(__c5) __REQUIRE_CONSTANT(__c6)
+ __REQUIRE_CONSTANT(__c7) __REQUIRE_CONSTANT(__c8)
+ __REQUIRE_CONSTANT(__c9) __REQUIRE_CONSTANT(__c10)
+ __REQUIRE_CONSTANT(__c11) __REQUIRE_CONSTANT(__c12)
+ __REQUIRE_CONSTANT(__c13) __REQUIRE_CONSTANT(__c14)
+ __REQUIRE_CONSTANT(__c15) {
+ return (v128_t)(__i8x16){__c0, __c1, __c2, __c3, __c4, __c5,
+ __c6, __c7, __c8, __c9, __c10, __c11,
+ __c12, __c13, __c14, __c15};
+}
-#define wasm_i16x8_const(__c0, __c1, __c2, __c3, __c4, __c5, __c6, __c7) \
- __extension__({ \
- __REQUIRE_CONSTANT(__c0); \
- __REQUIRE_CONSTANT(__c1); \
- __REQUIRE_CONSTANT(__c2); \
- __REQUIRE_CONSTANT(__c3); \
- __REQUIRE_CONSTANT(__c4); \
- __REQUIRE_CONSTANT(__c5); \
- __REQUIRE_CONSTANT(__c6); \
- __REQUIRE_CONSTANT(__c7); \
- (v128_t)(__i16x8){__c0, __c1, __c2, __c3, __c4, __c5, __c6, __c7}; \
- })
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i16x8_const(int16_t __c0, int16_t __c1, int16_t __c2, int16_t __c3,
+ int16_t __c4, int16_t __c5, int16_t __c6, int16_t __c7)
+ __REQUIRE_CONSTANT(__c0) __REQUIRE_CONSTANT(__c1) __REQUIRE_CONSTANT(__c2)
+ __REQUIRE_CONSTANT(__c3) __REQUIRE_CONSTANT(__c4)
+ __REQUIRE_CONSTANT(__c5) __REQUIRE_CONSTANT(__c6)
+ __REQUIRE_CONSTANT(__c7) {
+ return (v128_t)(__i16x8){__c0, __c1, __c2, __c3, __c4, __c5, __c6, __c7};
+}
-#define wasm_i32x4_const(__c0, __c1, __c2, __c3) \
- __extension__({ \
- __REQUIRE_CONSTANT(__c0); \
- __REQUIRE_CONSTANT(__c1); \
- __REQUIRE_CONSTANT(__c2); \
- __REQUIRE_CONSTANT(__c3); \
- (v128_t)(__i32x4){__c0, __c1, __c2, __c3}; \
- })
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i32x4_const(int32_t __c0, int32_t __c1, int32_t __c2, int32_t __c3)
+ __REQUIRE_CONSTANT(__c0) __REQUIRE_CONSTANT(__c1) __REQUIRE_CONSTANT(__c2)
+ __REQUIRE_CONSTANT(__c3) {
+ return (v128_t)(__i32x4){__c0, __c1, __c2, __c3};
+}
-#define wasm_f32x4_const(__c0, __c1, __c2, __c3) \
- __extension__({ \
- __REQUIRE_CONSTANT(__c0); \
- __REQUIRE_CONSTANT(__c1); \
- __REQUIRE_CONSTANT(__c2); \
- __REQUIRE_CONSTANT(__c3); \
- (v128_t)(__f32x4){__c0, __c1, __c2, __c3}; \
- })
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_const(int64_t __c0,
+ int64_t __c1)
+ __REQUIRE_CONSTANT(__c0) __REQUIRE_CONSTANT(__c1) {
+ return (v128_t)(__i64x2){__c0, __c1};
+}
-#define wasm_i64x2_const(__c0, __c1) \
- __extension__({ \
- __REQUIRE_CONSTANT(__c0); \
- __REQUIRE_CONSTANT(__c1); \
- (v128_t)(__i64x2){__c0, __c1}; \
- })
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_f32x4_const(float __c0, float __c1, float __c2, float __c3)
+ __REQUIRE_CONSTANT(__c0) __REQUIRE_CONSTANT(__c1) __REQUIRE_CONSTANT(__c2)
+ __REQUIRE_CONSTANT(__c3) {
+ return (v128_t)(__f32x4){__c0, __c1, __c2, __c3};
+}
-#define wasm_f64x2_const(__c0, __c1) \
- __extension__({ \
- __REQUIRE_CONSTANT(__c0); \
- __REQUIRE_CONSTANT(__c1); \
- (v128_t)(__f64x2){__c0, __c1}; \
- })
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_const(double __c0,
+ double __c1)
+ __REQUIRE_CONSTANT(__c0) __REQUIRE_CONSTANT(__c1) {
+ return (v128_t)(__f64x2){__c0, __c1};
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_const_splat(int8_t __c)
+ __REQUIRE_CONSTANT(__c) {
+ return (v128_t)(__i8x16){__c, __c, __c, __c, __c, __c, __c, __c,
+ __c, __c, __c, __c, __c, __c, __c, __c};
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i16x8_const_splat(int16_t __c)
+ __REQUIRE_CONSTANT(__c) {
+ return (v128_t)(__i16x8){__c, __c, __c, __c, __c, __c, __c, __c};
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i32x4_const_splat(int32_t __c)
+ __REQUIRE_CONSTANT(__c) {
+ return (v128_t)(__i32x4){__c, __c, __c, __c};
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_const_splat(int64_t __c)
+ __REQUIRE_CONSTANT(__c) {
+ return (v128_t)(__i64x2){__c, __c};
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_const_splat(float __c)
+ __REQUIRE_CONSTANT(__c) {
+ return (v128_t)(__f32x4){__c, __c, __c, __c};
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_const_splat(double __c)
+ __REQUIRE_CONSTANT(__c) {
+ return (v128_t)(__f64x2){__c, __c};
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_splat(int8_t __a) {
return (v128_t)(__i8x16){__a, __a, __a, __a, __a, __a, __a, __a,
__a, __a, __a, __a, __a, __a, __a, __a};
}
-#define wasm_i8x16_extract_lane(__a, __i) \
- (__builtin_wasm_extract_lane_s_i8x16((__i8x16)(__a), __i))
+static __inline__ int8_t __DEFAULT_FN_ATTRS wasm_i8x16_extract_lane(v128_t __a,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ return ((__i8x16)__a)[__i];
+}
-#define wasm_u8x16_extract_lane(__a, __i) \
- (__builtin_wasm_extract_lane_u_i8x16((__u8x16)(__a), __i))
+static __inline__ uint8_t __DEFAULT_FN_ATTRS wasm_u8x16_extract_lane(v128_t __a,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ return ((__u8x16)__a)[__i];
+}
-#define wasm_i8x16_replace_lane(__a, __i, __b) \
- ((v128_t)__builtin_wasm_replace_lane_i8x16((__i8x16)(__a), __i, __b))
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_replace_lane(v128_t __a,
+ int __i,
+ int8_t __b)
+ __REQUIRE_CONSTANT(__i) {
+ __i8x16 __v = (__i8x16)__a;
+ __v[__i] = __b;
+ return (v128_t)__v;
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i16x8_splat(int16_t __a) {
return (v128_t)(__i16x8){__a, __a, __a, __a, __a, __a, __a, __a};
}
-#define wasm_i16x8_extract_lane(__a, __i) \
- (__builtin_wasm_extract_lane_s_i16x8((__i16x8)(__a), __i))
+static __inline__ int16_t __DEFAULT_FN_ATTRS wasm_i16x8_extract_lane(v128_t __a,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ return ((__i16x8)__a)[__i];
+}
-#define wasm_u16x8_extract_lane(__a, __i) \
- (__builtin_wasm_extract_lane_u_i16x8((__u16x8)(__a), __i))
+static __inline__ uint16_t __DEFAULT_FN_ATTRS
+wasm_u16x8_extract_lane(v128_t __a, int __i) __REQUIRE_CONSTANT(__i) {
+ return ((__u16x8)__a)[__i];
+}
-#define wasm_i16x8_replace_lane(__a, __i, __b) \
- ((v128_t)__builtin_wasm_replace_lane_i16x8((__i16x8)(__a), __i, __b))
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i16x8_replace_lane(v128_t __a,
+ int __i,
+ int16_t __b)
+ __REQUIRE_CONSTANT(__i) {
+ __i16x8 __v = (__i16x8)__a;
+ __v[__i] = __b;
+ return (v128_t)__v;
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i32x4_splat(int32_t __a) {
return (v128_t)(__i32x4){__a, __a, __a, __a};
}
-#define wasm_i32x4_extract_lane(__a, __i) \
- (__builtin_wasm_extract_lane_i32x4((__i32x4)(__a), __i))
+static __inline__ int32_t __DEFAULT_FN_ATTRS wasm_i32x4_extract_lane(v128_t __a,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ return ((__i32x4)__a)[__i];
+}
-#define wasm_i32x4_replace_lane(__a, __i, __b) \
- ((v128_t)__builtin_wasm_replace_lane_i32x4((__i32x4)(__a), __i, __b))
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i32x4_replace_lane(v128_t __a,
+ int __i,
+ int32_t __b)
+ __REQUIRE_CONSTANT(__i) {
+ __i32x4 __v = (__i32x4)__a;
+ __v[__i] = __b;
+ return (v128_t)__v;
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_splat(int64_t __a) {
return (v128_t)(__i64x2){__a, __a};
}
-#define wasm_i64x2_extract_lane(__a, __i) \
- (__builtin_wasm_extract_lane_i64x2((__i64x2)(__a), __i))
+static __inline__ int64_t __DEFAULT_FN_ATTRS wasm_i64x2_extract_lane(v128_t __a,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ return ((__i64x2)__a)[__i];
+}
-#define wasm_i64x2_replace_lane(__a, __i, __b) \
- ((v128_t)__builtin_wasm_replace_lane_i64x2((__i64x2)(__a), __i, __b))
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_replace_lane(v128_t __a,
+ int __i,
+ int64_t __b)
+ __REQUIRE_CONSTANT(__i) {
+ __i64x2 __v = (__i64x2)__a;
+ __v[__i] = __b;
+ return (v128_t)__v;
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_splat(float __a) {
return (v128_t)(__f32x4){__a, __a, __a, __a};
}
-#define wasm_f32x4_extract_lane(__a, __i) \
- (__builtin_wasm_extract_lane_f32x4((__f32x4)(__a), __i))
+static __inline__ float __DEFAULT_FN_ATTRS wasm_f32x4_extract_lane(v128_t __a,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ return ((__f32x4)__a)[__i];
+}
-#define wasm_f32x4_replace_lane(__a, __i, __b) \
- ((v128_t)__builtin_wasm_replace_lane_f32x4((__f32x4)(__a), __i, __b))
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_replace_lane(v128_t __a,
+ int __i,
+ float __b)
+ __REQUIRE_CONSTANT(__i) {
+ __f32x4 __v = (__f32x4)__a;
+ __v[__i] = __b;
+ return (v128_t)__v;
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_splat(double __a) {
return (v128_t)(__f64x2){__a, __a};
}
-#define wasm_f64x2_extract_lane(__a, __i) \
- (__builtin_wasm_extract_lane_f64x2((__f64x2)(__a), __i))
+static __inline__ double __DEFAULT_FN_ATTRS wasm_f64x2_extract_lane(v128_t __a,
+ int __i)
+ __REQUIRE_CONSTANT(__i) {
+ return ((__f64x2)__a)[__i];
+}
-#define wasm_f64x2_replace_lane(__a, __i, __b) \
- ((v128_t)__builtin_wasm_replace_lane_f64x2((__f64x2)(__a), __i, __b))
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_replace_lane(v128_t __a,
+ int __i,
+ double __b)
+ __REQUIRE_CONSTANT(__i) {
+ __f64x2 __v = (__f64x2)__a;
+ __v[__i] = __b;
+ return (v128_t)__v;
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_eq(v128_t __a,
v128_t __b) {
@@ -487,6 +667,36 @@
return (v128_t)((__u32x4)__a >= (__u32x4)__b);
}
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_eq(v128_t __a,
+ v128_t __b) {
+ return (v128_t)((__i64x2)__a == (__i64x2)__b);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_ne(v128_t __a,
+ v128_t __b) {
+ return (v128_t)((__i64x2)__a != (__i64x2)__b);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_lt(v128_t __a,
+ v128_t __b) {
+ return (v128_t)((__i64x2)__a < (__i64x2)__b);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_gt(v128_t __a,
+ v128_t __b) {
+ return (v128_t)((__i64x2)__a > (__i64x2)__b);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_le(v128_t __a,
+ v128_t __b) {
+ return (v128_t)((__i64x2)__a <= (__i64x2)__b);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_ge(v128_t __a,
+ v128_t __b) {
+ return (v128_t)((__i64x2)__a >= (__i64x2)__b);
+}
+
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_eq(v128_t __a,
v128_t __b) {
return (v128_t)((__f32x4)__a == (__f32x4)__b);
@@ -571,6 +781,10 @@
return __a & ~__b;
}
+static __inline__ bool __DEFAULT_FN_ATTRS wasm_v128_any_true(v128_t __a) {
+ return __builtin_wasm_any_true_v128((__i8x16)__a);
+}
+
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v128_bitselect(v128_t __a,
v128_t __b,
v128_t __mask) {
@@ -586,14 +800,18 @@
return (v128_t)(-(__u8x16)__a);
}
-static __inline__ bool __DEFAULT_FN_ATTRS wasm_i8x16_any_true(v128_t __a) {
- return __builtin_wasm_any_true_i8x16((__i8x16)__a);
-}
-
static __inline__ bool __DEFAULT_FN_ATTRS wasm_i8x16_all_true(v128_t __a) {
return __builtin_wasm_all_true_i8x16((__i8x16)__a);
}
+static __inline__ int32_t __DEFAULT_FN_ATTRS wasm_i8x16_bitmask(v128_t __a) {
+ return __builtin_wasm_bitmask_i8x16((__i8x16)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_popcnt(v128_t __a) {
+ return (v128_t)__builtin_wasm_popcnt_i8x16((__i8x16)__a);
+}
+
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_shl(v128_t __a,
int32_t __b) {
return (v128_t)((__i8x16)__a << __b);
@@ -614,13 +832,13 @@
return (v128_t)((__u8x16)__a + (__u8x16)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i8x16_add_saturate(v128_t __a, v128_t __b) {
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_add_sat(v128_t __a,
+ v128_t __b) {
return (v128_t)__builtin_wasm_add_sat_s_i8x16((__i8x16)__a, (__i8x16)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_u8x16_add_saturate(v128_t __a, v128_t __b) {
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_u8x16_add_sat(v128_t __a,
+ v128_t __b) {
return (v128_t)__builtin_wasm_add_sat_u_i8x16((__u8x16)__a, (__u8x16)__b);
}
@@ -629,13 +847,13 @@
return (v128_t)((__u8x16)__a - (__u8x16)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i8x16_sub_saturate(v128_t __a, v128_t __b) {
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_sub_sat(v128_t __a,
+ v128_t __b) {
return (v128_t)__builtin_wasm_sub_sat_s_i8x16((__i8x16)__a, (__i8x16)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_u8x16_sub_saturate(v128_t __a, v128_t __b) {
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_u8x16_sub_sat(v128_t __a,
+ v128_t __b) {
return (v128_t)__builtin_wasm_sub_sat_u_i8x16((__u8x16)__a, (__u8x16)__b);
}
@@ -672,14 +890,14 @@
return (v128_t)(-(__u16x8)__a);
}
-static __inline__ bool __DEFAULT_FN_ATTRS wasm_i16x8_any_true(v128_t __a) {
- return __builtin_wasm_any_true_i16x8((__i16x8)__a);
-}
-
static __inline__ bool __DEFAULT_FN_ATTRS wasm_i16x8_all_true(v128_t __a) {
return __builtin_wasm_all_true_i16x8((__i16x8)__a);
}
+static __inline__ int32_t __DEFAULT_FN_ATTRS wasm_i16x8_bitmask(v128_t __a) {
+ return __builtin_wasm_bitmask_i16x8((__i16x8)__a);
+}
+
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i16x8_shl(v128_t __a,
int32_t __b) {
return (v128_t)((__i16x8)__a << __b);
@@ -700,13 +918,13 @@
return (v128_t)((__u16x8)__a + (__u16x8)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i16x8_add_saturate(v128_t __a, v128_t __b) {
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i16x8_add_sat(v128_t __a,
+ v128_t __b) {
return (v128_t)__builtin_wasm_add_sat_s_i16x8((__i16x8)__a, (__i16x8)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_u16x8_add_saturate(v128_t __a, v128_t __b) {
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_u16x8_add_sat(v128_t __a,
+ v128_t __b) {
return (v128_t)__builtin_wasm_add_sat_u_i16x8((__u16x8)__a, (__u16x8)__b);
}
@@ -715,13 +933,13 @@
return (v128_t)((__i16x8)__a - (__i16x8)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i16x8_sub_saturate(v128_t __a, v128_t __b) {
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i16x8_sub_sat(v128_t __a,
+ v128_t __b) {
return (v128_t)__builtin_wasm_sub_sat_s_i16x8((__i16x8)__a, (__i16x8)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_u16x8_sub_saturate(v128_t __a, v128_t __b) {
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_u16x8_sub_sat(v128_t __a,
+ v128_t __b) {
return (v128_t)__builtin_wasm_sub_sat_u_i16x8((__u16x8)__a, (__u16x8)__b);
}
@@ -763,14 +981,14 @@
return (v128_t)(-(__u32x4)__a);
}
-static __inline__ bool __DEFAULT_FN_ATTRS wasm_i32x4_any_true(v128_t __a) {
- return __builtin_wasm_any_true_i32x4((__i32x4)__a);
-}
-
static __inline__ bool __DEFAULT_FN_ATTRS wasm_i32x4_all_true(v128_t __a) {
return __builtin_wasm_all_true_i32x4((__i32x4)__a);
}
+static __inline__ int32_t __DEFAULT_FN_ATTRS wasm_i32x4_bitmask(v128_t __a) {
+ return __builtin_wasm_bitmask_i32x4((__i32x4)__a);
+}
+
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i32x4_shl(v128_t __a,
int32_t __b) {
return (v128_t)((__i32x4)__a << __b);
@@ -821,21 +1039,26 @@
return (v128_t)__builtin_wasm_max_u_i32x4((__u32x4)__a, (__u32x4)__b);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_neg(v128_t __a) {
- return (v128_t)(-(__u64x2)__a);
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i32x4_dot_i16x8(v128_t __a,
+ v128_t __b) {
+ return (v128_t)__builtin_wasm_dot_s_i32x4_i16x8((__i16x8)__a, (__i16x8)__b);
}
-#ifdef __wasm_unimplemented_simd128__
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_abs(v128_t __a) {
+ return (v128_t)__builtin_wasm_abs_i64x2((__i64x2)__a);
+}
-static __inline__ bool __DEFAULT_FN_ATTRS wasm_i64x2_any_true(v128_t __a) {
- return __builtin_wasm_any_true_i64x2((__i64x2)__a);
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_neg(v128_t __a) {
+ return (v128_t)(-(__u64x2)__a);
}
static __inline__ bool __DEFAULT_FN_ATTRS wasm_i64x2_all_true(v128_t __a) {
return __builtin_wasm_all_true_i64x2((__i64x2)__a);
}
-#endif // __wasm_unimplemented_simd128__
+static __inline__ int32_t __DEFAULT_FN_ATTRS wasm_i64x2_bitmask(v128_t __a) {
+ return __builtin_wasm_bitmask_i64x2((__i64x2)__a);
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i64x2_shl(v128_t __a,
int32_t __b) {
@@ -879,23 +1102,21 @@
return (v128_t)__builtin_wasm_sqrt_f32x4((__f32x4)__a);
}
-#ifdef __wasm_unimplemented_simd128__
-
-static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_qfma(v128_t __a,
- v128_t __b,
- v128_t __c) {
- return (v128_t)__builtin_wasm_qfma_f32x4((__f32x4)__a, (__f32x4)__b,
- (__f32x4)__c);
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_ceil(v128_t __a) {
+ return (v128_t)__builtin_wasm_ceil_f32x4((__f32x4)__a);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_qfms(v128_t __a,
- v128_t __b,
- v128_t __c) {
- return (v128_t)__builtin_wasm_qfms_f32x4((__f32x4)__a, (__f32x4)__b,
- (__f32x4)__c);
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_floor(v128_t __a) {
+ return (v128_t)__builtin_wasm_floor_f32x4((__f32x4)__a);
}
-#endif // __wasm_unimplemented_simd128__
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_trunc(v128_t __a) {
+ return (v128_t)__builtin_wasm_trunc_f32x4((__f32x4)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_nearest(v128_t __a) {
+ return (v128_t)__builtin_wasm_nearest_f32x4((__f32x4)__a);
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_add(v128_t __a,
v128_t __b) {
@@ -929,12 +1150,14 @@
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_pmin(v128_t __a,
v128_t __b) {
- return (v128_t)__builtin_wasm_pmin_f32x4((__f32x4)__a, (__f32x4)__b);
+ __i32x4 __mask = (__i32x4)((__f32x4)__b < (__f32x4)__a);
+ return (v128_t)((((__i32x4)__b) & __mask) | (((__i32x4)__a) & ~__mask));
}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f32x4_pmax(v128_t __a,
v128_t __b) {
- return (v128_t)__builtin_wasm_pmax_f32x4((__f32x4)__a, (__f32x4)__b);
+ __i32x4 __mask = (__i32x4)((__f32x4)__a < (__f32x4)__b);
+ return (v128_t)((((__i32x4)__b) & __mask) | (((__i32x4)__a) & ~__mask));
}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_abs(v128_t __a) {
@@ -949,23 +1172,21 @@
return (v128_t)__builtin_wasm_sqrt_f64x2((__f64x2)__a);
}
-#ifdef __wasm_unimplemented_simd128__
-
-static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_qfma(v128_t __a,
- v128_t __b,
- v128_t __c) {
- return (v128_t)__builtin_wasm_qfma_f64x2((__f64x2)__a, (__f64x2)__b,
- (__f64x2)__c);
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_ceil(v128_t __a) {
+ return (v128_t)__builtin_wasm_ceil_f64x2((__f64x2)__a);
}
-static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_qfms(v128_t __a,
- v128_t __b,
- v128_t __c) {
- return (v128_t)__builtin_wasm_qfms_f64x2((__f64x2)__a, (__f64x2)__b,
- (__f64x2)__c);
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_floor(v128_t __a) {
+ return (v128_t)__builtin_wasm_floor_f64x2((__f64x2)__a);
}
-#endif // __wasm_unimplemented_simd128__
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_trunc(v128_t __a) {
+ return (v128_t)__builtin_wasm_trunc_f64x2((__f64x2)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_nearest(v128_t __a) {
+ return (v128_t)__builtin_wasm_nearest_f64x2((__f64x2)__a);
+}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_add(v128_t __a,
v128_t __b) {
@@ -999,21 +1220,23 @@
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_pmin(v128_t __a,
v128_t __b) {
- return (v128_t)__builtin_wasm_pmin_f64x2((__f64x2)__a, (__f64x2)__b);
+ __i64x2 __mask = (__i64x2)((__f64x2)__b < (__f64x2)__a);
+ return (v128_t)((((__i64x2)__b) & __mask) | (((__i64x2)__a) & ~__mask));
}
static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_f64x2_pmax(v128_t __a,
v128_t __b) {
- return (v128_t)__builtin_wasm_pmax_f64x2((__f64x2)__a, (__f64x2)__b);
+ __i64x2 __mask = (__i64x2)((__f64x2)__a < (__f64x2)__b);
+ return (v128_t)((((__i64x2)__b) & __mask) | (((__i64x2)__a) & ~__mask));
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i32x4_trunc_saturate_f32x4(v128_t __a) {
+wasm_i32x4_trunc_sat_f32x4(v128_t __a) {
return (v128_t)__builtin_wasm_trunc_saturate_s_i32x4_f32x4((__f32x4)__a);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_u32x4_trunc_saturate_f32x4(v128_t __a) {
+wasm_u32x4_trunc_sat_f32x4(v128_t __a) {
return (v128_t)__builtin_wasm_trunc_saturate_u_i32x4_f32x4((__f32x4)__a);
}
@@ -1027,38 +1250,71 @@
return (v128_t) __builtin_convertvector((__u32x4)__a, __f32x4);
}
-#define wasm_v8x16_shuffle(__a, __b, __c0, __c1, __c2, __c3, __c4, __c5, __c6, \
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_f64x2_convert_low_i32x4(v128_t __a) {
+ return (v128_t) __builtin_convertvector((__i32x2){__a[0], __a[1]}, __f64x2);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_f64x2_convert_low_u32x4(v128_t __a) {
+ return (v128_t) __builtin_convertvector((__u32x2){__a[0], __a[1]}, __f64x2);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i32x4_trunc_sat_f64x2_zero(v128_t __a) {
+ return (v128_t)__builtin_wasm_trunc_sat_zero_s_f64x2_i32x4((__f64x2)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u32x4_trunc_sat_f64x2_zero(v128_t __a) {
+ return (v128_t)__builtin_wasm_trunc_sat_zero_u_f64x2_i32x4((__f64x2)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_f32x4_demote_f64x2_zero(v128_t __a) {
+ return (v128_t) __builtin_convertvector(
+ __builtin_shufflevector((__f64x2)__a, (__f64x2){0, 0}, 0, 1, 2, 3),
+ __f32x4);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_f64x2_promote_low_f32x4(v128_t __a) {
+ return (v128_t) __builtin_convertvector(
+ (__f32x2){((__f32x4)__a)[0], ((__f32x4)__a)[1]}, __f64x2);
+}
+
+#define wasm_i8x16_shuffle(__a, __b, __c0, __c1, __c2, __c3, __c4, __c5, __c6, \
__c7, __c8, __c9, __c10, __c11, __c12, __c13, \
__c14, __c15) \
- ((v128_t)__builtin_wasm_shuffle_v8x16( \
+ ((v128_t)__builtin_wasm_shuffle_i8x16( \
(__i8x16)(__a), (__i8x16)(__b), __c0, __c1, __c2, __c3, __c4, __c5, \
__c6, __c7, __c8, __c9, __c10, __c11, __c12, __c13, __c14, __c15))
-#define wasm_v16x8_shuffle(__a, __b, __c0, __c1, __c2, __c3, __c4, __c5, __c6, \
+#define wasm_i16x8_shuffle(__a, __b, __c0, __c1, __c2, __c3, __c4, __c5, __c6, \
__c7) \
- ((v128_t)__builtin_wasm_shuffle_v8x16( \
+ ((v128_t)__builtin_wasm_shuffle_i8x16( \
(__i8x16)(__a), (__i8x16)(__b), (__c0)*2, (__c0)*2 + 1, (__c1)*2, \
(__c1)*2 + 1, (__c2)*2, (__c2)*2 + 1, (__c3)*2, (__c3)*2 + 1, (__c4)*2, \
(__c4)*2 + 1, (__c5)*2, (__c5)*2 + 1, (__c6)*2, (__c6)*2 + 1, (__c7)*2, \
(__c7)*2 + 1))
-#define wasm_v32x4_shuffle(__a, __b, __c0, __c1, __c2, __c3) \
- ((v128_t)__builtin_wasm_shuffle_v8x16( \
+#define wasm_i32x4_shuffle(__a, __b, __c0, __c1, __c2, __c3) \
+ ((v128_t)__builtin_wasm_shuffle_i8x16( \
(__i8x16)(__a), (__i8x16)(__b), (__c0)*4, (__c0)*4 + 1, (__c0)*4 + 2, \
(__c0)*4 + 3, (__c1)*4, (__c1)*4 + 1, (__c1)*4 + 2, (__c1)*4 + 3, \
(__c2)*4, (__c2)*4 + 1, (__c2)*4 + 2, (__c2)*4 + 3, (__c3)*4, \
(__c3)*4 + 1, (__c3)*4 + 2, (__c3)*4 + 3))
-#define wasm_v64x2_shuffle(__a, __b, __c0, __c1) \
- ((v128_t)__builtin_wasm_shuffle_v8x16( \
+#define wasm_i64x2_shuffle(__a, __b, __c0, __c1) \
+ ((v128_t)__builtin_wasm_shuffle_i8x16( \
(__i8x16)(__a), (__i8x16)(__b), (__c0)*8, (__c0)*8 + 1, (__c0)*8 + 2, \
(__c0)*8 + 3, (__c0)*8 + 4, (__c0)*8 + 5, (__c0)*8 + 6, (__c0)*8 + 7, \
(__c1)*8, (__c1)*8 + 1, (__c1)*8 + 2, (__c1)*8 + 3, (__c1)*8 + 4, \
(__c1)*8 + 5, (__c1)*8 + 6, (__c1)*8 + 7))
-static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_v8x16_swizzle(v128_t __a,
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i8x16_swizzle(v128_t __a,
v128_t __b) {
- return (v128_t)__builtin_wasm_swizzle_v8x16((__i8x16)__a, (__i8x16)__b);
+ return (v128_t)__builtin_wasm_swizzle_i8x16((__i8x16)__a, (__i8x16)__b);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
@@ -1069,8 +1325,8 @@
static __inline__ v128_t __DEFAULT_FN_ATTRS
wasm_u8x16_narrow_i16x8(v128_t __a, v128_t __b) {
- return (v128_t)__builtin_wasm_narrow_u_i8x16_i16x8((__u16x8)__a,
- (__u16x8)__b);
+ return (v128_t)__builtin_wasm_narrow_u_i8x16_i16x8((__i16x8)__a,
+ (__i16x8)__b);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
@@ -1081,12 +1337,12 @@
static __inline__ v128_t __DEFAULT_FN_ATTRS
wasm_u16x8_narrow_i32x4(v128_t __a, v128_t __b) {
- return (v128_t)__builtin_wasm_narrow_u_i16x8_i32x4((__u32x4)__a,
- (__u32x4)__b);
+ return (v128_t)__builtin_wasm_narrow_u_i16x8_i32x4((__i32x4)__a,
+ (__i32x4)__b);
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i16x8_widen_low_i8x16(v128_t __a) {
+wasm_i16x8_extend_low_i8x16(v128_t __a) {
return (v128_t) __builtin_convertvector(
(__i8x8){((__i8x16)__a)[0], ((__i8x16)__a)[1], ((__i8x16)__a)[2],
((__i8x16)__a)[3], ((__i8x16)__a)[4], ((__i8x16)__a)[5],
@@ -1095,7 +1351,7 @@
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i16x8_widen_high_i8x16(v128_t __a) {
+wasm_i16x8_extend_high_i8x16(v128_t __a) {
return (v128_t) __builtin_convertvector(
(__i8x8){((__i8x16)__a)[8], ((__i8x16)__a)[9], ((__i8x16)__a)[10],
((__i8x16)__a)[11], ((__i8x16)__a)[12], ((__i8x16)__a)[13],
@@ -1104,7 +1360,7 @@
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i16x8_widen_low_u8x16(v128_t __a) {
+wasm_u16x8_extend_low_u8x16(v128_t __a) {
return (v128_t) __builtin_convertvector(
(__u8x8){((__u8x16)__a)[0], ((__u8x16)__a)[1], ((__u8x16)__a)[2],
((__u8x16)__a)[3], ((__u8x16)__a)[4], ((__u8x16)__a)[5],
@@ -1113,7 +1369,7 @@
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i16x8_widen_high_u8x16(v128_t __a) {
+wasm_u16x8_extend_high_u8x16(v128_t __a) {
return (v128_t) __builtin_convertvector(
(__u8x8){((__u8x16)__a)[8], ((__u8x16)__a)[9], ((__u8x16)__a)[10],
((__u8x16)__a)[11], ((__u8x16)__a)[12], ((__u8x16)__a)[13],
@@ -1122,7 +1378,7 @@
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i32x4_widen_low_i16x8(v128_t __a) {
+wasm_i32x4_extend_low_i16x8(v128_t __a) {
return (v128_t) __builtin_convertvector(
(__i16x4){((__i16x8)__a)[0], ((__i16x8)__a)[1], ((__i16x8)__a)[2],
((__i16x8)__a)[3]},
@@ -1130,7 +1386,7 @@
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i32x4_widen_high_i16x8(v128_t __a) {
+wasm_i32x4_extend_high_i16x8(v128_t __a) {
return (v128_t) __builtin_convertvector(
(__i16x4){((__i16x8)__a)[4], ((__i16x8)__a)[5], ((__i16x8)__a)[6],
((__i16x8)__a)[7]},
@@ -1138,7 +1394,7 @@
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i32x4_widen_low_u16x8(v128_t __a) {
+wasm_u32x4_extend_low_u16x8(v128_t __a) {
return (v128_t) __builtin_convertvector(
(__u16x4){((__u16x8)__a)[0], ((__u16x8)__a)[1], ((__u16x8)__a)[2],
((__u16x8)__a)[3]},
@@ -1146,14 +1402,333 @@
}
static __inline__ v128_t __DEFAULT_FN_ATTRS
-wasm_i32x4_widen_high_u16x8(v128_t __a) {
+wasm_u32x4_extend_high_u16x8(v128_t __a) {
return (v128_t) __builtin_convertvector(
(__u16x4){((__u16x8)__a)[4], ((__u16x8)__a)[5], ((__u16x8)__a)[6],
((__u16x8)__a)[7]},
__u32x4);
}
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i64x2_extend_low_i32x4(v128_t __a) {
+ return (v128_t) __builtin_convertvector(
+ (__i32x2){((__i32x4)__a)[0], ((__i32x4)__a)[1]}, __i64x2);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i64x2_extend_high_i32x4(v128_t __a) {
+ return (v128_t) __builtin_convertvector(
+ (__i32x2){((__i32x4)__a)[2], ((__i32x4)__a)[3]}, __i64x2);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u64x2_extend_low_u32x4(v128_t __a) {
+ return (v128_t) __builtin_convertvector(
+ (__u32x2){((__u32x4)__a)[0], ((__u32x4)__a)[1]}, __u64x2);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u64x2_extend_high_u32x4(v128_t __a) {
+ return (v128_t) __builtin_convertvector(
+ (__u32x2){((__u32x4)__a)[2], ((__u32x4)__a)[3]}, __u64x2);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i16x8_extadd_pairwise_i8x16(v128_t __a) {
+ return (v128_t)__builtin_wasm_extadd_pairwise_i8x16_s_i16x8((__i8x16)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u16x8_extadd_pairwise_u8x16(v128_t __a) {
+ return (v128_t)__builtin_wasm_extadd_pairwise_i8x16_u_i16x8((__u8x16)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i32x4_extadd_pairwise_i16x8(v128_t __a) {
+ return (v128_t)__builtin_wasm_extadd_pairwise_i16x8_s_i32x4((__i16x8)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u32x4_extadd_pairwise_u16x8(v128_t __a) {
+ return (v128_t)__builtin_wasm_extadd_pairwise_i16x8_u_i32x4((__u16x8)__a);
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i16x8_extmul_low_i8x16(v128_t __a, v128_t __b) {
+ return (v128_t)((__i16x8)wasm_i16x8_extend_low_i8x16(__a) *
+ (__i16x8)wasm_i16x8_extend_low_i8x16(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i16x8_extmul_high_i8x16(v128_t __a, v128_t __b) {
+ return (v128_t)((__i16x8)wasm_i16x8_extend_high_i8x16(__a) *
+ (__i16x8)wasm_i16x8_extend_high_i8x16(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u16x8_extmul_low_u8x16(v128_t __a, v128_t __b) {
+ return (v128_t)((__u16x8)wasm_u16x8_extend_low_u8x16(__a) *
+ (__u16x8)wasm_u16x8_extend_low_u8x16(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u16x8_extmul_high_u8x16(v128_t __a, v128_t __b) {
+ return (v128_t)((__u16x8)wasm_u16x8_extend_high_u8x16(__a) *
+ (__u16x8)wasm_u16x8_extend_high_u8x16(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i32x4_extmul_low_i16x8(v128_t __a, v128_t __b) {
+ return (v128_t)((__i32x4)wasm_i32x4_extend_low_i16x8(__a) *
+ (__i32x4)wasm_i32x4_extend_low_i16x8(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i32x4_extmul_high_i16x8(v128_t __a, v128_t __b) {
+ return (v128_t)((__i32x4)wasm_i32x4_extend_high_i16x8(__a) *
+ (__i32x4)wasm_i32x4_extend_high_i16x8(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u32x4_extmul_low_u16x8(v128_t __a, v128_t __b) {
+ return (v128_t)((__u32x4)wasm_u32x4_extend_low_u16x8(__a) *
+ (__u32x4)wasm_u32x4_extend_low_u16x8(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u32x4_extmul_high_u16x8(v128_t __a, v128_t __b) {
+ return (v128_t)((__u32x4)wasm_u32x4_extend_high_u16x8(__a) *
+ (__u32x4)wasm_u32x4_extend_high_u16x8(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i64x2_extmul_low_i32x4(v128_t __a, v128_t __b) {
+ return (v128_t)((__i64x2)wasm_i64x2_extend_low_i32x4(__a) *
+ (__i64x2)wasm_i64x2_extend_low_i32x4(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_i64x2_extmul_high_i32x4(v128_t __a, v128_t __b) {
+ return (v128_t)((__i64x2)wasm_i64x2_extend_high_i32x4(__a) *
+ (__i64x2)wasm_i64x2_extend_high_i32x4(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u64x2_extmul_low_u32x4(v128_t __a, v128_t __b) {
+ return (v128_t)((__u64x2)wasm_u64x2_extend_low_u32x4(__a) *
+ (__u64x2)wasm_u64x2_extend_low_u32x4(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS
+wasm_u64x2_extmul_high_u32x4(v128_t __a, v128_t __b) {
+ return (v128_t)((__u64x2)wasm_u64x2_extend_high_u32x4(__a) *
+ (__u64x2)wasm_u64x2_extend_high_u32x4(__b));
+}
+
+static __inline__ v128_t __DEFAULT_FN_ATTRS wasm_i16x8_q15mulr_sat(v128_t __a,
+ v128_t __b) {
+ return (v128_t)__builtin_wasm_q15mulr_sat_s_i16x8((__i16x8)__a, (__i16x8)__b);
+}
+
+// Old intrinsic names supported to ease transitioning to the standard names. Do
+// not use these; they will be removed in the near future.
+
+#define __DEPRECATED_FN_ATTRS(__replacement) \
+ __DEFAULT_FN_ATTRS __attribute__( \
+ (deprecated("use " __replacement " instead", __replacement)))
+
+#define __WASM_STR(X) #X
+
+#ifdef __DEPRECATED
+#define __DEPRECATED_WASM_MACRO(__name, __replacement) \
+ _Pragma(__WASM_STR(GCC warning( \
+ "'" __name "' is deprecated: use '" __replacement "' instead")))
+#else
+#define __DEPRECATED_WASM_MACRO(__name, __replacement)
+#endif
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_v128_load8_splat")
+wasm_v8x16_load_splat(const void *__mem) {
+ return wasm_v128_load8_splat(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_v128_load16_splat")
+wasm_v16x8_load_splat(const void *__mem) {
+ return wasm_v128_load16_splat(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_v128_load32_splat")
+wasm_v32x4_load_splat(const void *__mem) {
+ return wasm_v128_load32_splat(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_v128_load64_splat")
+wasm_v64x2_load_splat(const void *__mem) {
+ return wasm_v128_load64_splat(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i16x8_load8x8")
+wasm_i16x8_load_8x8(const void *__mem) {
+ return wasm_i16x8_load8x8(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u16x8_load8x8")
+wasm_u16x8_load_8x8(const void *__mem) {
+ return wasm_u16x8_load8x8(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i32x4_load16x4")
+wasm_i32x4_load_16x4(const void *__mem) {
+ return wasm_i32x4_load16x4(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u32x4_load16x4")
+wasm_u32x4_load_16x4(const void *__mem) {
+ return wasm_u32x4_load16x4(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i64x2_load32x2")
+wasm_i64x2_load_32x2(const void *__mem) {
+ return wasm_i64x2_load32x2(__mem);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u64x2_load32x2")
+wasm_u64x2_load_32x2(const void *__mem) {
+ return wasm_u64x2_load32x2(__mem);
+}
+
+#define wasm_v8x16_shuffle(__a, __b, __c0, __c1, __c2, __c3, __c4, __c5, __c6, \
+ __c7, __c8, __c9, __c10, __c11, __c12, __c13, \
+ __c14, __c15) \
+ __DEPRECATED_WASM_MACRO("wasm_v8x16_shuffle", "wasm_i8x16_shuffle") \
+ wasm_i8x16_shuffle(__a, __b, __c0, __c1, __c2, __c3, __c4, __c5, __c6, __c7, \
+ __c8, __c9, __c10, __c11, __c12, __c13, __c14, __c15)
+
+#define wasm_v16x8_shuffle(__a, __b, __c0, __c1, __c2, __c3, __c4, __c5, __c6, \
+ __c7) \
+ __DEPRECATED_WASM_MACRO("wasm_v16x8_shuffle", "wasm_i16x8_shuffle") \
+ wasm_i16x8_shuffle(__a, __b, __c0, __c1, __c2, __c3, __c4, __c5, __c6, __c7)
+
+#define wasm_v32x4_shuffle(__a, __b, __c0, __c1, __c2, __c3) \
+ __DEPRECATED_WASM_MACRO("wasm_v32x4_shuffle", "wasm_i32x4_shuffle") \
+ wasm_i32x4_shuffle(__a, __b, __c0, __c1, __c2, __c3)
+
+#define wasm_v64x2_shuffle(__a, __b, __c0, __c1) \
+ __DEPRECATED_WASM_MACRO("wasm_v64x2_shuffle", "wasm_i64x2_shuffle") \
+ wasm_i64x2_shuffle(__a, __b, __c0, __c1)
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i8x16_swizzle")
+wasm_v8x16_swizzle(v128_t __a, v128_t __b) {
+ return wasm_i8x16_swizzle(__a, __b);
+}
+
+static __inline__ bool __DEPRECATED_FN_ATTRS("wasm_v128_any_true")
+wasm_i8x16_any_true(v128_t __a) {
+ return wasm_v128_any_true(__a);
+}
+
+static __inline__ bool __DEPRECATED_FN_ATTRS("wasm_v128_any_true")
+wasm_i16x8_any_true(v128_t __a) {
+ return wasm_v128_any_true(__a);
+}
+
+static __inline__ bool __DEPRECATED_FN_ATTRS("wasm_v128_any_true")
+wasm_i32x4_any_true(v128_t __a) {
+ return wasm_v128_any_true(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i8x16_add_sat")
+wasm_i8x16_add_saturate(v128_t __a, v128_t __b) {
+ return wasm_i8x16_add_sat(__a, __b);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u8x16_add_sat")
+wasm_u8x16_add_saturate(v128_t __a, v128_t __b) {
+ return wasm_u8x16_add_sat(__a, __b);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i8x16_sub_sat")
+wasm_i8x16_sub_saturate(v128_t __a, v128_t __b) {
+ return wasm_i8x16_sub_sat(__a, __b);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u8x16_sub_sat")
+wasm_u8x16_sub_saturate(v128_t __a, v128_t __b) {
+ return wasm_u8x16_sub_sat(__a, __b);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i16x8_add_sat")
+wasm_i16x8_add_saturate(v128_t __a, v128_t __b) {
+ return wasm_i16x8_add_sat(__a, __b);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u16x8_add_sat")
+wasm_u16x8_add_saturate(v128_t __a, v128_t __b) {
+ return wasm_u16x8_add_sat(__a, __b);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i16x8_sub_sat")
+wasm_i16x8_sub_saturate(v128_t __a, v128_t __b) {
+ return wasm_i16x8_sub_sat(__a, __b);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u16x8_sub_sat")
+wasm_u16x8_sub_saturate(v128_t __a, v128_t __b) {
+ return wasm_u16x8_sub_sat(__a, __b);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i16x8_extend_low_i8x16")
+wasm_i16x8_widen_low_i8x16(v128_t __a) {
+ return wasm_i16x8_extend_low_i8x16(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i16x8_extend_high_i8x16")
+wasm_i16x8_widen_high_i8x16(v128_t __a) {
+ return wasm_i16x8_extend_high_i8x16(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u16x8_extend_low_u8x16")
+wasm_i16x8_widen_low_u8x16(v128_t __a) {
+ return wasm_u16x8_extend_low_u8x16(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u16x8_extend_high_u8x16")
+wasm_i16x8_widen_high_u8x16(v128_t __a) {
+ return wasm_u16x8_extend_high_u8x16(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i32x4_extend_low_i16x8")
+wasm_i32x4_widen_low_i16x8(v128_t __a) {
+ return wasm_i32x4_extend_low_i16x8(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i32x4_extend_high_i16x8")
+wasm_i32x4_widen_high_i16x8(v128_t __a) {
+ return wasm_i32x4_extend_high_i16x8(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u32x4_extend_low_u16x8")
+wasm_i32x4_widen_low_u16x8(v128_t __a) {
+ return wasm_u32x4_extend_low_u16x8(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u32x4_extend_high_u16x8")
+wasm_i32x4_widen_high_u16x8(v128_t __a) {
+ return wasm_u32x4_extend_high_u16x8(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_i32x4_trunc_sat_f32x4")
+wasm_i32x4_trunc_saturate_f32x4(v128_t __a) {
+ return wasm_i32x4_trunc_sat_f32x4(__a);
+}
+
+static __inline__ v128_t __DEPRECATED_FN_ATTRS("wasm_u32x4_trunc_sat_f32x4")
+wasm_u32x4_trunc_saturate_f32x4(v128_t __a) {
+ return wasm_u32x4_trunc_sat_f32x4(__a);
+}
+
// Undefine helper macros
#undef __DEFAULT_FN_ATTRS
+#undef __DEPRECATED_FN_ATTRS
#endif // __WASM_SIMD128_H
diff --git a/src/llvm-project/clang/lib/Index/FileIndexRecord.cpp b/src/llvm-project/clang/lib/Index/FileIndexRecord.cpp
index df18a9a..d392a2b 100644
--- a/src/llvm-project/clang/lib/Index/FileIndexRecord.cpp
+++ b/src/llvm-project/clang/lib/Index/FileIndexRecord.cpp
@@ -17,42 +17,63 @@
using namespace clang;
using namespace clang::index;
+ArrayRef<DeclOccurrence>
+FileIndexRecord::getDeclOccurrencesSortedByOffset() const {
+ if (!IsSorted) {
+ llvm::stable_sort(Decls,
+ [](const DeclOccurrence &A, const DeclOccurrence &B) {
+ return A.Offset < B.Offset;
+ });
+ IsSorted = true;
+ }
+ return Decls;
+}
+
void FileIndexRecord::addDeclOccurence(SymbolRoleSet Roles, unsigned Offset,
const Decl *D,
ArrayRef<SymbolRelation> Relations) {
assert(D->isCanonicalDecl() &&
"Occurrences should be associated with their canonical decl");
-
- auto IsNextOccurence = [&]() -> bool {
- if (Decls.empty())
- return true;
- auto &Last = Decls.back();
- return Last.Offset < Offset;
- };
-
- if (IsNextOccurence()) {
- Decls.emplace_back(Roles, Offset, D, Relations);
- return;
- }
-
- DeclOccurrence NewInfo(Roles, Offset, D, Relations);
- // We keep Decls in order as we need to access them in this order in all cases.
- auto It = llvm::upper_bound(Decls, NewInfo);
- Decls.insert(It, std::move(NewInfo));
+ IsSorted = false;
+ Decls.emplace_back(Roles, Offset, D, Relations);
}
-void FileIndexRecord::print(llvm::raw_ostream &OS) const {
+void FileIndexRecord::addMacroOccurence(SymbolRoleSet Roles, unsigned Offset,
+ const IdentifierInfo *Name,
+ const MacroInfo *MI) {
+ IsSorted = false;
+ Decls.emplace_back(Roles, Offset, Name, MI);
+}
+
+void FileIndexRecord::removeHeaderGuardMacros() {
+ auto It =
+ std::remove_if(Decls.begin(), Decls.end(), [](const DeclOccurrence &D) {
+ if (const auto *MI = D.DeclOrMacro.dyn_cast<const MacroInfo *>())
+ return MI->isUsedForHeaderGuard();
+ return false;
+ });
+ Decls.erase(It, Decls.end());
+}
+
+void FileIndexRecord::print(llvm::raw_ostream &OS, SourceManager &SM) const {
OS << "DECLS BEGIN ---\n";
for (auto &DclInfo : Decls) {
- const Decl *D = DclInfo.Dcl;
- SourceManager &SM = D->getASTContext().getSourceManager();
- SourceLocation Loc = SM.getFileLoc(D->getLocation());
- PresumedLoc PLoc = SM.getPresumedLoc(Loc);
- OS << llvm::sys::path::filename(PLoc.getFilename()) << ':' << PLoc.getLine()
- << ':' << PLoc.getColumn();
+ if (const auto *D = DclInfo.DeclOrMacro.dyn_cast<const Decl *>()) {
+ SourceLocation Loc = SM.getFileLoc(D->getLocation());
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ OS << llvm::sys::path::filename(PLoc.getFilename()) << ':'
+ << PLoc.getLine() << ':' << PLoc.getColumn();
- if (auto ND = dyn_cast<NamedDecl>(D)) {
- OS << ' ' << ND->getDeclName();
+ if (const auto *ND = dyn_cast<NamedDecl>(D)) {
+ OS << ' ' << ND->getDeclName();
+ }
+ } else {
+ const auto *MI = DclInfo.DeclOrMacro.get<const MacroInfo *>();
+ SourceLocation Loc = SM.getFileLoc(MI->getDefinitionLoc());
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+ OS << llvm::sys::path::filename(PLoc.getFilename()) << ':'
+ << PLoc.getLine() << ':' << PLoc.getColumn();
+ OS << ' ' << DclInfo.MacroName->getName();
}
OS << '\n';
diff --git a/src/llvm-project/clang/lib/Index/FileIndexRecord.h b/src/llvm-project/clang/lib/Index/FileIndexRecord.h
index 37bf96a..621d5b7 100644
--- a/src/llvm-project/clang/lib/Index/FileIndexRecord.h
+++ b/src/llvm-project/clang/lib/Index/FileIndexRecord.h
@@ -27,14 +27,13 @@
private:
FileID FID;
bool IsSystem;
- std::vector<DeclOccurrence> Decls;
+ mutable bool IsSorted = false;
+ mutable std::vector<DeclOccurrence> Decls;
public:
FileIndexRecord(FileID FID, bool IsSystem) : FID(FID), IsSystem(IsSystem) {}
- ArrayRef<DeclOccurrence> getDeclOccurrencesSortedByOffset() const {
- return Decls;
- }
+ ArrayRef<DeclOccurrence> getDeclOccurrencesSortedByOffset() const;
FileID getFileID() const { return FID; }
bool isSystem() const { return IsSystem; }
@@ -48,7 +47,21 @@
/// \param Relations the set of symbols related to this occurrence.
void addDeclOccurence(SymbolRoleSet Roles, unsigned Offset, const Decl *D,
ArrayRef<SymbolRelation> Relations);
- void print(llvm::raw_ostream &OS) const;
+
+ /// Adds an occurrence of the given macro at the supplied \c Offset.
+ ///
+ /// \param Roles the roles the occurrence fulfills in this position.
+ /// \param Offset the offset in the file of this occurrence.
+ /// \param Name the name of the macro.
+ /// \param MI the canonical declaration this is an occurrence of.
+ void addMacroOccurence(SymbolRoleSet Roles, unsigned Offset,
+ const IdentifierInfo *Name, const MacroInfo *MI);
+
+ /// Remove any macro occurrences for header guards. When preprocessing, this
+ /// will only be accurate after HandleEndOfFile.
+ void removeHeaderGuardMacros();
+
+ void print(llvm::raw_ostream &OS, SourceManager &SM) const;
};
} // end namespace index
diff --git a/src/llvm-project/clang/lib/Index/IndexBody.cpp b/src/llvm-project/clang/lib/Index/IndexBody.cpp
index e4944fd..fa35f74 100644
--- a/src/llvm-project/clang/lib/Index/IndexBody.cpp
+++ b/src/llvm-project/clang/lib/Index/IndexBody.cpp
@@ -286,9 +286,6 @@
}
bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
- if (E->isClassReceiver())
- IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(),
- Parent, ParentDC);
if (E->isExplicitProperty()) {
SmallVector<SymbolRelation, 2> Relations;
SymbolRoleSet Roles = getRolesForRef(E, Relations);
@@ -466,6 +463,15 @@
}
return true;
}
+
+ bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
+ SmallVector<SymbolRelation, 4> Relations;
+ SymbolRoleSet Roles = getRolesForRef(E, Relations);
+ for (auto *D : E->decls())
+ IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles,
+ Relations, E);
+ return true;
+ }
};
} // anonymous namespace
diff --git a/src/llvm-project/clang/lib/Index/IndexDecl.cpp b/src/llvm-project/clang/lib/Index/IndexDecl.cpp
index 2ba323e..00adb36 100644
--- a/src/llvm-project/clang/lib/Index/IndexDecl.cpp
+++ b/src/llvm-project/clang/lib/Index/IndexDecl.cpp
@@ -759,7 +759,7 @@
}
bool IndexingContext::indexTopLevelDecl(const Decl *D) {
- if (D->getLocation().isInvalid())
+ if (!D || D->getLocation().isInvalid())
return true;
if (isa<ObjCMethodDecl>(D))
diff --git a/src/llvm-project/clang/lib/Index/IndexSymbol.cpp b/src/llvm-project/clang/lib/Index/IndexSymbol.cpp
index 0d2e557..68e457d 100644
--- a/src/llvm-project/clang/lib/Index/IndexSymbol.cpp
+++ b/src/llvm-project/clang/lib/Index/IndexSymbol.cpp
@@ -329,6 +329,11 @@
Info.Kind = SymbolKind::Using;
Info.Lang = SymbolLanguage::CXX;
break;
+ case Decl::UsingEnum:
+ Info.Kind = SymbolKind::Using;
+ Info.Lang = SymbolLanguage::CXX;
+ Info.SubKind = SymbolSubKind::UsingEnum;
+ break;
case Decl::Binding:
Info.Kind = SymbolKind::Variable;
Info.Lang = SymbolLanguage::CXX;
@@ -542,6 +547,8 @@
case SymbolSubKind::AccessorSetter: return "acc-set";
case SymbolSubKind::UsingTypename: return "using-typename";
case SymbolSubKind::UsingValue: return "using-value";
+ case SymbolSubKind::UsingEnum:
+ return "using-enum";
}
llvm_unreachable("invalid symbol subkind");
}
diff --git a/src/llvm-project/clang/lib/Index/IndexingAction.cpp b/src/llvm-project/clang/lib/Index/IndexingAction.cpp
index 4986303..c9fcaad 100644
--- a/src/llvm-project/clang/lib/Index/IndexingAction.cpp
+++ b/src/llvm-project/clang/lib/Index/IndexingAction.cpp
@@ -51,6 +51,51 @@
MacroNameTok.getLocation(),
*MD.getMacroInfo());
}
+
+ void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range) override {
+ if (!MD.getMacroInfo()) // Ignore nonexistent macro.
+ return;
+ // Note: this is defined(M), not #define M
+ IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
+ MacroNameTok.getLocation(),
+ *MD.getMacroInfo());
+ }
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ if (!MD.getMacroInfo()) // Ignore non-existent macro.
+ return;
+ IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
+ MacroNameTok.getLocation(),
+ *MD.getMacroInfo());
+ }
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ if (!MD.getMacroInfo()) // Ignore nonexistent macro.
+ return;
+ IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
+ MacroNameTok.getLocation(),
+ *MD.getMacroInfo());
+ }
+
+ using PPCallbacks::Elifdef;
+ using PPCallbacks::Elifndef;
+ void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ if (!MD.getMacroInfo()) // Ignore non-existent macro.
+ return;
+ IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
+ MacroNameTok.getLocation(),
+ *MD.getMacroInfo());
+ }
+ void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ if (!MD.getMacroInfo()) // Ignore non-existent macro.
+ return;
+ IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
+ MacroNameTok.getLocation(),
+ *MD.getMacroInfo());
+ }
};
class IndexASTConsumer final : public ASTConsumer {
@@ -162,23 +207,54 @@
Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
}
-static void indexPreprocessorMacros(const Preprocessor &PP,
- IndexDataConsumer &DataConsumer) {
- for (const auto &M : PP.macros())
- if (MacroDirective *MD = M.second.getLatest()) {
- auto *MI = MD->getMacroInfo();
- // When using modules, it may happen that we find #undef of a macro that
- // was defined in another module. In such case, MI may be nullptr, since
- // we only look for macro definitions in the current TU. In that case,
- // there is nothing to index.
- if (!MI)
- continue;
+static void indexPreprocessorMacro(const IdentifierInfo *II,
+ const MacroInfo *MI,
+ MacroDirective::Kind DirectiveKind,
+ SourceLocation Loc,
+ IndexDataConsumer &DataConsumer) {
+ // When using modules, it may happen that we find #undef of a macro that
+ // was defined in another module. In such case, MI may be nullptr, since
+ // we only look for macro definitions in the current TU. In that case,
+ // there is nothing to index.
+ if (!MI)
+ return;
- DataConsumer.handleMacroOccurrence(
- M.first, MD->getMacroInfo(),
- static_cast<unsigned>(index::SymbolRole::Definition),
- MD->getLocation());
+ // Skip implicit visibility change.
+ if (DirectiveKind == MacroDirective::MD_Visibility)
+ return;
+
+ auto Role = DirectiveKind == MacroDirective::MD_Define
+ ? SymbolRole::Definition
+ : SymbolRole::Undefinition;
+ DataConsumer.handleMacroOccurrence(II, MI, static_cast<unsigned>(Role), Loc);
+}
+
+static void indexPreprocessorMacros(Preprocessor &PP,
+ IndexDataConsumer &DataConsumer) {
+ for (const auto &M : PP.macros()) {
+ for (auto *MD = M.second.getLatest(); MD; MD = MD->getPrevious()) {
+ indexPreprocessorMacro(M.first, MD->getMacroInfo(), MD->getKind(),
+ MD->getLocation(), DataConsumer);
}
+ }
+}
+
+static void indexPreprocessorModuleMacros(Preprocessor &PP,
+ serialization::ModuleFile &Mod,
+ IndexDataConsumer &DataConsumer) {
+ for (const auto &M : PP.macros()) {
+ if (M.second.getLatest() == nullptr) {
+ for (auto *MM : PP.getLeafModuleMacros(M.first)) {
+ auto *OwningMod = MM->getOwningModule();
+ if (OwningMod && OwningMod->getASTFile() == Mod.File) {
+ if (auto *MI = MM->getMacroInfo()) {
+ indexPreprocessorMacro(M.first, MI, MacroDirective::MD_Define,
+ MI->getDefinitionLoc(), DataConsumer);
+ }
+ }
+ }
+ }
+ }
}
void index::indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,
@@ -225,8 +301,9 @@
IndexCtx.setASTContext(Ctx);
DataConsumer.initialize(Ctx);
- if (Opts.IndexMacrosInPreprocessor)
- indexPreprocessorMacros(Reader.getPreprocessor(), DataConsumer);
+ if (Opts.IndexMacrosInPreprocessor) {
+ indexPreprocessorModuleMacros(Reader.getPreprocessor(), Mod, DataConsumer);
+ }
for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
IndexCtx.indexTopLevelDecl(D);
diff --git a/src/llvm-project/clang/lib/Index/IndexingContext.cpp b/src/llvm-project/clang/lib/Index/IndexingContext.cpp
index 784a600..8a962a0 100644
--- a/src/llvm-project/clang/lib/Index/IndexingContext.cpp
+++ b/src/llvm-project/clang/lib/Index/IndexingContext.cpp
@@ -457,6 +457,8 @@
void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
SourceLocation Loc,
const MacroInfo &MI) {
+ if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
+ return;
SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
}
@@ -464,6 +466,8 @@
void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
SourceLocation Loc,
const MacroInfo &MI) {
+ if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
+ return;
SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
}
@@ -471,6 +475,37 @@
void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
SourceLocation Loc,
const MacroInfo &MI) {
+ if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc))
+ return;
SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
}
+
+bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef,
+ SourceLocation Loc) {
+ if (!IndexOpts.IndexMacros)
+ return false;
+
+ switch (IndexOpts.SystemSymbolFilter) {
+ case IndexingOptions::SystemSymbolFilterKind::None:
+ break;
+ case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
+ if (!IsRef)
+ return true;
+ break;
+ case IndexingOptions::SystemSymbolFilterKind::All:
+ return true;
+ }
+
+ SourceManager &SM = Ctx->getSourceManager();
+ FileID FID = SM.getFileID(SM.getFileLoc(Loc));
+ if (FID.isInvalid())
+ return false;
+
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
+ if (Invalid || !SEntry.isFile())
+ return false;
+
+ return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User;
+}
diff --git a/src/llvm-project/clang/lib/Index/IndexingContext.h b/src/llvm-project/clang/lib/Index/IndexingContext.h
index 3136878..626d81f 100644
--- a/src/llvm-project/clang/lib/Index/IndexingContext.h
+++ b/src/llvm-project/clang/lib/Index/IndexingContext.h
@@ -124,6 +124,8 @@
private:
bool shouldIgnoreIfImplicit(const Decl *D);
+ bool shouldIndexMacroOccurrence(bool IsRef, SourceLocation Loc);
+
bool handleDeclOccurrence(const Decl *D, SourceLocation Loc,
bool IsRef, const Decl *Parent,
SymbolRoleSet Roles,
diff --git a/src/llvm-project/clang/lib/Index/USRGeneration.cpp b/src/llvm-project/clang/lib/Index/USRGeneration.cpp
index abaeb1a..6db763c 100644
--- a/src/llvm-project/clang/lib/Index/USRGeneration.cpp
+++ b/src/llvm-project/clang/lib/Index/USRGeneration.cpp
@@ -732,6 +732,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
case BuiltinType::ShortAccum:
case BuiltinType::Accum:
case BuiltinType::LongAccum:
@@ -1101,15 +1103,14 @@
bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc,
const SourceManager &SM,
SmallVectorImpl<char> &Buf) {
- // Don't generate USRs for things with invalid locations.
- if (MacroName.empty() || Loc.isInvalid())
+ if (MacroName.empty())
return true;
llvm::raw_svector_ostream Out(Buf);
// Assume that system headers are sane. Don't put source location
// information into the USR if the macro comes from a system header.
- bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc);
+ bool ShouldGenerateLocation = Loc.isValid() && !SM.isInSystemHeader(Loc);
Out << getUSRSpacePrefix();
if (ShouldGenerateLocation)
diff --git a/src/llvm-project/clang/lib/Interpreter/CMakeLists.txt b/src/llvm-project/clang/lib/Interpreter/CMakeLists.txt
new file mode 100644
index 0000000..88a0a71
--- /dev/null
+++ b/src/llvm-project/clang/lib/Interpreter/CMakeLists.txt
@@ -0,0 +1,31 @@
+set(LLVM_LINK_COMPONENTS
+ core
+ native
+ Option
+ OrcJit
+ Support
+ Target
+ )
+
+add_clang_library(clangInterpreter
+ IncrementalExecutor.cpp
+ IncrementalParser.cpp
+ Interpreter.cpp
+
+ DEPENDS
+ intrinsics_gen
+
+ LINK_LIBS
+ clangAST
+ clangAnalysis
+ clangBasic
+ clangDriver
+ clangEdit
+ clangFrontend
+ clangLex
+ clangParse
+ clangSema
+ clangSerialization
+ clangCodeGen
+ clangFrontendTool
+ )
diff --git a/src/llvm-project/clang/lib/Interpreter/IncrementalExecutor.cpp b/src/llvm-project/clang/lib/Interpreter/IncrementalExecutor.cpp
new file mode 100644
index 0000000..9a368d9
--- /dev/null
+++ b/src/llvm-project/clang/lib/Interpreter/IncrementalExecutor.cpp
@@ -0,0 +1,63 @@
+//===--- IncrementalExecutor.cpp - Incremental Execution --------*- 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 implements the class which performs incremental code execution.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IncrementalExecutor.h"
+
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/TargetSelect.h"
+
+namespace clang {
+
+IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC,
+ llvm::Error &Err,
+ const llvm::Triple &Triple)
+ : TSCtx(TSC) {
+ using namespace llvm::orc;
+ llvm::ErrorAsOutParameter EAO(&Err);
+
+ auto JTMB = JITTargetMachineBuilder(Triple);
+ if (auto JitOrErr = LLJITBuilder().setJITTargetMachineBuilder(JTMB).create())
+ Jit = std::move(*JitOrErr);
+ else {
+ Err = JitOrErr.takeError();
+ return;
+ }
+
+ const char Pref = Jit->getDataLayout().getGlobalPrefix();
+ // Discover symbols from the process as a fallback.
+ if (auto PSGOrErr = DynamicLibrarySearchGenerator::GetForCurrentProcess(Pref))
+ Jit->getMainJITDylib().addGenerator(std::move(*PSGOrErr));
+ else {
+ Err = PSGOrErr.takeError();
+ return;
+ }
+}
+
+IncrementalExecutor::~IncrementalExecutor() {}
+
+llvm::Error IncrementalExecutor::addModule(std::unique_ptr<llvm::Module> M) {
+ return Jit->addIRModule(llvm::orc::ThreadSafeModule(std::move(M), TSCtx));
+}
+
+llvm::Error IncrementalExecutor::runCtors() const {
+ return Jit->initialize(Jit->getMainJITDylib());
+}
+
+} // end namespace clang
diff --git a/src/llvm-project/clang/lib/Interpreter/IncrementalExecutor.h b/src/llvm-project/clang/lib/Interpreter/IncrementalExecutor.h
new file mode 100644
index 0000000..b4c6dde
--- /dev/null
+++ b/src/llvm-project/clang/lib/Interpreter/IncrementalExecutor.h
@@ -0,0 +1,48 @@
+//===--- IncrementalExecutor.h - Incremental Execution ----------*- 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 implements the class which performs incremental code execution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H
+#define LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+
+#include <memory>
+
+namespace llvm {
+class Error;
+class Module;
+namespace orc {
+class LLJIT;
+class ThreadSafeContext;
+} // namespace orc
+} // namespace llvm
+
+namespace clang {
+class IncrementalExecutor {
+ using CtorDtorIterator = llvm::orc::CtorDtorIterator;
+ std::unique_ptr<llvm::orc::LLJIT> Jit;
+ llvm::orc::ThreadSafeContext &TSCtx;
+
+public:
+ IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, llvm::Error &Err,
+ const llvm::Triple &Triple);
+ ~IncrementalExecutor();
+
+ llvm::Error addModule(std::unique_ptr<llvm::Module> M);
+ llvm::Error runCtors() const;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H
diff --git a/src/llvm-project/clang/lib/Interpreter/IncrementalParser.cpp b/src/llvm-project/clang/lib/Interpreter/IncrementalParser.cpp
new file mode 100644
index 0000000..897e2cd
--- /dev/null
+++ b/src/llvm-project/clang/lib/Interpreter/IncrementalParser.cpp
@@ -0,0 +1,292 @@
+//===--------- IncrementalParser.cpp - Incremental Compilation -----------===//
+//
+// Part of the LLVM Project, under the Apache 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 the class which performs incremental code compilation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IncrementalParser.h"
+
+#include "clang/AST/DeclContextInternals.h"
+#include "clang/CodeGen/BackendUtil.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/FrontendTool/Utils.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/Sema.h"
+
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Timer.h"
+
+#include <sstream>
+
+namespace clang {
+
+/// A custom action enabling the incremental processing functionality.
+///
+/// The usual \p FrontendAction expects one call to ExecuteAction and once it
+/// sees a call to \p EndSourceFile it deletes some of the important objects
+/// such as \p Preprocessor and \p Sema assuming no further input will come.
+///
+/// \p IncrementalAction ensures it keep its underlying action's objects alive
+/// as long as the \p IncrementalParser needs them.
+///
+class IncrementalAction : public WrapperFrontendAction {
+private:
+ bool IsTerminating = false;
+
+public:
+ IncrementalAction(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx,
+ llvm::Error &Err)
+ : WrapperFrontendAction([&]() {
+ llvm::ErrorAsOutParameter EAO(&Err);
+ std::unique_ptr<FrontendAction> Act;
+ switch (CI.getFrontendOpts().ProgramAction) {
+ default:
+ Err = llvm::createStringError(
+ std::errc::state_not_recoverable,
+ "Driver initialization failed. "
+ "Incremental mode for action %d is not supported",
+ CI.getFrontendOpts().ProgramAction);
+ return Act;
+ case frontend::ASTDump:
+ LLVM_FALLTHROUGH;
+ case frontend::ASTPrint:
+ LLVM_FALLTHROUGH;
+ case frontend::ParseSyntaxOnly:
+ Act = CreateFrontendAction(CI);
+ break;
+ case frontend::EmitAssembly:
+ LLVM_FALLTHROUGH;
+ case frontend::EmitObj:
+ LLVM_FALLTHROUGH;
+ case frontend::EmitLLVMOnly:
+ Act.reset(new EmitLLVMOnlyAction(&LLVMCtx));
+ break;
+ }
+ return Act;
+ }()) {}
+ FrontendAction *getWrapped() const { return WrappedAction.get(); }
+ TranslationUnitKind getTranslationUnitKind() override {
+ return TU_Incremental;
+ }
+ void ExecuteAction() override {
+ CompilerInstance &CI = getCompilerInstance();
+ assert(CI.hasPreprocessor() && "No PP!");
+
+ // FIXME: Move the truncation aspect of this into Sema, we delayed this till
+ // here so the source manager would be initialized.
+ if (hasCodeCompletionSupport() &&
+ !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
+ CI.createCodeCompletionConsumer();
+
+ // Use a code completion consumer?
+ CodeCompleteConsumer *CompletionConsumer = nullptr;
+ if (CI.hasCodeCompletionConsumer())
+ CompletionConsumer = &CI.getCodeCompletionConsumer();
+
+ Preprocessor &PP = CI.getPreprocessor();
+ PP.enableIncrementalProcessing();
+ PP.EnterMainSourceFile();
+
+ if (!CI.hasSema())
+ CI.createSema(getTranslationUnitKind(), CompletionConsumer);
+ }
+
+ // Do not terminate after processing the input. This allows us to keep various
+ // clang objects alive and to incrementally grow the current TU.
+ void EndSourceFile() override {
+ // The WrappedAction can be nullptr if we issued an error in the ctor.
+ if (IsTerminating && getWrapped())
+ WrapperFrontendAction::EndSourceFile();
+ }
+
+ void FinalizeAction() {
+ assert(!IsTerminating && "Already finalized!");
+ IsTerminating = true;
+ EndSourceFile();
+ }
+};
+
+IncrementalParser::IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
+ llvm::LLVMContext &LLVMCtx,
+ llvm::Error &Err)
+ : CI(std::move(Instance)) {
+ llvm::ErrorAsOutParameter EAO(&Err);
+ Act = std::make_unique<IncrementalAction>(*CI, LLVMCtx, Err);
+ if (Err)
+ return;
+ CI->ExecuteAction(*Act);
+ Consumer = &CI->getASTConsumer();
+ P.reset(
+ new Parser(CI->getPreprocessor(), CI->getSema(), /*SkipBodies=*/false));
+ P->Initialize();
+}
+
+IncrementalParser::~IncrementalParser() { Act->FinalizeAction(); }
+
+llvm::Expected<PartialTranslationUnit &>
+IncrementalParser::ParseOrWrapTopLevelDecl() {
+ // Recover resources if we crash before exiting this method.
+ Sema &S = CI->getSema();
+ llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);
+ Sema::GlobalEagerInstantiationScope GlobalInstantiations(S, /*Enabled=*/true);
+ Sema::LocalEagerInstantiationScope LocalInstantiations(S);
+
+ PTUs.emplace_back(PartialTranslationUnit());
+ PartialTranslationUnit &LastPTU = PTUs.back();
+ // Add a new PTU.
+ ASTContext &C = S.getASTContext();
+ C.addTranslationUnitDecl();
+ LastPTU.TUPart = C.getTranslationUnitDecl();
+
+ // Skip previous eof due to last incremental input.
+ if (P->getCurToken().is(tok::eof)) {
+ P->ConsumeToken();
+ // FIXME: Clang does not call ExitScope on finalizing the regular TU, we
+ // might want to do that around HandleEndOfTranslationUnit.
+ P->ExitScope();
+ S.CurContext = nullptr;
+ // Start a new PTU.
+ P->EnterScope(Scope::DeclScope);
+ S.ActOnTranslationUnitScope(P->getCurScope());
+ }
+
+ Parser::DeclGroupPtrTy ADecl;
+ for (bool AtEOF = P->ParseFirstTopLevelDecl(ADecl); !AtEOF;
+ AtEOF = P->ParseTopLevelDecl(ADecl)) {
+ // If we got a null return and something *was* parsed, ignore it. This
+ // is due to a top-level semicolon, an action override, or a parse error
+ // skipping something.
+ if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
+ return llvm::make_error<llvm::StringError>("Parsing failed. "
+ "The consumer rejected a decl",
+ std::error_code());
+ }
+
+ DiagnosticsEngine &Diags = getCI()->getDiagnostics();
+ if (Diags.hasErrorOccurred()) {
+ TranslationUnitDecl *MostRecentTU = C.getTranslationUnitDecl();
+ TranslationUnitDecl *PreviousTU = MostRecentTU->getPreviousDecl();
+ assert(PreviousTU && "Must have a TU from the ASTContext initialization!");
+ TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
+ assert(FirstTU);
+ FirstTU->RedeclLink.setLatest(PreviousTU);
+ C.TUDecl = PreviousTU;
+ S.TUScope->setEntity(PreviousTU);
+
+ // Clean up the lookup table
+ if (StoredDeclsMap *Map = PreviousTU->getLookupPtr()) {
+ for (auto I = Map->begin(); I != Map->end(); ++I) {
+ StoredDeclsList &List = I->second;
+ DeclContextLookupResult R = List.getLookupResult();
+ for (NamedDecl *D : R)
+ if (D->getTranslationUnitDecl() == MostRecentTU)
+ List.remove(D);
+ if (List.isNull())
+ Map->erase(I);
+ }
+ }
+
+ // FIXME: Do not reset the pragma handlers.
+ Diags.Reset();
+ return llvm::make_error<llvm::StringError>("Parsing failed.",
+ std::error_code());
+ }
+
+ // Process any TopLevelDecls generated by #pragma weak.
+ for (Decl *D : S.WeakTopLevelDecls()) {
+ DeclGroupRef DGR(D);
+ Consumer->HandleTopLevelDecl(DGR);
+ }
+
+ LocalInstantiations.perform();
+ GlobalInstantiations.perform();
+
+ Consumer->HandleTranslationUnit(C);
+
+ return LastPTU;
+}
+
+static CodeGenerator *getCodeGen(FrontendAction *Act) {
+ IncrementalAction *IncrAct = static_cast<IncrementalAction *>(Act);
+ FrontendAction *WrappedAct = IncrAct->getWrapped();
+ if (!WrappedAct->hasIRSupport())
+ return nullptr;
+ return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();
+}
+
+llvm::Expected<PartialTranslationUnit &>
+IncrementalParser::Parse(llvm::StringRef input) {
+ Preprocessor &PP = CI->getPreprocessor();
+ assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?");
+
+ std::ostringstream SourceName;
+ SourceName << "input_line_" << InputCount++;
+
+ // Create an uninitialized memory buffer, copy code in and append "\n"
+ size_t InputSize = input.size(); // don't include trailing 0
+ // MemBuffer size should *not* include terminating zero
+ std::unique_ptr<llvm::MemoryBuffer> MB(
+ llvm::WritableMemoryBuffer::getNewUninitMemBuffer(InputSize + 1,
+ SourceName.str()));
+ char *MBStart = const_cast<char *>(MB->getBufferStart());
+ memcpy(MBStart, input.data(), InputSize);
+ MBStart[InputSize] = '\n';
+
+ SourceManager &SM = CI->getSourceManager();
+
+ // FIXME: Create SourceLocation, which will allow clang to order the overload
+ // candidates for example
+ SourceLocation NewLoc = SM.getLocForStartOfFile(SM.getMainFileID());
+
+ // Create FileID for the current buffer.
+ FileID FID = SM.createFileID(std::move(MB), SrcMgr::C_User, /*LoadedID=*/0,
+ /*LoadedOffset=*/0, NewLoc);
+
+ // NewLoc only used for diags.
+ if (PP.EnterSourceFile(FID, /*DirLookup=*/0, NewLoc))
+ return llvm::make_error<llvm::StringError>("Parsing failed. "
+ "Cannot enter source file.",
+ std::error_code());
+
+ auto PTU = ParseOrWrapTopLevelDecl();
+ if (!PTU)
+ return PTU.takeError();
+
+ if (PP.getLangOpts().DelayedTemplateParsing) {
+ // Microsoft-specific:
+ // Late parsed templates can leave unswallowed "macro"-like tokens.
+ // They will seriously confuse the Parser when entering the next
+ // source file. So lex until we are EOF.
+ Token Tok;
+ do {
+ PP.Lex(Tok);
+ } while (Tok.isNot(tok::eof));
+ }
+
+ Token AssertTok;
+ PP.Lex(AssertTok);
+ assert(AssertTok.is(tok::eof) &&
+ "Lexer must be EOF when starting incremental parse!");
+
+ if (CodeGenerator *CG = getCodeGen(Act.get())) {
+ std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
+ CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
+ M->getContext());
+
+ PTU->TheModule = std::move(M);
+ }
+
+ return PTU;
+}
+} // end namespace clang
diff --git a/src/llvm-project/clang/lib/Interpreter/IncrementalParser.h b/src/llvm-project/clang/lib/Interpreter/IncrementalParser.h
new file mode 100644
index 0000000..aa8142c
--- /dev/null
+++ b/src/llvm-project/clang/lib/Interpreter/IncrementalParser.h
@@ -0,0 +1,77 @@
+//===--- IncrementalParser.h - Incremental Compilation ----------*- 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 implements the class which performs incremental code compilation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_INTERPRETER_INCREMENTALPARSER_H
+#define LLVM_CLANG_LIB_INTERPRETER_INCREMENTALPARSER_H
+
+#include "clang/Interpreter/PartialTranslationUnit.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+#include <list>
+#include <memory>
+namespace llvm {
+class LLVMContext;
+}
+
+namespace clang {
+class ASTConsumer;
+class CompilerInstance;
+class CodeGenerator;
+class DeclGroupRef;
+class FrontendAction;
+class IncrementalAction;
+class Parser;
+
+/// Provides support for incremental compilation. Keeps track of the state
+/// changes between the subsequent incremental input.
+///
+class IncrementalParser {
+ /// Long-lived, incremental parsing action.
+ std::unique_ptr<IncrementalAction> Act;
+
+ /// Compiler instance performing the incremental compilation.
+ std::unique_ptr<CompilerInstance> CI;
+
+ /// Parser.
+ std::unique_ptr<Parser> P;
+
+ /// Consumer to process the produced top level decls. Owned by Act.
+ ASTConsumer *Consumer = nullptr;
+
+ /// Counts the number of direct user input lines that have been parsed.
+ unsigned InputCount = 0;
+
+ /// List containing every information about every incrementally parsed piece
+ /// of code.
+ std::list<PartialTranslationUnit> PTUs;
+
+public:
+ IncrementalParser(std::unique_ptr<CompilerInstance> Instance,
+ llvm::LLVMContext &LLVMCtx, llvm::Error &Err);
+ ~IncrementalParser();
+
+ const CompilerInstance *getCI() const { return CI.get(); }
+
+ /// Parses incremental input by creating an in-memory file.
+ ///\returns a \c PartialTranslationUnit which holds information about the
+ /// \c TranslationUnitDecl and \c llvm::Module corresponding to the input.
+ llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Input);
+
+private:
+ llvm::Expected<PartialTranslationUnit &> ParseOrWrapTopLevelDecl();
+};
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_INTERPRETER_INCREMENTALPARSER_H
diff --git a/src/llvm-project/clang/lib/Interpreter/Interpreter.cpp b/src/llvm-project/clang/lib/Interpreter/Interpreter.cpp
new file mode 100644
index 0000000..937504f
--- /dev/null
+++ b/src/llvm-project/clang/lib/Interpreter/Interpreter.cpp
@@ -0,0 +1,225 @@
+//===------ Interpreter.cpp - Incremental Compilation and Execution -------===//
+//
+// Part of the LLVM Project, under the Apache 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 the component which performs incremental code
+// compilation and execution.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Interpreter/Interpreter.h"
+
+#include "IncrementalExecutor.h"
+#include "IncrementalParser.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Host.h"
+
+using namespace clang;
+
+// FIXME: Figure out how to unify with namespace init_convenience from
+// tools/clang-import-test/clang-import-test.cpp and
+// examples/clang-interpreter/main.cpp
+namespace {
+/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
+/// \returns NULL on error.
+static llvm::Expected<const llvm::opt::ArgStringList *>
+GetCC1Arguments(DiagnosticsEngine *Diagnostics,
+ driver::Compilation *Compilation) {
+ // We expect to get back exactly one Command job, if we didn't something
+ // failed. Extract that job from the Compilation.
+ const driver::JobList &Jobs = Compilation->getJobs();
+ if (!Jobs.size() || !isa<driver::Command>(*Jobs.begin()))
+ return llvm::createStringError(std::errc::state_not_recoverable,
+ "Driver initialization failed. "
+ "Unable to create a driver job");
+
+ // The one job we find should be to invoke clang again.
+ const driver::Command *Cmd = cast<driver::Command>(&(*Jobs.begin()));
+ if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
+ return llvm::createStringError(std::errc::state_not_recoverable,
+ "Driver initialization failed");
+
+ return &Cmd->getArguments();
+}
+
+static llvm::Expected<std::unique_ptr<CompilerInstance>>
+CreateCI(const llvm::opt::ArgStringList &Argv) {
+ std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+
+ // Register the support for object-file-wrapped Clang modules.
+ // FIXME: Clang should register these container operations automatically.
+ auto PCHOps = Clang->getPCHContainerOperations();
+ PCHOps->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
+ PCHOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());
+
+ // Buffer diagnostics from argument parsing so that we can output them using
+ // a well formed diagnostic object.
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
+ bool Success = CompilerInvocation::CreateFromArgs(
+ Clang->getInvocation(), llvm::makeArrayRef(Argv.begin(), Argv.size()),
+ Diags);
+
+ // Infer the builtin include path if unspecified.
+ if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
+ Clang->getHeaderSearchOpts().ResourceDir.empty())
+ Clang->getHeaderSearchOpts().ResourceDir =
+ CompilerInvocation::GetResourcesPath(Argv[0], nullptr);
+
+ // Create the actual diagnostics engine.
+ Clang->createDiagnostics();
+ if (!Clang->hasDiagnostics())
+ return llvm::createStringError(std::errc::state_not_recoverable,
+ "Initialization failed. "
+ "Unable to create diagnostics engine");
+
+ DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
+ if (!Success)
+ return llvm::createStringError(std::errc::state_not_recoverable,
+ "Initialization failed. "
+ "Unable to flush diagnostics");
+
+ // FIXME: Merge with CompilerInstance::ExecuteAction.
+ llvm::MemoryBuffer *MB = llvm::MemoryBuffer::getMemBuffer("").release();
+ Clang->getPreprocessorOpts().addRemappedFile("<<< inputs >>>", MB);
+
+ Clang->setTarget(TargetInfo::CreateTargetInfo(
+ Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
+ if (!Clang->hasTarget())
+ return llvm::createStringError(std::errc::state_not_recoverable,
+ "Initialization failed. "
+ "Target is missing");
+
+ Clang->getTarget().adjust(Clang->getDiagnostics(), Clang->getLangOpts());
+
+ return std::move(Clang);
+}
+
+} // anonymous namespace
+
+llvm::Expected<std::unique_ptr<CompilerInstance>>
+IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {
+
+ // If we don't know ClangArgv0 or the address of main() at this point, try
+ // to guess it anyway (it's possible on some platforms).
+ std::string MainExecutableName =
+ llvm::sys::fs::getMainExecutable(nullptr, nullptr);
+
+ ClangArgv.insert(ClangArgv.begin(), MainExecutableName.c_str());
+
+ // Prepending -c to force the driver to do something if no action was
+ // specified. By prepending we allow users to override the default
+ // action and use other actions in incremental mode.
+ // FIXME: Print proper driver diagnostics if the driver flags are wrong.
+ ClangArgv.insert(ClangArgv.begin() + 1, "-c");
+
+ if (!llvm::is_contained(ClangArgv, " -x")) {
+ // We do C++ by default; append right after argv[0] if no "-x" given
+ ClangArgv.push_back("-x");
+ ClangArgv.push_back("c++");
+ }
+
+ // Put a dummy C++ file on to ensure there's at least one compile job for the
+ // driver to construct.
+ ClangArgv.push_back("<<< inputs >>>");
+
+ CompilerInvocation Invocation;
+ // Buffer diagnostics from argument parsing so that we can output them using a
+ // well formed diagnostic object.
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
+ unsigned MissingArgIndex, MissingArgCount;
+ const llvm::opt::OptTable &Opts = driver::getDriverOptTable();
+ llvm::opt::InputArgList ParsedArgs =
+ Opts.ParseArgs(ArrayRef<const char *>(ClangArgv).slice(1),
+ MissingArgIndex, MissingArgCount);
+ ParseDiagnosticArgs(*DiagOpts, ParsedArgs, &Diags);
+
+ driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0],
+ llvm::sys::getProcessTriple(), Diags);
+ Driver.setCheckInputsExist(false); // the input comes from mem buffers
+ llvm::ArrayRef<const char *> RF = llvm::makeArrayRef(ClangArgv);
+ std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));
+
+ if (Compilation->getArgs().hasArg(driver::options::OPT_v))
+ Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
+
+ auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
+ if (auto Err = ErrOrCC1Args.takeError())
+ return std::move(Err);
+
+ return CreateCI(**ErrOrCC1Args);
+}
+
+Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
+ llvm::Error &Err) {
+ llvm::ErrorAsOutParameter EAO(&Err);
+ auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
+ TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
+ IncrParser = std::make_unique<IncrementalParser>(std::move(CI),
+ *TSCtx->getContext(), Err);
+}
+
+Interpreter::~Interpreter() {}
+
+llvm::Expected<std::unique_ptr<Interpreter>>
+Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+ llvm::Error Err = llvm::Error::success();
+ auto Interp =
+ std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
+ if (Err)
+ return std::move(Err);
+ return std::move(Interp);
+}
+
+const CompilerInstance *Interpreter::getCompilerInstance() const {
+ return IncrParser->getCI();
+}
+
+llvm::Expected<PartialTranslationUnit &>
+Interpreter::Parse(llvm::StringRef Code) {
+ return IncrParser->Parse(Code);
+}
+
+llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
+ assert(T.TheModule);
+ if (!IncrExecutor) {
+ const llvm::Triple &Triple =
+ getCompilerInstance()->getASTContext().getTargetInfo().getTriple();
+ llvm::Error Err = llvm::Error::success();
+ IncrExecutor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, Triple);
+
+ if (Err)
+ return Err;
+ }
+ // FIXME: Add a callback to retain the llvm::Module once the JIT is done.
+ if (auto Err = IncrExecutor->addModule(std::move(T.TheModule)))
+ return Err;
+
+ if (auto Err = IncrExecutor->runCtors())
+ return Err;
+
+ return llvm::Error::success();
+}
diff --git a/src/llvm-project/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp b/src/llvm-project/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
index cdb4a79..cfca167 100644
--- a/src/llvm-project/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
+++ b/src/llvm-project/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
@@ -846,6 +846,8 @@
.Case("ifdef", pp_ifdef)
.Case("ifndef", pp_ifndef)
.Case("elif", pp_elif)
+ .Case("elifdef", pp_elifdef)
+ .Case("elifndef", pp_elifndef)
.Case("else", pp_else)
.Case("endif", pp_endif)
.Case("pragma", pp_pragma_import)
@@ -904,7 +906,7 @@
struct Directive {
enum DirectiveKind {
If, // if/ifdef/ifndef
- Else // elif,else
+ Else // elif/elifdef/elifndef, else
};
int Offset;
DirectiveKind Kind;
@@ -919,6 +921,8 @@
break;
case pp_elif:
+ case pp_elifdef:
+ case pp_elifndef:
case pp_else: {
if (Offsets.empty())
return true;
diff --git a/src/llvm-project/clang/lib/Lex/HeaderMap.cpp b/src/llvm-project/clang/lib/Lex/HeaderMap.cpp
index d44ef29..ae5e6b2 100644
--- a/src/llvm-project/clang/lib/Lex/HeaderMap.cpp
+++ b/src/llvm-project/clang/lib/Lex/HeaderMap.cpp
@@ -224,7 +224,7 @@
Optional<StringRef> Key = getString(B.Key);
if (LLVM_UNLIKELY(!Key))
continue;
- if (!Filename.equals_lower(*Key))
+ if (!Filename.equals_insensitive(*Key))
continue;
// If so, we have a match in the hash table. Construct the destination
@@ -240,3 +240,32 @@
return StringRef(DestPath.begin(), DestPath.size());
}
}
+
+StringRef HeaderMapImpl::reverseLookupFilename(StringRef DestPath) const {
+ if (!ReverseMap.empty())
+ return ReverseMap.lookup(DestPath);
+
+ const HMapHeader &Hdr = getHeader();
+ unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
+ StringRef RetKey;
+ for (unsigned i = 0; i != NumBuckets; ++i) {
+ HMapBucket B = getBucket(i);
+ if (B.Key == HMAP_EmptyBucketKey)
+ continue;
+
+ Optional<StringRef> Key = getString(B.Key);
+ Optional<StringRef> Prefix = getString(B.Prefix);
+ Optional<StringRef> Suffix = getString(B.Suffix);
+ if (LLVM_LIKELY(Key && Prefix && Suffix)) {
+ SmallVector<char, 1024> Buf;
+ Buf.append(Prefix->begin(), Prefix->end());
+ Buf.append(Suffix->begin(), Suffix->end());
+ StringRef Value(Buf.begin(), Buf.size());
+ ReverseMap[Value] = *Key;
+
+ if (DestPath == Value)
+ RetKey = *Key;
+ }
+ }
+ return RetKey;
+}
diff --git a/src/llvm-project/clang/lib/Lex/HeaderSearch.cpp b/src/llvm-project/clang/lib/Lex/HeaderSearch.cpp
index 99c92e9..d5adbcf 100644
--- a/src/llvm-project/clang/lib/Lex/HeaderSearch.cpp
+++ b/src/llvm-project/clang/lib/Lex/HeaderSearch.cpp
@@ -727,7 +727,7 @@
if (!isAngled && !FoundByHeaderMap) {
SmallString<128> NewInclude("<");
if (IsIncludeeInFramework) {
- NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework
+ NewInclude += ToFramework.str().drop_back(10); // drop .framework
NewInclude += "/";
}
NewInclude += IncludeFilename;
@@ -1834,7 +1834,7 @@
};
for (unsigned I = 0; I != SearchDirs.size(); ++I) {
- // FIXME: Support this search within frameworks and header maps.
+ // FIXME: Support this search within frameworks.
if (!SearchDirs[I].isNormalDir())
continue;
@@ -1848,6 +1848,19 @@
if (!BestPrefixLength && CheckDir(path::parent_path(MainFile)) && IsSystem)
*IsSystem = false;
+ // Try resolving resulting filename via reverse search in header maps,
+ // key from header name is user prefered name for the include file.
+ StringRef Filename = File.drop_front(BestPrefixLength);
+ for (unsigned I = 0; I != SearchDirs.size(); ++I) {
+ if (!SearchDirs[I].isHeaderMap())
+ continue;
- return path::convert_to_slash(File.drop_front(BestPrefixLength));
+ StringRef SpelledFilename =
+ SearchDirs[I].getHeaderMap()->reverseLookupFilename(Filename);
+ if (!SpelledFilename.empty()) {
+ Filename = SpelledFilename;
+ break;
+ }
+ }
+ return path::convert_to_slash(Filename);
}
diff --git a/src/llvm-project/clang/lib/Lex/Lexer.cpp b/src/llvm-project/clang/lib/Lex/Lexer.cpp
index 34732b6..6494449 100644
--- a/src/llvm-project/clang/lib/Lex/Lexer.cpp
+++ b/src/llvm-project/clang/lib/Lex/Lexer.cpp
@@ -588,7 +588,7 @@
// Create a lexer starting at the beginning of the file. Note that we use a
// "fake" file source location at offset 1 so that the lexer will track our
// position within the file.
- const unsigned StartOffset = 1;
+ const SourceLocation::UIntTy StartOffset = 1;
SourceLocation FileLoc = SourceLocation::getFromRawEncoding(StartOffset);
Lexer TheLexer(FileLoc, LangOpts, Buffer.begin(), Buffer.begin(),
Buffer.end());
@@ -682,6 +682,8 @@
.Case("ifdef", PDK_Skipped)
.Case("ifndef", PDK_Skipped)
.Case("elif", PDK_Skipped)
+ .Case("elifdef", PDK_Skipped)
+ .Case("elifndef", PDK_Skipped)
.Case("else", PDK_Skipped)
.Case("endif", PDK_Skipped)
.Default(PDK_Unknown);
@@ -875,6 +877,14 @@
return CharSourceRange::getCharRange(Begin, End);
}
+// Assumes that `Loc` is in an expansion.
+static bool isInExpansionTokenRange(const SourceLocation Loc,
+ const SourceManager &SM) {
+ return SM.getSLocEntry(SM.getFileID(Loc))
+ .getExpansion()
+ .isExpansionTokenRange();
+}
+
CharSourceRange Lexer::makeFileCharRange(CharSourceRange Range,
const SourceManager &SM,
const LangOptions &LangOpts) {
@@ -894,10 +904,12 @@
}
if (Begin.isFileID() && End.isMacroID()) {
- if ((Range.isTokenRange() && !isAtEndOfMacroExpansion(End, SM, LangOpts,
- &End)) ||
- (Range.isCharRange() && !isAtStartOfMacroExpansion(End, SM, LangOpts,
- &End)))
+ if (Range.isTokenRange()) {
+ if (!isAtEndOfMacroExpansion(End, SM, LangOpts, &End))
+ return {};
+ // Use the *original* end, not the expanded one in `End`.
+ Range.setTokenRange(isInExpansionTokenRange(Range.getEnd(), SM));
+ } else if (!isAtStartOfMacroExpansion(End, SM, LangOpts, &End))
return {};
Range.setEnd(End);
return makeRangeFromFileLocs(Range, SM, LangOpts);
@@ -912,6 +924,9 @@
&MacroEnd)))) {
Range.setBegin(MacroBegin);
Range.setEnd(MacroEnd);
+ // Use the *original* `End`, not the expanded one in `MacroEnd`.
+ if (Range.isTokenRange())
+ Range.setTokenRange(isInExpansionTokenRange(End, SM));
return makeRangeFromFileLocs(Range, SM, LangOpts);
}
@@ -1788,12 +1803,14 @@
}
// If we have a digit separator, continue.
- if (C == '\'' && getLangOpts().CPlusPlus14) {
+ if (C == '\'' && (getLangOpts().CPlusPlus14 || getLangOpts().C2x)) {
unsigned NextSize;
char Next = getCharAndSizeNoWarn(CurPtr + Size, NextSize, getLangOpts());
if (isIdentifierBody(Next)) {
if (!isLexingRawMode())
- Diag(CurPtr, diag::warn_cxx11_compat_digit_separator);
+ Diag(CurPtr, getLangOpts().CPlusPlus
+ ? diag::warn_cxx11_compat_digit_separator
+ : diag::warn_c2x_compat_digit_separator);
CurPtr = ConsumeChar(CurPtr, Size, Result);
CurPtr = ConsumeChar(CurPtr, NextSize, Result);
return LexNumericConstant(Result, CurPtr);
@@ -2059,7 +2076,7 @@
if (C == '\\')
C = getAndAdvanceChar(CurPtr, Result);
- if (C == '\n' || C == '\r' || // Newline.
+ if (isVerticalWhitespace(C) || // Newline.
(C == 0 && (CurPtr - 1 == BufferEnd))) { // End of file.
// If the filename is unterminated, then it must just be a lone <
// character. Return this as such.
@@ -2441,56 +2458,70 @@
Lexer *L) {
assert(CurPtr[0] == '\n' || CurPtr[0] == '\r');
- // Back up off the newline.
- --CurPtr;
+ // Position of the first trigraph in the ending sequence.
+ const char *TrigraphPos = 0;
+ // Position of the first whitespace after a '\' in the ending sequence.
+ const char *SpacePos = 0;
- // If this is a two-character newline sequence, skip the other character.
- if (CurPtr[0] == '\n' || CurPtr[0] == '\r') {
- // \n\n or \r\r -> not escaped newline.
- if (CurPtr[0] == CurPtr[1])
- return false;
- // \n\r or \r\n -> skip the newline.
+ while (true) {
+ // Back up off the newline.
--CurPtr;
+
+ // If this is a two-character newline sequence, skip the other character.
+ if (CurPtr[0] == '\n' || CurPtr[0] == '\r') {
+ // \n\n or \r\r -> not escaped newline.
+ if (CurPtr[0] == CurPtr[1])
+ return false;
+ // \n\r or \r\n -> skip the newline.
+ --CurPtr;
+ }
+
+ // If we have horizontal whitespace, skip over it. We allow whitespace
+ // between the slash and newline.
+ while (isHorizontalWhitespace(*CurPtr) || *CurPtr == 0) {
+ SpacePos = CurPtr;
+ --CurPtr;
+ }
+
+ // If we have a slash, this is an escaped newline.
+ if (*CurPtr == '\\') {
+ --CurPtr;
+ } else if (CurPtr[0] == '/' && CurPtr[-1] == '?' && CurPtr[-2] == '?') {
+ // This is a trigraph encoding of a slash.
+ TrigraphPos = CurPtr - 2;
+ CurPtr -= 3;
+ } else {
+ return false;
+ }
+
+ // If the character preceding the escaped newline is a '*', then after line
+ // splicing we have a '*/' ending the comment.
+ if (*CurPtr == '*')
+ break;
+
+ if (*CurPtr != '\n' && *CurPtr != '\r')
+ return false;
}
- // If we have horizontal whitespace, skip over it. We allow whitespace
- // between the slash and newline.
- bool HasSpace = false;
- while (isHorizontalWhitespace(*CurPtr) || *CurPtr == 0) {
- --CurPtr;
- HasSpace = true;
- }
-
- // If we have a slash, we know this is an escaped newline.
- if (*CurPtr == '\\') {
- if (CurPtr[-1] != '*') return false;
- } else {
- // It isn't a slash, is it the ?? / trigraph?
- if (CurPtr[0] != '/' || CurPtr[-1] != '?' || CurPtr[-2] != '?' ||
- CurPtr[-3] != '*')
- return false;
-
- // This is the trigraph ending the comment. Emit a stern warning!
- CurPtr -= 2;
-
+ if (TrigraphPos) {
// If no trigraphs are enabled, warn that we ignored this trigraph and
// ignore this * character.
if (!L->getLangOpts().Trigraphs) {
if (!L->isLexingRawMode())
- L->Diag(CurPtr, diag::trigraph_ignored_block_comment);
+ L->Diag(TrigraphPos, diag::trigraph_ignored_block_comment);
return false;
}
if (!L->isLexingRawMode())
- L->Diag(CurPtr, diag::trigraph_ends_block_comment);
+ L->Diag(TrigraphPos, diag::trigraph_ends_block_comment);
}
// Warn about having an escaped newline between the */ characters.
if (!L->isLexingRawMode())
- L->Diag(CurPtr, diag::escaped_newline_block_comment_end);
+ L->Diag(CurPtr + 1, diag::escaped_newline_block_comment_end);
// If there was space between the backslash and newline, warn about it.
- if (HasSpace && !L->isLexingRawMode())
- L->Diag(CurPtr, diag::backslash_newline_space);
+ if (SpacePos && !L->isLexingRawMode())
+ L->Diag(SpacePos, diag::backslash_newline_space);
return true;
}
@@ -2762,6 +2793,11 @@
if (PP->isRecordingPreamble() && PP->isInPrimaryFile()) {
PP->setRecordedPreambleConditionalStack(ConditionalStack);
+ // If the preamble cuts off the end of a header guard, consider it guarded.
+ // The guard is valid for the preamble content itself, and for tools the
+ // most useful answer is "yes, this file has a header guard".
+ if (!ConditionalStack.empty())
+ MIOpt.ExitTopLevelConditional();
ConditionalStack.clear();
}
@@ -2775,11 +2811,11 @@
ConditionalStack.pop_back();
}
+ SourceLocation EndLoc = getSourceLocation(BufferEnd);
// C99 5.1.1.2p2: If the file is non-empty and didn't end in a newline, issue
// a pedwarn.
if (CurPtr != BufferStart && (CurPtr[-1] != '\n' && CurPtr[-1] != '\r')) {
DiagnosticsEngine &Diags = PP->getDiagnostics();
- SourceLocation EndLoc = getSourceLocation(BufferEnd);
unsigned DiagID;
if (LangOpts.CPlusPlus11) {
@@ -2802,7 +2838,7 @@
BufferPtr = CurPtr;
// Finally, let the preprocessor handle this.
- return PP->HandleEndOfFile(Result, isPragmaLexer());
+ return PP->HandleEndOfFile(Result, EndLoc, isPragmaLexer());
}
/// isNextPPTokenLParen - Return 1 if the next unexpanded token lexed from
@@ -3206,10 +3242,10 @@
const char *CurPtr = BufferPtr;
// Small amounts of horizontal whitespace is very common between tokens.
- if ((*CurPtr == ' ') || (*CurPtr == '\t')) {
- ++CurPtr;
- while ((*CurPtr == ' ') || (*CurPtr == '\t'))
+ if (isHorizontalWhitespace(*CurPtr)) {
+ do {
++CurPtr;
+ } while (isHorizontalWhitespace(*CurPtr));
// If we are keeping whitespace and other tokens, just return what we just
// skipped. The next lexer invocation will return the token after the
diff --git a/src/llvm-project/clang/lib/Lex/LiteralSupport.cpp b/src/llvm-project/clang/lib/Lex/LiteralSupport.cpp
index 6c3cdbd..85d826c 100644
--- a/src/llvm-project/clang/lib/Lex/LiteralSupport.cpp
+++ b/src/llvm-project/clang/lib/Lex/LiteralSupport.cpp
@@ -546,6 +546,7 @@
isLong = false;
isUnsigned = false;
isLongLong = false;
+ isSizeT = false;
isHalf = false;
isFloat = false;
isImaginary = false;
@@ -589,6 +590,7 @@
// integer constant.
bool isFixedPointConstant = isFixedPointLiteral();
bool isFPConstant = isFloatingLiteral();
+ bool HasSize = false;
// Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop.
@@ -616,14 +618,17 @@
if (!(LangOpts.Half || LangOpts.FixedPoint))
break;
if (isIntegerLiteral()) break; // Error for integer constant.
- if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.
+ if (HasSize)
+ break;
+ HasSize = true;
isHalf = true;
continue; // Success.
case 'f': // FP Suffix for "float"
case 'F':
if (!isFPConstant) break; // Error for integer constant.
- if (isHalf || isFloat || isLong || isFloat128)
- break; // HF, FF, LF, QF invalid.
+ if (HasSize)
+ break;
+ HasSize = true;
// CUDA host and device may have different _Float16 support, therefore
// allows f16 literals to avoid false alarm.
@@ -640,8 +645,9 @@
case 'q': // FP Suffix for "__float128"
case 'Q':
if (!isFPConstant) break; // Error for integer constant.
- if (isHalf || isFloat || isLong || isFloat128)
- break; // HQ, FQ, LQ, QQ invalid.
+ if (HasSize)
+ break;
+ HasSize = true;
isFloat128 = true;
continue; // Success.
case 'u':
@@ -652,8 +658,9 @@
continue; // Success.
case 'l':
case 'L':
- if (isLong || isLongLong) break; // Cannot be repeated.
- if (isHalf || isFloat || isFloat128) break; // LH, LF, LQ invalid.
+ if (HasSize)
+ break;
+ HasSize = true;
// Check for long long. The L's need to be adjacent and the same case.
if (s[1] == s[0]) {
@@ -665,42 +672,54 @@
isLong = true;
}
continue; // Success.
+ case 'z':
+ case 'Z':
+ if (isFPConstant)
+ break; // Invalid for floats.
+ if (HasSize)
+ break;
+ HasSize = true;
+ isSizeT = true;
+ continue;
case 'i':
case 'I':
- if (LangOpts.MicrosoftExt) {
- if (isLong || isLongLong || MicrosoftInteger)
+ if (LangOpts.MicrosoftExt && !isFPConstant) {
+ // Allow i8, i16, i32, and i64. First, look ahead and check if
+ // suffixes are Microsoft integers and not the imaginary unit.
+ uint8_t Bits = 0;
+ size_t ToSkip = 0;
+ switch (s[1]) {
+ case '8': // i8 suffix
+ Bits = 8;
+ ToSkip = 2;
break;
-
- if (!isFPConstant) {
- // Allow i8, i16, i32, and i64.
- switch (s[1]) {
- case '8':
- s += 2; // i8 suffix
- MicrosoftInteger = 8;
- break;
- case '1':
- if (s[2] == '6') {
- s += 3; // i16 suffix
- MicrosoftInteger = 16;
- }
- break;
- case '3':
- if (s[2] == '2') {
- s += 3; // i32 suffix
- MicrosoftInteger = 32;
- }
- break;
- case '6':
- if (s[2] == '4') {
- s += 3; // i64 suffix
- MicrosoftInteger = 64;
- }
- break;
- default:
- break;
+ case '1':
+ if (s[2] == '6') { // i16 suffix
+ Bits = 16;
+ ToSkip = 3;
}
+ break;
+ case '3':
+ if (s[2] == '2') { // i32 suffix
+ Bits = 32;
+ ToSkip = 3;
+ }
+ break;
+ case '6':
+ if (s[2] == '4') { // i64 suffix
+ Bits = 64;
+ ToSkip = 3;
+ }
+ break;
+ default:
+ break;
}
- if (MicrosoftInteger) {
+ if (Bits) {
+ if (HasSize)
+ break;
+ HasSize = true;
+ MicrosoftInteger = Bits;
+ s += ToSkip;
assert(s <= ThisTokEnd && "didn't maximally munch?");
break;
}
@@ -727,6 +746,7 @@
isLong = false;
isUnsigned = false;
isLongLong = false;
+ isSizeT = false;
isFloat = false;
isFloat16 = false;
isHalf = false;
@@ -1628,16 +1648,29 @@
// Check for raw string
if (ThisTokBuf[0] == 'R') {
+ if (ThisTokBuf[1] != '"') {
+ // The file may have come from PCH and then changed after loading the
+ // PCH; Fail gracefully.
+ return DiagnoseLexingError(StringToks[i].getLocation());
+ }
ThisTokBuf += 2; // skip R"
+ // C++11 [lex.string]p2: A `d-char-sequence` shall consist of at most 16
+ // characters.
+ constexpr unsigned MaxRawStrDelimLen = 16;
+
const char *Prefix = ThisTokBuf;
- while (ThisTokBuf[0] != '(')
+ while (static_cast<unsigned>(ThisTokBuf - Prefix) < MaxRawStrDelimLen &&
+ ThisTokBuf[0] != '(')
++ThisTokBuf;
+ if (ThisTokBuf[0] != '(')
+ return DiagnoseLexingError(StringToks[i].getLocation());
++ThisTokBuf; // skip '('
// Remove same number of characters from the end
ThisTokEnd -= ThisTokBuf - Prefix;
- assert(ThisTokEnd >= ThisTokBuf && "malformed raw string literal");
+ if (ThisTokEnd < ThisTokBuf)
+ return DiagnoseLexingError(StringToks[i].getLocation());
// C++14 [lex.string]p4: A source-file new-line in a raw string literal
// results in a new-line in the resulting execution string-literal.
diff --git a/src/llvm-project/clang/lib/Lex/ModuleMap.cpp b/src/llvm-project/clang/lib/Lex/ModuleMap.cpp
index bbda1f1..f9af7c2 100644
--- a/src/llvm-project/clang/lib/Lex/ModuleMap.cpp
+++ b/src/llvm-project/clang/lib/Lex/ModuleMap.cpp
@@ -260,9 +260,10 @@
<< UmbrellaMod->getFullModuleName();
else
// Record this umbrella header.
- setUmbrellaHeader(Mod, *File, RelativePathName.str());
+ setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
} else {
- Module::Header H = {std::string(RelativePathName.str()), *File};
+ Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
+ *File};
if (Header.Kind == Module::HK_Excluded)
excludeHeader(Mod, H);
else
@@ -300,12 +301,12 @@
// supplied by Clang. Find that builtin header.
SmallString<128> Path;
llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
- auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
+ auto File = SourceMgr.getFileManager().getFile(Path);
if (!File)
return false;
auto Role = headerKindToRole(Header.Kind);
- Module::Header H = {std::string(Path.str()), *File};
+ Module::Header H = {Header.FileName, std::string(Path.str()), *File};
addHeader(Mod, H, Role);
return true;
}
@@ -1012,7 +1013,7 @@
// Look for an umbrella header.
SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
- auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);
+ auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
// FIXME: If there's no umbrella header, we could probably scan the
// framework to load *everything*. But, it's not clear that this is a good
@@ -1038,11 +1039,13 @@
Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
Result->Directory = FrameworkDir;
+ // Chop off the first framework bit, as that is implied.
+ StringRef RelativePath = UmbrellaName.str().substr(
+ Result->getTopLevelModule()->Directory->getName().size());
+ RelativePath = llvm::sys::path::relative_path(RelativePath);
+
// umbrella header "umbrella-header-name"
- //
- // The "Headers/" component of the name is implied because this is
- // a framework module.
- setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h");
+ setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
// export *
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
@@ -1121,22 +1124,28 @@
return Result;
}
-void ModuleMap::setUmbrellaHeader(Module *Mod, FileEntryRef UmbrellaHeader,
- Twine NameAsWritten) {
+void ModuleMap::setUmbrellaHeader(
+ Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten,
+ const Twine &PathRelativeToRootModuleDirectory) {
Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
- Mod->Umbrella = &UmbrellaHeader.getMapEntry();
+ Mod->Umbrella = UmbrellaHeader;
Mod->UmbrellaAsWritten = NameAsWritten.str();
- UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
+ Mod->UmbrellaRelativeToRootModuleDirectory =
+ PathRelativeToRootModuleDirectory.str();
+ UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
// Notify callbacks that we just added a new header.
for (const auto &Cb : Callbacks)
Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
}
-void ModuleMap::setUmbrellaDir(Module *Mod, DirectoryEntryRef UmbrellaDir,
- Twine NameAsWritten) {
- Mod->Umbrella = &UmbrellaDir.getMapEntry();
+void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
+ const Twine &NameAsWritten,
+ const Twine &PathRelativeToRootModuleDirectory) {
+ Mod->Umbrella = UmbrellaDir;
Mod->UmbrellaAsWritten = NameAsWritten.str();
+ Mod->UmbrellaRelativeToRootModuleDirectory =
+ PathRelativeToRootModuleDirectory.str();
UmbrellaDirs[UmbrellaDir] = Mod;
}
@@ -1369,7 +1378,7 @@
RSquare
} Kind;
- unsigned Location;
+ SourceLocation::UIntTy Location;
unsigned StringLength;
union {
// If Kind != IntegerLiteral.
@@ -2405,6 +2414,7 @@
}
std::string DirName = std::string(Tok.getString());
+ std::string DirNameAsWritten = DirName;
SourceLocation DirNameLoc = consumeToken();
// Check whether we already have an umbrella.
@@ -2416,15 +2426,15 @@
}
// Look for this file.
- Optional<DirectoryEntryRef> Dir;
+ const DirectoryEntry *Dir = nullptr;
if (llvm::sys::path::is_absolute(DirName)) {
- if (auto D = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName))
+ if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
Dir = *D;
} else {
SmallString<128> PathName;
PathName = Directory->getName();
llvm::sys::path::append(PathName, DirName);
- if (auto D = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName))
+ if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
Dir = *D;
}
@@ -2445,8 +2455,8 @@
SourceMgr.getFileManager().getVirtualFileSystem();
for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
I != E && !EC; I.increment(EC)) {
- if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
- Module::Header Header = {std::string(I->path()), *FE};
+ if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
+ Module::Header Header = {"", std::string(I->path()), *FE};
Headers.push_back(std::move(Header));
}
}
@@ -2459,7 +2469,7 @@
return;
}
- if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
+ if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
<< OwningModule->getFullModuleName();
HadError = true;
@@ -2467,7 +2477,7 @@
}
// Record this umbrella directory.
- Map.setUmbrellaDir(ActiveModule, *Dir, DirName);
+ Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
}
/// Parse a module export declaration.
diff --git a/src/llvm-project/clang/lib/Lex/PPCaching.cpp b/src/llvm-project/clang/lib/Lex/PPCaching.cpp
index 31548d2..e05e52b 100644
--- a/src/llvm-project/clang/lib/Lex/PPCaching.cpp
+++ b/src/llvm-project/clang/lib/Lex/PPCaching.cpp
@@ -145,7 +145,7 @@
if (LastCachedTok.getKind() != Tok.getKind())
return false;
- int RelOffset = 0;
+ SourceLocation::IntTy RelOffset = 0;
if ((!getSourceManager().isInSameSLocAddrSpace(
Tok.getLocation(), getLastCachedTokenLocation(), &RelOffset)) ||
RelOffset)
diff --git a/src/llvm-project/clang/lib/Lex/PPConditionalDirectiveRecord.cpp b/src/llvm-project/clang/lib/Lex/PPConditionalDirectiveRecord.cpp
index facee28..ddc88f8 100644
--- a/src/llvm-project/clang/lib/Lex/PPConditionalDirectiveRecord.cpp
+++ b/src/llvm-project/clang/lib/Lex/PPConditionalDirectiveRecord.cpp
@@ -101,6 +101,28 @@
CondDirectiveStack.back() = Loc;
}
+void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) {
+ addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
+ CondDirectiveStack.back() = Loc;
+}
+void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, SourceRange,
+ SourceLocation) {
+ addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
+ CondDirectiveStack.back() = Loc;
+}
+
+void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, const Token &,
+ const MacroDefinition &) {
+ addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
+ CondDirectiveStack.back() = Loc;
+}
+void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, SourceRange,
+ SourceLocation) {
+ addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
+ CondDirectiveStack.back() = Loc;
+}
+
void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
SourceLocation IfLoc) {
addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
diff --git a/src/llvm-project/clang/lib/Lex/PPDirectives.cpp b/src/llvm-project/clang/lib/Lex/PPDirectives.cpp
index d6b03d8..3fa8746 100644
--- a/src/llvm-project/clang/lib/Lex/PPDirectives.cpp
+++ b/src/llvm-project/clang/lib/Lex/PPDirectives.cpp
@@ -100,31 +100,19 @@
MD_ReservedMacro //> #define of #undef reserved id, disabled by default
};
-/// Checks if the specified identifier is reserved in the specified
-/// language.
-/// This function does not check if the identifier is a keyword.
-static bool isReservedId(StringRef Text, const LangOptions &Lang) {
- // C++ [macro.names], C11 7.1.3:
- // All identifiers that begin with an underscore and either an uppercase
- // letter or another underscore are always reserved for any use.
- if (Text.size() >= 2 && Text[0] == '_' &&
- (isUppercase(Text[1]) || Text[1] == '_'))
- return true;
- // C++ [global.names]
- // Each name that contains a double underscore ... is reserved to the
- // implementation for any use.
- if (Lang.CPlusPlus) {
- if (Text.find("__") != StringRef::npos)
- return true;
- }
- return false;
-}
+/// Enumerates possible %select values for the pp_err_elif_after_else and
+/// pp_err_elif_without_if diagnostics.
+enum PPElifDiag {
+ PED_Elif,
+ PED_Elifdef,
+ PED_Elifndef
+};
// The -fmodule-name option tells the compiler to textually include headers in
// the specified module, meaning clang won't build the specified module. This is
// useful in a number of situations, for instance, when building a library that
// vends a module map, one might want to avoid hitting intermediate build
-// products containimg the the module map or avoid finding the system installed
+// products containing the the module map or avoid finding the system installed
// modulemap for that library.
static bool isForModuleBuilding(Module *M, StringRef CurrentModule,
StringRef ModuleName) {
@@ -141,9 +129,50 @@
static MacroDiag shouldWarnOnMacroDef(Preprocessor &PP, IdentifierInfo *II) {
const LangOptions &Lang = PP.getLangOpts();
- StringRef Text = II->getName();
- if (isReservedId(Text, Lang))
+ if (II->isReserved(Lang) != ReservedIdentifierStatus::NotReserved) {
+ // list from:
+ // - https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html
+ // - https://docs.microsoft.com/en-us/cpp/c-runtime-library/security-features-in-the-crt?view=msvc-160
+ // - man 7 feature_test_macros
+ // The list must be sorted for correct binary search.
+ static constexpr StringRef ReservedMacro[] = {
+ "_ATFILE_SOURCE",
+ "_BSD_SOURCE",
+ "_CRT_NONSTDC_NO_WARNINGS",
+ "_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES",
+ "_CRT_SECURE_NO_WARNINGS",
+ "_FILE_OFFSET_BITS",
+ "_FORTIFY_SOURCE",
+ "_GLIBCXX_ASSERTIONS",
+ "_GLIBCXX_CONCEPT_CHECKS",
+ "_GLIBCXX_DEBUG",
+ "_GLIBCXX_DEBUG_PEDANTIC",
+ "_GLIBCXX_PARALLEL",
+ "_GLIBCXX_PARALLEL_ASSERTIONS",
+ "_GLIBCXX_SANITIZE_VECTOR",
+ "_GLIBCXX_USE_CXX11_ABI",
+ "_GLIBCXX_USE_DEPRECATED",
+ "_GNU_SOURCE",
+ "_ISOC11_SOURCE",
+ "_ISOC95_SOURCE",
+ "_ISOC99_SOURCE",
+ "_LARGEFILE64_SOURCE",
+ "_POSIX_C_SOURCE",
+ "_REENTRANT",
+ "_SVID_SOURCE",
+ "_THREAD_SAFE",
+ "_XOPEN_SOURCE",
+ "_XOPEN_SOURCE_EXTENDED",
+ "__STDCPP_WANT_MATH_SPEC_FUNCS__",
+ "__STDC_FORMAT_MACROS",
+ };
+ if (std::binary_search(std::begin(ReservedMacro), std::end(ReservedMacro),
+ II->getName()))
+ return MD_NoWarn;
+
return MD_ReservedMacro;
+ }
+ StringRef Text = II->getName();
if (II->isKeyword(Lang))
return MD_KeywordDef;
if (Lang.CPlusPlus11 && (Text.equals("override") || Text.equals("final")))
@@ -153,9 +182,8 @@
static MacroDiag shouldWarnOnMacroUndef(Preprocessor &PP, IdentifierInfo *II) {
const LangOptions &Lang = PP.getLangOpts();
- StringRef Text = II->getName();
// Do not warn on keyword undef. It is generally harmless and widely used.
- if (isReservedId(Text, Lang))
+ if (II->isReserved(Lang) != ReservedIdentifierStatus::NotReserved)
return MD_ReservedMacro;
return MD_NoWarn;
}
@@ -168,7 +196,7 @@
static bool warnByDefaultOnWrongCase(StringRef Include) {
// If the first component of the path is "boost", treat this like a standard header
// for the purposes of diagnostics.
- if (::llvm::sys::path::begin(Include)->equals_lower("boost"))
+ if (::llvm::sys::path::begin(Include)->equals_insensitive("boost"))
return true;
// "condition_variable" is the longest standard header name at 18 characters.
@@ -441,9 +469,9 @@
CurLexer->Lex(Tok);
if (Tok.is(tok::code_completion)) {
+ setCodeCompletionReached();
if (CodeComplete)
CodeComplete->CodeCompleteInConditionalExclusion();
- setCodeCompletionReached();
continue;
}
@@ -558,7 +586,8 @@
PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
// If this is a #else with a #else before it, report the error.
- if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_else_after_else);
+ if (CondInfo.FoundElse)
+ Diag(Tok, diag::pp_err_else_after_else);
// Note that we've seen a #else in this conditional.
CondInfo.FoundElse = true;
@@ -582,7 +611,8 @@
PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
// If this is a #elif with a #else before it, report the error.
- if (CondInfo.FoundElse) Diag(Tok, diag::pp_err_elif_after_else);
+ if (CondInfo.FoundElse)
+ Diag(Tok, diag::pp_err_elif_after_else) << PED_Elif;
// If this is in a skipping block or if we're already handled this #if
// block, don't bother parsing the condition.
@@ -595,6 +625,9 @@
CurPPLexer->LexingRawMode = false;
IdentifierInfo *IfNDefMacro = nullptr;
DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
+ // Stop if Lexer became invalid after hitting code completion token.
+ if (!CurPPLexer)
+ return;
const bool CondValue = DER.Conditional;
CurPPLexer->LexingRawMode = true;
if (Callbacks) {
@@ -609,6 +642,59 @@
break;
}
}
+ } else if (Sub == "lifdef" || // "elifdef"
+ Sub == "lifndef") { // "elifndef"
+ bool IsElifDef = Sub == "lifdef";
+ PPConditionalInfo &CondInfo = CurPPLexer->peekConditionalLevel();
+ Token DirectiveToken = Tok;
+
+ // If this is a #elif with a #else before it, report the error.
+ if (CondInfo.FoundElse)
+ Diag(Tok, diag::pp_err_elif_after_else)
+ << (IsElifDef ? PED_Elifdef : PED_Elifndef);
+
+ // If this is in a skipping block or if we're already handled this #if
+ // block, don't bother parsing the condition.
+ if (CondInfo.WasSkipping || CondInfo.FoundNonSkip) {
+ DiscardUntilEndOfDirective();
+ } else {
+ // Restore the value of LexingRawMode so that identifiers are
+ // looked up, etc, inside the #elif[n]def expression.
+ assert(CurPPLexer->LexingRawMode && "We have to be skipping here!");
+ CurPPLexer->LexingRawMode = false;
+ Token MacroNameTok;
+ ReadMacroName(MacroNameTok);
+ CurPPLexer->LexingRawMode = true;
+
+ // If the macro name token is tok::eod, there was an error that was
+ // already reported.
+ if (MacroNameTok.is(tok::eod)) {
+ // Skip code until we get to #endif. This helps with recovery by
+ // not emitting an error when the #endif is reached.
+ continue;
+ }
+
+ CheckEndOfDirective(IsElifDef ? "elifdef" : "elifndef");
+
+ IdentifierInfo *MII = MacroNameTok.getIdentifierInfo();
+ auto MD = getMacroDefinition(MII);
+ MacroInfo *MI = MD.getMacroInfo();
+
+ if (Callbacks) {
+ if (IsElifDef) {
+ Callbacks->Elifdef(DirectiveToken.getLocation(), MacroNameTok,
+ MD);
+ } else {
+ Callbacks->Elifndef(DirectiveToken.getLocation(), MacroNameTok,
+ MD);
+ }
+ }
+ // If this condition is true, enter it!
+ if (static_cast<bool>(MI) == IsElifDef) {
+ CondInfo.FoundNonSkip = true;
+ break;
+ }
+ }
}
}
@@ -966,10 +1052,10 @@
case tok::eod:
return; // null directive.
case tok::code_completion:
+ setCodeCompletionReached();
if (CodeComplete)
CodeComplete->CodeCompleteDirective(
CurPPLexer->getConditionalStackDepth() > 0);
- setCodeCompletionReached();
return;
case tok::numeric_constant: // # 7 GNU line marker directive.
if (getLangOpts().AsmPreprocessor)
@@ -992,7 +1078,10 @@
return HandleIfdefDirective(Result, SavedHash, true,
ReadAnyTokensBeforeDirective);
case tok::pp_elif:
- return HandleElifDirective(Result, SavedHash);
+ case tok::pp_elifdef:
+ case tok::pp_elifndef:
+ return HandleElifFamilyDirective(Result, SavedHash, II->getPPKeywordID());
+
case tok::pp_else:
return HandleElseDirective(Result, SavedHash);
case tok::pp_endif:
@@ -1045,12 +1134,12 @@
break;
case tok::pp___public_macro:
- if (getLangOpts().Modules)
+ if (getLangOpts().Modules || getLangOpts().ModulesLocalVisibility)
return HandleMacroPublicDirective(Result);
break;
case tok::pp___private_macro:
- if (getLangOpts().Modules)
+ if (getLangOpts().Modules || getLangOpts().ModulesLocalVisibility)
return HandleMacroPrivateDirective();
break;
}
@@ -1391,7 +1480,7 @@
// Find the first non-whitespace character, so that we can make the
// diagnostic more succinct.
- StringRef Msg = StringRef(Message).ltrim(' ');
+ StringRef Msg = Message.str().ltrim(' ');
if (isWarning)
Diag(Tok, diag::pp_hash_warning) << Msg;
@@ -1634,7 +1723,8 @@
// If these path components differ by more than just case, then we
// may be looking at symlinked paths. Bail on this diagnostic to avoid
// noisy false positives.
- SuggestReplacement = RealPathComponentIter->equals_lower(Component);
+ SuggestReplacement =
+ RealPathComponentIter->equals_insensitive(Component);
if (!SuggestReplacement)
break;
Component = *RealPathComponentIter;
@@ -1932,6 +2022,10 @@
IsFrameworkFound, IsImportDecl, IsMapped, LookupFrom, LookupFromFile,
LookupFilename, RelativePath, SearchPath, SuggestedModule, isAngled);
+ // Record the header's filename for later use.
+ if (File)
+ CurLexer->addInclude(OriginalFilename, File->getFileEntry(), FilenameLoc);
+
if (usingPCHWithThroughHeader() && SkippingUntilPCHThroughHeader) {
if (File && isPCHThroughHeader(&File->getFileEntry()))
SkippingUntilPCHThroughHeader = false;
@@ -2870,6 +2964,23 @@
// If the callbacks want to know, tell them about the macro definition.
if (Callbacks)
Callbacks->MacroDefined(MacroNameTok, MD);
+
+ // If we're in MS compatibility mode and the macro being defined is the
+ // assert macro, implicitly add a macro definition for static_assert to work
+ // around their broken assert.h header file in C. Only do so if there isn't
+ // already a static_assert macro defined.
+ if (!getLangOpts().CPlusPlus && getLangOpts().MSVCCompat &&
+ MacroNameTok.getIdentifierInfo()->isStr("assert") &&
+ !isMacroDefined("static_assert")) {
+ MacroInfo *MI = AllocateMacroInfo(SourceLocation());
+
+ Token Tok;
+ Tok.startToken();
+ Tok.setKind(tok::kw__Static_assert);
+ Tok.setIdentifierInfo(getIdentifierInfo("_Static_assert"));
+ MI->AddTokenToBody(Tok);
+ (void)appendDefMacroDirective(getIdentifierInfo("static_assert"), MI);
+ }
}
/// HandleUndefDirective - Implements \#undef.
@@ -3006,6 +3117,10 @@
IdentifierInfo *IfNDefMacro = nullptr;
const DirectiveEvalResult DER = EvaluateDirectiveExpression(IfNDefMacro);
const bool ConditionalTrue = DER.Conditional;
+ // Lexer might become invalid if we hit code completion point while evaluating
+ // expression.
+ if (!CurPPLexer)
+ return;
// If this condition is equivalent to #ifndef X, and if this is the first
// directive seen, handle it for the multiple-include optimization.
@@ -3110,10 +3225,13 @@
/*FoundElse*/ true, Result.getLocation());
}
-/// HandleElifDirective - Implements the \#elif directive.
-///
-void Preprocessor::HandleElifDirective(Token &ElifToken,
- const Token &HashToken) {
+/// Implements the \#elif, \#elifdef, and \#elifndef directives.
+void Preprocessor::HandleElifFamilyDirective(Token &ElifToken,
+ const Token &HashToken,
+ tok::PPKeywordKind Kind) {
+ PPElifDiag DirKind = Kind == tok::pp_elif ? PED_Elif
+ : Kind == tok::pp_elifdef ? PED_Elifdef
+ : PED_Elifndef;
++NumElse;
// #elif directive in a non-skipping conditional... start skipping.
@@ -3123,7 +3241,7 @@
PPConditionalInfo CI;
if (CurPPLexer->popConditionalLevel(CI)) {
- Diag(ElifToken, diag::pp_err_elif_without_if);
+ Diag(ElifToken, diag::pp_err_elif_without_if) << DirKind;
return;
}
@@ -3132,11 +3250,26 @@
CurPPLexer->MIOpt.EnterTopLevelConditional();
// If this is a #elif with a #else before it, report the error.
- if (CI.FoundElse) Diag(ElifToken, diag::pp_err_elif_after_else);
+ if (CI.FoundElse)
+ Diag(ElifToken, diag::pp_err_elif_after_else) << DirKind;
- if (Callbacks)
- Callbacks->Elif(ElifToken.getLocation(), ConditionRange,
- PPCallbacks::CVK_NotEvaluated, CI.IfLoc);
+ if (Callbacks) {
+ switch (Kind) {
+ case tok::pp_elif:
+ Callbacks->Elif(ElifToken.getLocation(), ConditionRange,
+ PPCallbacks::CVK_NotEvaluated, CI.IfLoc);
+ break;
+ case tok::pp_elifdef:
+ Callbacks->Elifdef(ElifToken.getLocation(), ConditionRange, CI.IfLoc);
+ break;
+ case tok::pp_elifndef:
+ Callbacks->Elifndef(ElifToken.getLocation(), ConditionRange, CI.IfLoc);
+ break;
+ default:
+ assert(false && "unexpected directive kind");
+ break;
+ }
+ }
bool RetainExcludedCB = PPOpts->RetainExcludedConditionalBlocks &&
getSourceManager().isInMainFile(ElifToken.getLocation());
diff --git a/src/llvm-project/clang/lib/Lex/PPExpressions.cpp b/src/llvm-project/clang/lib/Lex/PPExpressions.cpp
index 8c120c1..cab4bab 100644
--- a/src/llvm-project/clang/lib/Lex/PPExpressions.cpp
+++ b/src/llvm-project/clang/lib/Lex/PPExpressions.cpp
@@ -321,6 +321,14 @@
PP.Diag(PeekTok, diag::ext_c99_longlong);
}
+ // 'z/uz' literals are a C++2b feature.
+ if (Literal.isSizeT)
+ PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus
+ ? PP.getLangOpts().CPlusPlus2b
+ ? diag::warn_cxx20_compat_size_t_suffix
+ : diag::ext_cxx2b_size_t_suffix
+ : diag::err_cxx2b_size_t_suffix);
+
// Parse the integer literal into Result.
if (Literal.GetIntegerValue(Result.Val)) {
// Overflow parsing integer literal.
@@ -658,13 +666,13 @@
if (ValueLive && Res.isUnsigned()) {
if (!LHS.isUnsigned() && LHS.Val.isNegative())
PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0
- << LHS.Val.toString(10, true) + " to " +
- LHS.Val.toString(10, false)
+ << toString(LHS.Val, 10, true) + " to " +
+ toString(LHS.Val, 10, false)
<< LHS.getRange() << RHS.getRange();
if (!RHS.isUnsigned() && RHS.Val.isNegative())
PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1
- << RHS.Val.toString(10, true) + " to " +
- RHS.Val.toString(10, false)
+ << toString(RHS.Val, 10, true) + " to " +
+ toString(RHS.Val, 10, false)
<< LHS.getRange() << RHS.getRange();
}
LHS.Val.setIsUnsigned(Res.isUnsigned());
diff --git a/src/llvm-project/clang/lib/Lex/PPLexerChange.cpp b/src/llvm-project/clang/lib/Lex/PPLexerChange.cpp
index b979b96..1617096 100644
--- a/src/llvm-project/clang/lib/Lex/PPLexerChange.cpp
+++ b/src/llvm-project/clang/lib/Lex/PPLexerChange.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
@@ -22,6 +23,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/Path.h"
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -299,10 +301,46 @@
}
}
+void Preprocessor::ResolvePragmaIncludeInstead(
+ const SourceLocation Location) const {
+ assert(Location.isValid());
+ if (CurLexer == nullptr)
+ return;
+
+ if (SourceMgr.isInSystemHeader(Location))
+ return;
+
+ for (const auto &Include : CurLexer->getIncludeHistory()) {
+ StringRef Filename = Include.getKey();
+ const PreprocessorLexer::IncludeInfo &Info = Include.getValue();
+ ArrayRef<SmallString<32>> Aliases =
+ HeaderInfo.getFileInfo(Info.File).Aliases.getArrayRef();
+
+ if (Aliases.empty())
+ continue;
+
+ switch (Aliases.size()) {
+ case 1:
+ Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
+ << Filename << 0 << Aliases[0];
+ continue;
+ case 2:
+ Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
+ << Filename << 1 << Aliases[0] << Aliases[1];
+ continue;
+ default: {
+ Diag(Info.Location, diag::err_pragma_include_instead_system_reserved)
+ << Filename << 2 << ("{'" + llvm::join(Aliases, "', '") + "'}");
+ }
+ }
+ }
+}
+
/// HandleEndOfFile - This callback is invoked when the lexer hits the end of
/// the current file. This either returns the EOF token or pops a level off
/// the include stack and keeps going.
-bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
+bool Preprocessor::HandleEndOfFile(Token &Result, SourceLocation EndLoc,
+ bool isEndOfMacro) {
assert(!CurTokenLexer &&
"Ending a file when currently in a macro!");
@@ -372,6 +410,9 @@
}
}
+ if (EndLoc.isValid())
+ ResolvePragmaIncludeInstead(EndLoc);
+
// Complain about reaching a true EOF within arc_cf_code_audited.
// We don't want to complain about reaching the end of a macro
// instantiation or a _Pragma.
@@ -560,7 +601,7 @@
TokenLexerCache[NumCachedTokenLexers++] = std::move(CurTokenLexer);
// Handle this like a #include file being popped off the stack.
- return HandleEndOfFile(Result, true);
+ return HandleEndOfFile(Result, {}, true);
}
/// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
diff --git a/src/llvm-project/clang/lib/Lex/PPMacroExpansion.cpp b/src/llvm-project/clang/lib/Lex/PPMacroExpansion.cpp
index 43d31d6..d8ad9d8 100644
--- a/src/llvm-project/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/src/llvm-project/clang/lib/Lex/PPMacroExpansion.cpp
@@ -25,6 +25,7 @@
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -170,7 +171,8 @@
return MM;
}
-ModuleMacro *Preprocessor::getModuleMacro(Module *Mod, IdentifierInfo *II) {
+ModuleMacro *Preprocessor::getModuleMacro(Module *Mod,
+ const IdentifierInfo *II) {
llvm::FoldingSetNodeID ID;
ModuleMacro::Profile(ID, Mod, II);
@@ -1428,7 +1430,7 @@
StringRef VendorName = TI.getTriple().getVendorName();
if (VendorName.empty())
VendorName = "unknown";
- return VendorName.equals_lower(II->getName());
+ return VendorName.equals_insensitive(II->getName());
}
/// Implements the __is_target_os builtin macro.
@@ -1451,15 +1453,6 @@
return TI.getTriple().getEnvironment() == Env.getEnvironment();
}
-static void remapMacroPath(
- SmallString<256> &Path,
- const std::map<std::string, std::string, std::greater<std::string>>
- &MacroPrefixMap) {
- for (const auto &Entry : MacroPrefixMap)
- if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
- break;
-}
-
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
/// as a builtin macro, handle it and return the next token as 'Tok'.
void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
@@ -1541,7 +1534,7 @@
} else {
FN += PLoc.getFilename();
}
- remapMacroPath(FN, PPOpts->MacroPrefixMap);
+ getLangOpts().remapPathPrefix(FN);
Lexer::Stringify(FN);
OS << '"' << FN << '"';
}
@@ -1812,7 +1805,14 @@
if (!Tok.isAnnotation() && Tok.getIdentifierInfo())
Tok.setKind(tok::identifier);
- else {
+ else if (Tok.is(tok::string_literal) && !Tok.hasUDSuffix()) {
+ StringLiteralParser Literal(Tok, *this);
+ if (Literal.hadError)
+ return;
+
+ Tok.setIdentifierInfo(getIdentifierInfo(Literal.GetString()));
+ Tok.setKind(tok::identifier);
+ } else {
Diag(Tok.getLocation(), diag::err_pp_identifier_arg_not_identifier)
<< Tok.getKind();
// Don't walk past anything that's not a real token.
diff --git a/src/llvm-project/clang/lib/Lex/Pragma.cpp b/src/llvm-project/clang/lib/Lex/Pragma.cpp
index a05df06..27765af 100644
--- a/src/llvm-project/clang/lib/Lex/Pragma.cpp
+++ b/src/llvm-project/clang/lib/Lex/Pragma.cpp
@@ -13,6 +13,7 @@
#include "clang/Lex/Pragma.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticLex.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
@@ -35,11 +36,12 @@
#include "clang/Lex/TokenLexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Timer.h"
@@ -412,9 +414,13 @@
HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
}
-void Preprocessor::HandlePragmaMark() {
+void Preprocessor::HandlePragmaMark(Token &MarkTok) {
assert(CurPPLexer && "No current lexer?");
- CurLexer->ReadToEndOfLine();
+
+ SmallString<64> Buffer;
+ CurLexer->ReadToEndOfLine(&Buffer);
+ if (Callbacks)
+ Callbacks->PragmaMark(MarkTok.getLocation(), Buffer);
}
/// HandlePragmaPoison - Handle \#pragma GCC poison. PoisonTok is the 'poison'.
@@ -491,43 +497,88 @@
SrcMgr::C_System);
}
-/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
-void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
+static llvm::Optional<Token> LexHeader(Preprocessor &PP,
+ Optional<FileEntryRef> &File,
+ bool SuppressIncludeNotFoundError) {
Token FilenameTok;
- if (LexHeaderName(FilenameTok, /*AllowConcatenation*/false))
- return;
+ if (PP.LexHeaderName(FilenameTok, /*AllowConcatenation*/ false))
+ return llvm::None;
// If the next token wasn't a header-name, diagnose the error.
if (FilenameTok.isNot(tok::header_name)) {
- Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
- return;
+ PP.Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
+ return llvm::None;
}
// Reserve a buffer to get the spelling.
SmallString<128> FilenameBuffer;
bool Invalid = false;
- StringRef Filename = getSpelling(FilenameTok, FilenameBuffer, &Invalid);
+ StringRef Filename = PP.getSpelling(FilenameTok, FilenameBuffer, &Invalid);
if (Invalid)
- return;
+ return llvm::None;
bool isAngled =
- GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
+ PP.GetIncludeFilenameSpelling(FilenameTok.getLocation(), Filename);
// If GetIncludeFilenameSpelling set the start ptr to null, there was an
// error.
if (Filename.empty())
- return;
+ return llvm::None;
// Search include directories for this file.
const DirectoryLookup *CurDir;
- Optional<FileEntryRef> File =
- LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
- nullptr, CurDir, nullptr, nullptr, nullptr, nullptr, nullptr);
+ File = PP.LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
+ nullptr, CurDir, nullptr, nullptr, nullptr, nullptr,
+ nullptr);
if (!File) {
if (!SuppressIncludeNotFoundError)
- Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
+ PP.Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
+ return llvm::None;
+ }
+
+ return FilenameTok;
+}
+
+/// HandlePragmaIncludeInstead - Handle \#pragma clang include_instead(header).
+void Preprocessor::HandlePragmaIncludeInstead(Token &Tok) {
+ // Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
+ PreprocessorLexer *TheLexer = getCurrentFileLexer();
+
+ if (!SourceMgr.isInSystemHeader(Tok.getLocation())) {
+ Diag(Tok, diag::err_pragma_include_instead_not_sysheader);
return;
}
+ Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(Tok, diag::err_expected) << "(";
+ return;
+ }
+
+ Optional<FileEntryRef> File;
+ llvm::Optional<Token> FilenameTok =
+ LexHeader(*this, File, SuppressIncludeNotFoundError);
+ if (!FilenameTok)
+ return;
+
+ Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(Tok, diag::err_expected) << ")";
+ return;
+ }
+
+ SmallString<128> FilenameBuffer;
+ StringRef Filename = getSpelling(*FilenameTok, FilenameBuffer);
+ HeaderInfo.AddFileAlias(TheLexer->getFileEntry(), Filename);
+}
+
+/// HandlePragmaDependency - Handle \#pragma GCC dependency "foo" blah.
+void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
+ Optional<FileEntryRef> File;
+ llvm::Optional<Token> FilenameTok =
+ LexHeader(*this, File, SuppressIncludeNotFoundError);
+ if (!FilenameTok)
+ return;
+
const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
// If this file is older than the file it depends on, emit a diagnostic.
@@ -543,7 +594,7 @@
// Remove the trailing ' ' if present.
if (!Message.empty())
Message.erase(Message.end()-1);
- Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
+ Diag(*FilenameTok, diag::pp_out_of_date_dependency) << Message;
}
}
@@ -992,7 +1043,7 @@
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Token &MarkTok) override {
- PP.HandlePragmaMark();
+ PP.HandlePragmaMark(MarkTok);
}
};
@@ -1018,6 +1069,18 @@
}
};
+/// PragmaIncludeInsteadHandler - "\#pragma clang include_instead(header)" marks
+/// the current file as non-includable if the including header is not a system
+/// header.
+struct PragmaIncludeInsteadHandler : public PragmaHandler {
+ PragmaIncludeInsteadHandler() : PragmaHandler("include_instead") {}
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &IIToken) override {
+ PP.HandlePragmaIncludeInstead(IIToken);
+ }
+};
+
struct PragmaDependencyHandler : public PragmaHandler {
PragmaDependencyHandler() : PragmaHandler("dependency") {}
@@ -1122,6 +1185,57 @@
DebugOverflowStack();
} else if (II->isStr("captured")) {
HandleCaptured(PP);
+ } else if (II->isStr("modules")) {
+ struct ModuleVisitor {
+ Preprocessor &PP;
+ void visit(Module *M, bool VisibleOnly) {
+ SourceLocation ImportLoc = PP.getModuleImportLoc(M);
+ if (!VisibleOnly || ImportLoc.isValid()) {
+ llvm::errs() << M->getFullModuleName() << " ";
+ if (ImportLoc.isValid()) {
+ llvm::errs() << M << " visible ";
+ ImportLoc.print(llvm::errs(), PP.getSourceManager());
+ }
+ llvm::errs() << "\n";
+ }
+ for (Module *Sub : M->submodules()) {
+ if (!VisibleOnly || ImportLoc.isInvalid() || Sub->IsExplicit)
+ visit(Sub, VisibleOnly);
+ }
+ }
+ void visitAll(bool VisibleOnly) {
+ for (auto &NameAndMod :
+ PP.getHeaderSearchInfo().getModuleMap().modules())
+ visit(NameAndMod.second, VisibleOnly);
+ }
+ } Visitor{PP};
+
+ Token Kind;
+ PP.LexUnexpandedToken(Kind);
+ auto *DumpII = Kind.getIdentifierInfo();
+ if (!DumpII) {
+ PP.Diag(Kind, diag::warn_pragma_debug_missing_argument)
+ << II->getName();
+ } else if (DumpII->isStr("all")) {
+ Visitor.visitAll(false);
+ } else if (DumpII->isStr("visible")) {
+ Visitor.visitAll(true);
+ } else if (DumpII->isStr("building")) {
+ for (auto &Building : PP.getBuildingSubmodules()) {
+ llvm::errs() << "in " << Building.M->getFullModuleName();
+ if (Building.ImportLoc.isValid()) {
+ llvm::errs() << " imported ";
+ if (Building.IsPragma)
+ llvm::errs() << "via pragma ";
+ llvm::errs() << "at ";
+ Building.ImportLoc.print(llvm::errs(), PP.getSourceManager());
+ llvm::errs() << "\n";
+ }
+ }
+ } else {
+ PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
+ << DumpII->getName();
+ }
} else {
PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
<< II->getName();
@@ -1879,6 +1993,7 @@
// #pragma clang ...
AddPragmaHandler("clang", new PragmaPoisonHandler());
AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
+ AddPragmaHandler("clang", new PragmaIncludeInsteadHandler());
AddPragmaHandler("clang", new PragmaDebugHandler());
AddPragmaHandler("clang", new PragmaDependencyHandler());
AddPragmaHandler("clang", new PragmaDiagnosticHandler("clang"));
@@ -1904,6 +2019,7 @@
AddPragmaHandler(new PragmaExecCharsetHandler());
AddPragmaHandler(new PragmaIncludeAliasHandler());
AddPragmaHandler(new PragmaHdrstopHandler());
+ AddPragmaHandler(new PragmaSystemHeaderHandler());
}
// Pragmas added by plugins
diff --git a/src/llvm-project/clang/lib/Lex/PreprocessingRecord.cpp b/src/llvm-project/clang/lib/Lex/PreprocessingRecord.cpp
index 115256d..ed59dbd 100644
--- a/src/llvm-project/clang/lib/Lex/PreprocessingRecord.cpp
+++ b/src/llvm-project/clang/lib/Lex/PreprocessingRecord.cpp
@@ -411,6 +411,14 @@
MacroNameTok.getLocation());
}
+void PreprocessingRecord::Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ // This is not actually a macro expansion but record it as a macro reference.
+ if (MD)
+ addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
+ MacroNameTok.getLocation());
+}
+
void PreprocessingRecord::Ifndef(SourceLocation Loc, const Token &MacroNameTok,
const MacroDefinition &MD) {
// This is not actually a macro expansion but record it as a macro reference.
@@ -419,6 +427,15 @@
MacroNameTok.getLocation());
}
+void PreprocessingRecord::Elifndef(SourceLocation Loc,
+ const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ // This is not actually a macro expansion but record it as a macro reference.
+ if (MD)
+ addMacroExpansion(MacroNameTok, MD.getMacroInfo(),
+ MacroNameTok.getLocation());
+}
+
void PreprocessingRecord::Defined(const Token &MacroNameTok,
const MacroDefinition &MD,
SourceRange Range) {
diff --git a/src/llvm-project/clang/lib/Lex/Preprocessor.cpp b/src/llvm-project/clang/lib/Lex/Preprocessor.cpp
index 177786d..e376fff 100644
--- a/src/llvm-project/clang/lib/Lex/Preprocessor.cpp
+++ b/src/llvm-project/clang/lib/Lex/Preprocessor.cpp
@@ -274,7 +274,7 @@
llvm::errs() << " " << NumEnteredSourceFiles << " source files entered.\n";
llvm::errs() << " " << MaxIncludeStackDepth << " max include stack depth\n";
llvm::errs() << " " << NumIf << " #if/#ifndef/#ifdef.\n";
- llvm::errs() << " " << NumElse << " #else/#elif.\n";
+ llvm::errs() << " " << NumElse << " #else/#elif/#elifdef/#elifndef.\n";
llvm::errs() << " " << NumEndif << " #endif.\n";
llvm::errs() << " " << NumPragma << " #pragma.\n";
llvm::errs() << NumSkipped << " #if/#ifndef#ifdef regions skipped\n";
@@ -442,15 +442,15 @@
void Preprocessor::CodeCompleteIncludedFile(llvm::StringRef Dir,
bool IsAngled) {
+ setCodeCompletionReached();
if (CodeComplete)
CodeComplete->CodeCompleteIncludedFile(Dir, IsAngled);
- setCodeCompletionReached();
}
void Preprocessor::CodeCompleteNaturalLanguage() {
+ setCodeCompletionReached();
if (CodeComplete)
CodeComplete->CodeCompleteNaturalLanguage();
- setCodeCompletionReached();
}
/// getSpelling - This method is used to get the spelling of a token into a
diff --git a/src/llvm-project/clang/lib/Lex/TokenLexer.cpp b/src/llvm-project/clang/lib/Lex/TokenLexer.cpp
index da5681a..41e7f3f 100644
--- a/src/llvm-project/clang/lib/Lex/TokenLexer.cpp
+++ b/src/llvm-project/clang/lib/Lex/TokenLexer.cpp
@@ -971,7 +971,7 @@
assert(SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength) &&
"Expected loc to come from the macro definition");
- unsigned relativeOffset = 0;
+ SourceLocation::UIntTy relativeOffset = 0;
SM.isInSLocAddrSpace(loc, MacroDefStart, MacroDefLength, &relativeOffset);
return MacroExpansionStart.getLocWithOffset(relativeOffset);
}
@@ -1010,7 +1010,7 @@
if (CurLoc.isFileID() != NextLoc.isFileID())
break; // Token from different kind of FileID.
- int RelOffs;
+ SourceLocation::IntTy RelOffs;
if (!SM.isInSameSLocAddrSpace(CurLoc, NextLoc, &RelOffs))
break; // Token from different local/loaded location.
// Check that token is not before the previous token or more than 50
@@ -1027,10 +1027,11 @@
// For the consecutive tokens, find the length of the SLocEntry to contain
// all of them.
Token &LastConsecutiveTok = *(NextTok-1);
- int LastRelOffs = 0;
+ SourceLocation::IntTy LastRelOffs = 0;
SM.isInSameSLocAddrSpace(FirstLoc, LastConsecutiveTok.getLocation(),
&LastRelOffs);
- unsigned FullLength = LastRelOffs + LastConsecutiveTok.getLength();
+ SourceLocation::UIntTy FullLength =
+ LastRelOffs + LastConsecutiveTok.getLength();
// Create a macro expansion SLocEntry that will "contain" all of the tokens.
SourceLocation Expansion =
@@ -1040,7 +1041,7 @@
// expanded location.
for (; begin_tokens < NextTok; ++begin_tokens) {
Token &Tok = *begin_tokens;
- int RelOffs = 0;
+ SourceLocation::IntTy RelOffs = 0;
SM.isInSameSLocAddrSpace(FirstLoc, Tok.getLocation(), &RelOffs);
Tok.setLocation(Expansion.getLocWithOffset(RelOffs));
}
diff --git a/src/llvm-project/clang/lib/Parse/ParseCXXInlineMethods.cpp b/src/llvm-project/clang/lib/Parse/ParseCXXInlineMethods.cpp
index b033590..116724a 100644
--- a/src/llvm-project/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -778,6 +778,7 @@
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
assert(Tok.isAnnotation() && "Expected annotation token.");
switch (Tok.getKind()) {
+ case tok::annot_attr_openmp:
case tok::annot_pragma_openmp: {
AccessSpecifier AS = LP.getAccessSpecifier();
ParsedAttributesWithRange Attrs(AttrFactory);
diff --git a/src/llvm-project/clang/lib/Parse/ParseDecl.cpp b/src/llvm-project/clang/lib/Parse/ParseDecl.cpp
index 347d992..9393235 100644
--- a/src/llvm-project/clang/lib/Parse/ParseDecl.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseDecl.cpp
@@ -103,6 +103,24 @@
return AttrStartIsInMacro && AttrEndIsInMacro;
}
+void Parser::ParseAttributes(unsigned WhichAttrKinds,
+ ParsedAttributesWithRange &Attrs,
+ SourceLocation *End,
+ LateParsedAttrList *LateAttrs) {
+ bool MoreToParse;
+ do {
+ // Assume there's nothing left to parse, but if any attributes are in fact
+ // parsed, loop to ensure all specified attribute combinations are parsed.
+ MoreToParse = false;
+ if (WhichAttrKinds & PAKM_CXX11)
+ MoreToParse |= MaybeParseCXX11Attributes(Attrs, End);
+ if (WhichAttrKinds & PAKM_GNU)
+ MoreToParse |= MaybeParseGNUAttributes(Attrs, End, LateAttrs);
+ if (WhichAttrKinds & PAKM_Declspec)
+ MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs, End);
+ } while (MoreToParse);
+}
+
/// ParseGNUAttributes - Parse a non-empty attributes list.
///
/// [GNU] attributes:
@@ -144,15 +162,19 @@
/// ',' or ')' are ignored, otherwise they produce a parse error.
///
/// We follow the C++ model, but don't allow junk after the identifier.
-void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
- SourceLocation *endLoc,
- LateParsedAttrList *LateAttrs,
- Declarator *D) {
+void Parser::ParseGNUAttributes(ParsedAttributesWithRange &Attrs,
+ SourceLocation *EndLoc,
+ LateParsedAttrList *LateAttrs, Declarator *D) {
assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
+ SourceLocation StartLoc = Tok.getLocation(), Loc;
+
+ if (!EndLoc)
+ EndLoc = &Loc;
+
while (Tok.is(tok::kw___attribute)) {
SourceLocation AttrTokLoc = ConsumeToken();
- unsigned OldNumAttrs = attrs.size();
+ unsigned OldNumAttrs = Attrs.size();
unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0;
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
@@ -180,14 +202,14 @@
SourceLocation AttrNameLoc = ConsumeToken();
if (Tok.isNot(tok::l_paren)) {
- attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
ParsedAttr::AS_GNU);
continue;
}
// Handle "parameterized" attributes
if (!LateAttrs || !isAttributeLateParsed(*AttrName)) {
- ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr,
+ ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, nullptr,
SourceLocation(), ParsedAttr::AS_GNU, D);
continue;
}
@@ -220,8 +242,8 @@
SourceLocation Loc = Tok.getLocation();
if (ExpectAndConsume(tok::r_paren))
SkipUntil(tok::r_paren, StopAtSemi);
- if (endLoc)
- *endLoc = Loc;
+ if (EndLoc)
+ *EndLoc = Loc;
// If this was declared in a macro, attach the macro IdentifierInfo to the
// parsed attribute.
@@ -233,8 +255,8 @@
Lexer::getSourceText(ExpansionRange, SM, PP.getLangOpts());
IdentifierInfo *MacroII = PP.getIdentifierInfo(FoundName);
- for (unsigned i = OldNumAttrs; i < attrs.size(); ++i)
- attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin());
+ for (unsigned i = OldNumAttrs; i < Attrs.size(); ++i)
+ Attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin());
if (LateAttrs) {
for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i)
@@ -242,6 +264,8 @@
}
}
}
+
+ Attrs.Range = SourceRange(StartLoc, *EndLoc);
}
/// Determine whether the given attribute has an identifier argument.
@@ -1589,7 +1613,30 @@
}
void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
- unsigned DiagID) {
+ unsigned DiagID, bool DiagnoseEmptyAttrs) {
+
+ if (DiagnoseEmptyAttrs && Attrs.empty() && Attrs.Range.isValid()) {
+ // An attribute list has been parsed, but it was empty.
+ // This is the case for [[]].
+ const auto &LangOpts = getLangOpts();
+ auto &SM = PP.getSourceManager();
+ Token FirstLSquare;
+ Lexer::getRawToken(Attrs.Range.getBegin(), FirstLSquare, SM, LangOpts);
+
+ if (FirstLSquare.is(tok::l_square)) {
+ llvm::Optional<Token> SecondLSquare =
+ Lexer::findNextToken(FirstLSquare.getLocation(), SM, LangOpts);
+
+ if (SecondLSquare && SecondLSquare->is(tok::l_square)) {
+ // The attribute range starts with [[, but is empty. So this must
+ // be [[]], which we are supposed to diagnose because
+ // DiagnoseEmptyAttrs is true.
+ Diag(Attrs.Range.getBegin(), DiagID) << Attrs.Range;
+ return;
+ }
+ }
+ }
+
for (const ParsedAttr &AL : Attrs) {
if (!AL.isCXX11Attribute() && !AL.isC2xAttribute())
continue;
@@ -1603,6 +1650,13 @@
}
}
+void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributesWithRange &Attrs) {
+ for (const ParsedAttr &PA : Attrs) {
+ if (PA.isCXX11Attribute() || PA.isC2xAttribute())
+ Diag(PA.getLoc(), diag::ext_cxx11_attr_placement) << PA << PA.getRange();
+ }
+}
+
// Usually, `__attribute__((attrib)) class Foo {} var` means that attribute
// applies to var, not the type Foo.
// As an exception to the rule, __declspec(align(...)) before the
@@ -1952,8 +2006,8 @@
// Check to see if we have a function *definition* which must have a body.
if (D.isFunctionDeclarator()) {
if (Tok.is(tok::equal) && NextToken().is(tok::code_completion)) {
- Actions.CodeCompleteAfterFunctionEquals(D);
cutOffParsing();
+ Actions.CodeCompleteAfterFunctionEquals(D);
return nullptr;
}
// Look at the next token to make sure that this isn't a function
@@ -2292,9 +2346,9 @@
InitializerScopeRAII InitScope(*this, D, ThisDecl);
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
Actions.FinalizeDeclaration(ThisDecl);
- cutOffParsing();
return nullptr;
}
@@ -3024,6 +3078,19 @@
SourceLocation Loc = Tok.getLocation();
+ // Helper for image types in OpenCL.
+ auto handleOpenCLImageKW = [&] (StringRef Ext, TypeSpecifierType ImageTypeSpec) {
+ // Check if the image type is supported and otherwise turn the keyword into an identifier
+ // because image types from extensions are not reserved identifiers.
+ if (!StringRef(Ext).empty() && !getActions().getOpenCLOptions().isSupported(Ext, getLangOpts())) {
+ Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
+ Tok.setKind(tok::identifier);
+ return false;
+ }
+ isInvalid = DS.SetTypeSpecType(ImageTypeSpec, Loc, PrevSpec, DiagID, Policy);
+ return true;
+ };
+
switch (Tok.getKind()) {
default:
DoneWithDeclSpec:
@@ -3072,10 +3139,11 @@
= DSContext == DeclSpecContext::DSC_top_level ||
(DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified());
+ cutOffParsing();
Actions.CodeCompleteDeclSpec(getCurScope(), DS,
AllowNonIdentifiers,
AllowNestedNameSpecifiers);
- return cutOffParsing();
+ return;
}
if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())
@@ -3088,8 +3156,9 @@
else if (CurParsedObjCImpl)
CCC = Sema::PCC_ObjCImplementation;
+ cutOffParsing();
Actions.CodeCompleteOrdinaryName(getCurScope(), CCC);
- return cutOffParsing();
+ return;
}
case tok::coloncolon: // ::foo::bar
@@ -3485,14 +3554,11 @@
continue;
}
- // GNU attributes support.
+ // Attributes support.
case tok::kw___attribute:
- ParseGNUAttributes(DS.getAttributes(), nullptr, LateAttrs);
- continue;
-
- // Microsoft declspec support.
case tok::kw___declspec:
- ParseMicrosoftDeclSpecs(DS.getAttributes());
+ ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), nullptr,
+ LateAttrs);
continue;
// Microsoft single token adornments.
@@ -3631,8 +3697,8 @@
// C++ for OpenCL does not allow virtual function qualifier, to avoid
// function pointers restricted in OpenCL v2.0 s6.9.a.
if (getLangOpts().OpenCLCPlusPlus &&
- !getActions().getOpenCLOptions().isEnabled(
- "__cl_clang_function_pointers")) {
+ !getActions().getOpenCLOptions().isAvailableOption(
+ "__cl_clang_function_pointers", getLangOpts())) {
DiagID = diag::err_openclcxx_virtual_function;
PrevSpec = Tok.getIdentifierInfo()->getNameStart();
isInvalid = true;
@@ -3881,18 +3947,26 @@
case tok::kw_pipe:
if (!getLangOpts().OpenCL || (getLangOpts().OpenCLVersion < 200 &&
!getLangOpts().OpenCLCPlusPlus)) {
- // OpenCL 2.0 defined this keyword. OpenCL 1.2 and earlier should
- // support the "pipe" word as identifier.
+ // OpenCL 2.0 and later define this keyword. OpenCL 1.2 and earlier
+ // should support the "pipe" word as identifier.
Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
+ Tok.setKind(tok::identifier);
goto DoneWithDeclSpec;
- }
- isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
+ } else if (!getLangOpts().OpenCLPipes) {
+ DiagID = diag::err_opencl_unknown_type_specifier;
+ PrevSpec = Tok.getIdentifierInfo()->getNameStart();
+ isInvalid = true;
+ } else
+ isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
break;
-#define GENERIC_IMAGE_TYPE(ImgType, Id) \
- case tok::kw_##ImgType##_t: \
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_##ImgType##_t, Loc, PrevSpec, \
- DiagID, Policy); \
- break;
+// We only need to enumerate each image type once.
+#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
+#define IMAGE_WRITE_TYPE(Type, Id, Ext)
+#define IMAGE_READ_TYPE(ImgType, Id, Ext) \
+ case tok::kw_##ImgType##_t: \
+ if (!handleOpenCLImageKW(Ext, DeclSpec::TST_##ImgType##_t)) \
+ goto DoneWithDeclSpec; \
+ break;
#include "clang/Basic/OpenCLImageTypes.def"
case tok::kw___unknown_anytype:
isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
@@ -4002,8 +4076,9 @@
case tok::kw___generic:
// generic address space is introduced only in OpenCL v2.0
// see OpenCL C Spec v2.0 s6.5.5
- if (Actions.getLangOpts().OpenCLVersion < 200 &&
- !Actions.getLangOpts().OpenCLCPlusPlus) {
+ // OpenCL v3.0 introduces __opencl_c_generic_address_space
+ // feature macro to indicate if generic address space is supported
+ if (!Actions.getLangOpts().OpenCLGenericAddressSpace) {
DiagID = diag::err_opencl_unknown_type_specifier;
PrevSpec = Tok.getIdentifierInfo()->getNameStart();
isInvalid = true;
@@ -4232,7 +4307,7 @@
continue;
}
- if (Tok.is(tok::annot_pragma_openmp)) {
+ if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
// Result can be ignored, because it must be always empty.
AccessSpecifier AS = AS_none;
ParsedAttributesWithRange Attrs(AttrFactory);
@@ -4348,15 +4423,14 @@
// Parse the tag portion of this.
if (Tok.is(tok::code_completion)) {
// Code completion for an enum name.
+ cutOffParsing();
Actions.CodeCompleteTag(getCurScope(), DeclSpec::TST_enum);
- return cutOffParsing();
+ return;
}
// If attributes exist after tag, parse them.
ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseGNUAttributes(attrs);
- MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftDeclSpecs(attrs);
+ MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
SourceLocation ScopedEnumKWLoc;
bool IsScopedUsingClassTag = false;
@@ -4373,9 +4447,7 @@
ProhibitAttributes(attrs);
// They are allowed afterwards, though.
- MaybeParseGNUAttributes(attrs);
- MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftDeclSpecs(attrs);
+ MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
}
// C++11 [temp.explicit]p12:
@@ -4617,7 +4689,8 @@
// or opaque-enum-declaration anywhere.
if (IsElaboratedTypeSpecifier && !getLangOpts().MicrosoftExt &&
!getLangOpts().ObjC) {
- ProhibitAttributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ /*DiagnoseEmptyAttrs=*/true);
if (BaseType.isUsable())
Diag(BaseRange.getBegin(), diag::ext_enum_base_in_type_specifier)
<< (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes) << BaseRange;
@@ -4761,7 +4834,6 @@
// If attributes exist after the enumerator, parse them.
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseGNUAttributes(attrs);
- ProhibitAttributes(attrs); // GNU-style attributes are prohibited.
if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
if (getLangOpts().CPlusPlus)
Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
@@ -5058,6 +5130,7 @@
switch (Tok.getKind()) {
default: return false;
+ // OpenCL 2.0 and later define this keyword.
case tok::kw_pipe:
return (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200) ||
getLangOpts().OpenCLCPlusPlus;
@@ -5449,11 +5522,12 @@
switch (Tok.getKind()) {
case tok::code_completion:
+ cutOffParsing();
if (CodeCompletionHandler)
(*CodeCompletionHandler)();
else
Actions.CodeCompleteTypeQualifiers(DS);
- return cutOffParsing();
+ return;
case tok::kw_const:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
@@ -5588,6 +5662,7 @@
if (Kind == tok::star || Kind == tok::caret)
return true;
+ // OpenCL 2.0 and later define this keyword.
if (Kind == tok::kw_pipe &&
((Lang.OpenCL && Lang.OpenCLVersion >= 200) || Lang.OpenCLCPlusPlus))
return true;
@@ -6991,8 +7066,9 @@
std::move(attrs), T.getCloseLocation());
return;
} else if (Tok.getKind() == tok::code_completion) {
+ cutOffParsing();
Actions.CodeCompleteBracketDeclarator(getCurScope());
- return cutOffParsing();
+ return;
}
// If valid, this location is the position where we read the 'static' keyword.
@@ -7275,6 +7351,7 @@
case tok::kw_float:
case tok::kw_double:
case tok::kw_bool:
+ case tok::kw__Bool:
case tok::kw___bool:
case tok::kw___pixel:
Tok.setKind(tok::kw___vector);
@@ -7284,7 +7361,8 @@
Tok.setKind(tok::kw___vector);
return true;
}
- if (Next.getIdentifierInfo() == Ident_bool) {
+ if (Next.getIdentifierInfo() == Ident_bool ||
+ Next.getIdentifierInfo() == Ident_Bool) {
Tok.setKind(tok::kw___vector);
return true;
}
@@ -7309,6 +7387,7 @@
case tok::kw_float:
case tok::kw_double:
case tok::kw_bool:
+ case tok::kw__Bool:
case tok::kw___bool:
case tok::kw___pixel:
isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
@@ -7318,8 +7397,10 @@
isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
return true;
}
- if (Next.getIdentifierInfo() == Ident_bool) {
- isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);
+ if (Next.getIdentifierInfo() == Ident_bool ||
+ Next.getIdentifierInfo() == Ident_Bool) {
+ isInvalid =
+ DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);
return true;
}
break;
diff --git a/src/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp b/src/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp
index 88ebb59..ca5c013 100644
--- a/src/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp
@@ -63,8 +63,8 @@
ObjCDeclContextSwitch ObjCDC(*this);
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteNamespaceDecl(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteNamespaceDecl(getCurScope());
return nullptr;
}
@@ -132,7 +132,7 @@
<< FixItHint::CreateRemoval(InlineLoc);
Decl *NSAlias = ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
return Actions.ConvertDeclToDeclGroup(NSAlias);
-}
+ }
BalancedDelimiterTracker T(*this, tok::l_brace);
if (T.consumeOpen()) {
@@ -283,8 +283,8 @@
ConsumeToken(); // eat the '='.
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteNamespaceAliasDecl(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteNamespaceAliasDecl(getCurScope());
return nullptr;
}
@@ -471,8 +471,8 @@
SourceLocation UsingLoc = ConsumeToken();
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteUsing(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteUsing(getCurScope());
return nullptr;
}
@@ -497,11 +497,7 @@
}
// Otherwise, it must be a using-declaration or an alias-declaration.
-
- // Using declarations can't have attributes.
- ProhibitAttributes(attrs);
-
- return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd,
+ return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, attrs,
AS_none);
}
@@ -525,8 +521,8 @@
SourceLocation NamespcLoc = ConsumeToken();
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteUsingDirective(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteUsingDirective(getCurScope());
return nullptr;
}
@@ -627,7 +623,8 @@
if (getLangOpts().CPlusPlus11 && Context == DeclaratorContext::Member &&
Tok.is(tok::identifier) &&
(NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
- NextToken().is(tok::ellipsis)) &&
+ NextToken().is(tok::ellipsis) || NextToken().is(tok::l_square) ||
+ NextToken().is(tok::kw___attribute)) &&
D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
!D.SS.getScopeRep()->getAsNamespace() &&
!D.SS.getScopeRep()->getAsNamespaceAlias()) {
@@ -670,11 +667,48 @@
/// alias-declaration: C++11 [dcl.dcl]p1
/// 'using' identifier attribute-specifier-seq[opt] = type-id ;
///
+/// using-enum-declaration: [C++20, dcl.enum]
+/// 'using' elaborated-enum-specifier ;
+///
+/// elaborated-enum-specifier:
+/// 'enum' nested-name-specifier[opt] identifier
Parser::DeclGroupPtrTy
-Parser::ParseUsingDeclaration(DeclaratorContext Context,
- const ParsedTemplateInfo &TemplateInfo,
- SourceLocation UsingLoc, SourceLocation &DeclEnd,
- AccessSpecifier AS) {
+Parser::ParseUsingDeclaration(
+ DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation UsingLoc, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &PrefixAttrs, AccessSpecifier AS) {
+ SourceLocation UELoc;
+ if (TryConsumeToken(tok::kw_enum, UELoc)) {
+ // C++20 using-enum
+ Diag(UELoc, getLangOpts().CPlusPlus20
+ ? diag::warn_cxx17_compat_using_enum_declaration
+ : diag::ext_using_enum_declaration);
+
+ DiagnoseCXX11AttributeExtension(PrefixAttrs);
+
+ DeclSpec DS(AttrFactory);
+ ParseEnumSpecifier(UELoc, DS, TemplateInfo, AS,
+ // DSC_trailing has the semantics we desire
+ DeclSpecContext::DSC_trailing);
+
+ if (TemplateInfo.Kind) {
+ SourceRange R = TemplateInfo.getSourceRange();
+ Diag(UsingLoc, diag::err_templated_using_directive_declaration)
+ << 1 /* declaration */ << R << FixItHint::CreateRemoval(R);
+
+ return nullptr;
+ }
+
+ Decl *UED = Actions.ActOnUsingEnumDeclaration(getCurScope(), AS, UsingLoc,
+ UELoc, DS);
+ DeclEnd = Tok.getLocation();
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ "using-enum declaration"))
+ SkipUntil(tok::semi);
+
+ return Actions.ConvertDeclToDeclGroup(UED);
+ }
+
// Check for misplaced attributes before the identifier in an
// alias-declaration.
ParsedAttributesWithRange MisplacedAttrs(AttrFactory);
@@ -684,8 +718,18 @@
bool InvalidDeclarator = ParseUsingDeclarator(Context, D);
ParsedAttributesWithRange Attrs(AttrFactory);
- MaybeParseGNUAttributes(Attrs);
- MaybeParseCXX11Attributes(Attrs);
+ MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);
+
+ // If we had any misplaced attributes from earlier, this is where they
+ // should have been written.
+ if (MisplacedAttrs.Range.isValid()) {
+ Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed)
+ << FixItHint::CreateInsertionFromRange(
+ Tok.getLocation(),
+ CharSourceRange::getTokenRange(MisplacedAttrs.Range))
+ << FixItHint::CreateRemoval(MisplacedAttrs.Range);
+ Attrs.takeAllFrom(MisplacedAttrs);
+ }
// Maybe this is an alias-declaration.
if (Tok.is(tok::equal)) {
@@ -694,16 +738,7 @@
return nullptr;
}
- // If we had any misplaced attributes from earlier, this is where they
- // should have been written.
- if (MisplacedAttrs.Range.isValid()) {
- Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed)
- << FixItHint::CreateInsertionFromRange(
- Tok.getLocation(),
- CharSourceRange::getTokenRange(MisplacedAttrs.Range))
- << FixItHint::CreateRemoval(MisplacedAttrs.Range);
- Attrs.takeAllFrom(MisplacedAttrs);
- }
+ ProhibitAttributes(PrefixAttrs);
Decl *DeclFromDeclSpec = nullptr;
Decl *AD = ParseAliasDeclarationAfterDeclarator(
@@ -711,10 +746,7 @@
return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec);
}
- // C++11 attributes are not allowed on a using-declaration, but GNU ones
- // are.
- ProhibitAttributes(MisplacedAttrs);
- ProhibitAttributes(Attrs);
+ DiagnoseCXX11AttributeExtension(PrefixAttrs);
// Diagnose an attempt to declare a templated using-declaration.
// In C++11, alias-declarations can be templates:
@@ -732,8 +764,10 @@
SmallVector<Decl *, 8> DeclsInGroup;
while (true) {
- // Parse (optional) attributes (most likely GNU strong-using extension).
- MaybeParseGNUAttributes(Attrs);
+ // Parse (optional) attributes.
+ MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);
+ DiagnoseCXX11AttributeExtension(Attrs);
+ Attrs.addAll(PrefixAttrs.begin(), PrefixAttrs.end());
if (InvalidDeclarator)
SkipUntil(tok::comma, tok::semi, StopBeforeMatch);
@@ -772,8 +806,9 @@
// Eat ';'.
DeclEnd = Tok.getLocation();
if (ExpectAndConsume(tok::semi, diag::err_expected_after,
- !Attrs.empty() ? "attributes list"
- : "using declaration"))
+ !Attrs.empty() ? "attributes list"
+ : UELoc.isValid() ? "using-enum declaration"
+ : "using declaration"))
SkipUntil(tok::semi);
return Actions.BuildDeclaratorGroup(DeclsInGroup);
@@ -857,6 +892,16 @@
DeclFromDeclSpec);
}
+static FixItHint getStaticAssertNoMessageFixIt(const Expr *AssertExpr,
+ SourceLocation EndExprLoc) {
+ if (const auto *BO = dyn_cast_or_null<BinaryOperator>(AssertExpr)) {
+ if (BO->getOpcode() == BO_LAnd &&
+ isa<StringLiteral>(BO->getRHS()->IgnoreImpCasts()))
+ return FixItHint::CreateReplacement(BO->getOperatorLoc(), ",");
+ }
+ return FixItHint::CreateInsertion(EndExprLoc, ", \"\"");
+}
+
/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
///
/// [C++0x] static_assert-declaration:
@@ -871,8 +916,13 @@
if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();
- if (Tok.is(tok::kw_static_assert))
- Diag(Tok, diag::warn_cxx98_compat_static_assert);
+ if (Tok.is(tok::kw_static_assert)) {
+ if (!getLangOpts().CPlusPlus)
+ Diag(Tok, diag::ext_ms_static_assert)
+ << FixItHint::CreateReplacement(Tok.getLocation(), "_Static_assert");
+ else
+ Diag(Tok, diag::warn_cxx98_compat_static_assert);
+ }
SourceLocation StaticAssertLoc = ConsumeToken();
@@ -893,12 +943,17 @@
ExprResult AssertMessage;
if (Tok.is(tok::r_paren)) {
- Diag(Tok, getLangOpts().CPlusPlus17
- ? diag::warn_cxx14_compat_static_assert_no_message
- : diag::ext_static_assert_no_message)
- << (getLangOpts().CPlusPlus17
- ? FixItHint()
- : FixItHint::CreateInsertion(Tok.getLocation(), ", \"\""));
+ unsigned DiagVal;
+ if (getLangOpts().CPlusPlus17)
+ DiagVal = diag::warn_cxx14_compat_static_assert_no_message;
+ else if (getLangOpts().CPlusPlus)
+ DiagVal = diag::ext_cxx_static_assert_no_message;
+ else if (getLangOpts().C2x)
+ DiagVal = diag::warn_c17_compat_static_assert_no_message;
+ else
+ DiagVal = diag::ext_c_static_assert_no_message;
+ Diag(Tok, DiagVal) << getStaticAssertNoMessageFixIt(AssertExpr.get(),
+ Tok.getLocation());
} else {
if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::semi);
@@ -1414,8 +1469,9 @@
if (Tok.is(tok::code_completion)) {
// Code completion for a struct, class, or union name.
+ cutOffParsing();
Actions.CodeCompleteTag(getCurScope(), TagType);
- return cutOffParsing();
+ return;
}
// C++03 [temp.explicit] 14.7.2/8:
@@ -1435,8 +1491,7 @@
ParsedAttributesWithRange attrs(AttrFactory);
// If attributes exist after tag, parse them.
- MaybeParseGNUAttributes(attrs);
- MaybeParseMicrosoftDeclSpecs(attrs);
+ MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
// Parse inheritance specifiers.
if (Tok.isOneOf(tok::kw___single_inheritance,
@@ -1444,10 +1499,8 @@
tok::kw___virtual_inheritance))
ParseMicrosoftInheritanceClassAttributes(attrs);
- // If C++0x attributes exist here, parse them.
- // FIXME: Are we consistent with the ordering of parsing of different
- // styles of attributes?
- MaybeParseCXX11Attributes(attrs);
+ // Allow attributes to precede or succeed the inheritance specifiers.
+ MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
// Source location used by FIXIT to insert misplaced
// C++11 attributes
@@ -1693,7 +1746,7 @@
TUK = Sema::TUK_Reference;
else if (Tok.is(tok::l_brace) ||
(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
- (isCXX11FinalKeyword() &&
+ (isClassCompatibleKeyword() &&
(NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) {
if (DS.isFriendSpecified()) {
// C++ [class.friend]p2:
@@ -1709,14 +1762,18 @@
// Okay, this is a class definition.
TUK = Sema::TUK_Definition;
}
- } else if (isCXX11FinalKeyword() && (NextToken().is(tok::l_square) ||
- NextToken().is(tok::kw_alignas))) {
+ } else if (isClassCompatibleKeyword() &&
+ (NextToken().is(tok::l_square) ||
+ NextToken().is(tok::kw_alignas) ||
+ isCXX11VirtSpecifier(NextToken()) != VirtSpecifiers::VS_None)) {
// We can't tell if this is a definition or reference
// until we skipped the 'final' and C++11 attribute specifiers.
TentativeParsingAction PA(*this);
- // Skip the 'final' keyword.
- ConsumeToken();
+ // Skip the 'final', abstract'... keywords.
+ while (isClassCompatibleKeyword()) {
+ ConsumeToken();
+ }
// Skip C++11 attribute specifiers.
while (true) {
@@ -1819,7 +1876,8 @@
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
TUK == Sema::TUK_Declaration) {
// This is an explicit instantiation of a class template.
- ProhibitAttributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ /*DiagnoseEmptyAttrs=*/true);
TagOrTempResult = Actions.ActOnExplicitInstantiation(
getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc,
@@ -1834,7 +1892,8 @@
} else if (TUK == Sema::TUK_Reference ||
(TUK == Sema::TUK_Friend &&
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
- ProhibitAttributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ /*DiagnoseEmptyAttrs=*/true);
TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc,
SS,
TemplateId->TemplateKWLoc,
@@ -1906,7 +1965,8 @@
TagType, StartLoc, SS, Name, NameLoc, attrs);
} else if (TUK == Sema::TUK_Friend &&
TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
- ProhibitAttributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ /*DiagnoseEmptyAttrs=*/true);
TagOrTempResult = Actions.ActOnTemplatedFriendTag(
getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name,
@@ -1915,7 +1975,8 @@
TemplateParams ? TemplateParams->size() : 0));
} else {
if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
- ProhibitAttributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,
+ /* DiagnoseEmptyAttrs=*/true);
if (TUK == Sema::TUK_Definition &&
TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
@@ -1961,7 +2022,7 @@
if (TUK == Sema::TUK_Definition) {
assert(Tok.is(tok::l_brace) ||
(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
- isCXX11FinalKeyword());
+ isClassCompatibleKeyword());
if (SkipBody.ShouldSkip)
SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType,
TagOrTempResult.get());
@@ -2228,8 +2289,10 @@
Ident_final = &PP.getIdentifierTable().get("final");
if (getLangOpts().GNUKeywords)
Ident_GNU_final = &PP.getIdentifierTable().get("__final");
- if (getLangOpts().MicrosoftExt)
+ if (getLangOpts().MicrosoftExt) {
Ident_sealed = &PP.getIdentifierTable().get("sealed");
+ Ident_abstract = &PP.getIdentifierTable().get("abstract");
+ }
Ident_override = &PP.getIdentifierTable().get("override");
}
@@ -2239,6 +2302,9 @@
if (II == Ident_sealed)
return VirtSpecifiers::VS_Sealed;
+ if (II == Ident_abstract)
+ return VirtSpecifiers::VS_Abstract;
+
if (II == Ident_final)
return VirtSpecifiers::VS_Final;
@@ -2284,6 +2350,8 @@
<< VirtSpecifiers::getSpecifierName(Specifier);
} else if (Specifier == VirtSpecifiers::VS_Sealed) {
Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword);
+ } else if (Specifier == VirtSpecifiers::VS_Abstract) {
+ Diag(Tok.getLocation(), diag::ext_ms_abstract_keyword);
} else if (Specifier == VirtSpecifiers::VS_GNU_Final) {
Diag(Tok.getLocation(), diag::ext_warn_gnu_final);
} else {
@@ -2306,6 +2374,16 @@
Specifier == VirtSpecifiers::VS_Sealed;
}
+/// isClassCompatibleKeyword - Determine whether the next token is a C++11
+/// 'final' or Microsoft 'sealed' or 'abstract' contextual keywords.
+bool Parser::isClassCompatibleKeyword() const {
+ VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
+ return Specifier == VirtSpecifiers::VS_Final ||
+ Specifier == VirtSpecifiers::VS_GNU_Final ||
+ Specifier == VirtSpecifiers::VS_Sealed ||
+ Specifier == VirtSpecifiers::VS_Abstract;
+}
+
/// Parse a C++ member-declarator up to, but not including, the optional
/// brace-or-equal-initializer or pure-specifier.
bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
@@ -2589,6 +2667,13 @@
ParsedAttributesViewWithRange FnAttrs;
// Optional C++11 attribute-specifier
MaybeParseCXX11Attributes(attrs);
+
+ // The next token may be an OpenMP pragma annotation token. That would
+ // normally be handled from ParseCXXClassMemberDeclarationWithPragmas, but in
+ // this case, it came from an *attribute* rather than a pragma. Handle it now.
+ if (Tok.is(tok::annot_attr_openmp))
+ return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, attrs);
+
// We need to keep these attributes for future diagnostic
// before they are taken over by declaration specifier.
FnAttrs.addAll(attrs.begin(), attrs.end());
@@ -2597,8 +2682,6 @@
MaybeParseMicrosoftAttributes(attrs);
if (Tok.is(tok::kw_using)) {
- ProhibitAttributes(attrs);
-
// Eat 'using'.
SourceLocation UsingLoc = ConsumeToken();
@@ -2617,7 +2700,7 @@
SourceLocation DeclEnd;
// Otherwise, it must be a using-declaration or an alias-declaration.
return ParseUsingDeclaration(DeclaratorContext::Member, TemplateInfo,
- UsingLoc, DeclEnd, AS);
+ UsingLoc, DeclEnd, attrs, AS);
}
// Hold late-parsed attributes so we can attach a Decl to them later.
@@ -2733,8 +2816,8 @@
else if (KW.is(tok::kw_delete))
DefinitionKind = FunctionDefinitionKind::Deleted;
else if (KW.is(tok::code_completion)) {
- Actions.CodeCompleteAfterFunctionEquals(DeclaratorInfo);
cutOffParsing();
+ Actions.CodeCompleteAfterFunctionEquals(DeclaratorInfo);
return nullptr;
}
}
@@ -2872,8 +2955,13 @@
HasStaticInitializer = true;
}
+ if (PureSpecLoc.isValid() && VS.getAbstractLoc().isValid()) {
+ Diag(PureSpecLoc, diag::err_duplicate_virt_specifier) << "abstract";
+ }
if (ThisDecl && PureSpecLoc.isValid())
Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc);
+ else if (ThisDecl && VS.getAbstractLoc().isValid())
+ Actions.ActOnPureSpecifier(ThisDecl, VS.getAbstractLoc());
// Handle the initializer.
if (HasInClassInit != ICIS_NoInit) {
@@ -3180,6 +3268,7 @@
return nullptr;
}
+ case tok::annot_attr_openmp:
case tok::annot_pragma_openmp:
return ParseOpenMPDeclarativeDirectiveWithExtDecl(
AS, AccessAttrs, /*Delayed=*/true, TagType, TagDecl);
@@ -3258,30 +3347,53 @@
Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
SourceLocation FinalLoc;
+ SourceLocation AbstractLoc;
bool IsFinalSpelledSealed = false;
+ bool IsAbstract = false;
// Parse the optional 'final' keyword.
if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
- VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
- assert((Specifier == VirtSpecifiers::VS_Final ||
- Specifier == VirtSpecifiers::VS_GNU_Final ||
- Specifier == VirtSpecifiers::VS_Sealed) &&
+ while (true) {
+ VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
+ if (Specifier == VirtSpecifiers::VS_None)
+ break;
+ if (isCXX11FinalKeyword()) {
+ if (FinalLoc.isValid()) {
+ auto Skipped = ConsumeToken();
+ Diag(Skipped, diag::err_duplicate_class_virt_specifier)
+ << VirtSpecifiers::getSpecifierName(Specifier);
+ } else {
+ FinalLoc = ConsumeToken();
+ if (Specifier == VirtSpecifiers::VS_Sealed)
+ IsFinalSpelledSealed = true;
+ }
+ } else {
+ if (AbstractLoc.isValid()) {
+ auto Skipped = ConsumeToken();
+ Diag(Skipped, diag::err_duplicate_class_virt_specifier)
+ << VirtSpecifiers::getSpecifierName(Specifier);
+ } else {
+ AbstractLoc = ConsumeToken();
+ IsAbstract = true;
+ }
+ }
+ if (TagType == DeclSpec::TST_interface)
+ Diag(FinalLoc, diag::err_override_control_interface)
+ << VirtSpecifiers::getSpecifierName(Specifier);
+ else if (Specifier == VirtSpecifiers::VS_Final)
+ Diag(FinalLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_override_control_keyword
+ : diag::ext_override_control_keyword)
+ << VirtSpecifiers::getSpecifierName(Specifier);
+ else if (Specifier == VirtSpecifiers::VS_Sealed)
+ Diag(FinalLoc, diag::ext_ms_sealed_keyword);
+ else if (Specifier == VirtSpecifiers::VS_Abstract)
+ Diag(AbstractLoc, diag::ext_ms_abstract_keyword);
+ else if (Specifier == VirtSpecifiers::VS_GNU_Final)
+ Diag(FinalLoc, diag::ext_warn_gnu_final);
+ }
+ assert((FinalLoc.isValid() || AbstractLoc.isValid()) &&
"not a class definition");
- FinalLoc = ConsumeToken();
- IsFinalSpelledSealed = Specifier == VirtSpecifiers::VS_Sealed;
-
- if (TagType == DeclSpec::TST_interface)
- Diag(FinalLoc, diag::err_override_control_interface)
- << VirtSpecifiers::getSpecifierName(Specifier);
- else if (Specifier == VirtSpecifiers::VS_Final)
- Diag(FinalLoc, getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_override_control_keyword
- : diag::ext_override_control_keyword)
- << VirtSpecifiers::getSpecifierName(Specifier);
- else if (Specifier == VirtSpecifiers::VS_Sealed)
- Diag(FinalLoc, diag::ext_ms_sealed_keyword);
- else if (Specifier == VirtSpecifiers::VS_GNU_Final)
- Diag(FinalLoc, diag::ext_warn_gnu_final);
// Parse any C++11 attributes after 'final' keyword.
// These attributes are not allowed to appear here,
@@ -3354,7 +3466,7 @@
if (TagDecl)
Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc,
- IsFinalSpelledSealed,
+ IsFinalSpelledSealed, IsAbstract,
T.getOpenLocation());
// C++ 11p3: Members of a class defined with the keyword class are private
@@ -3401,15 +3513,6 @@
// declarations and the lexed inline method definitions, along with any
// delayed attributes.
- // Save the state of Sema.FPFeatures, and change the setting
- // to the levels specified on the command line. Previous level
- // will be restored when the RAII object is destroyed.
- Sema::FPFeaturesStateRAII SaveFPFeaturesState(Actions);
- FPOptionsOverride NewOverrides;
- Actions.CurFPFeatures = NewOverrides.applyOverrides(getLangOpts());
- Actions.FpPragmaStack.Act(Tok.getLocation(), Sema::PSK_Reset, StringRef(),
- {} /*unused*/);
-
SourceLocation SavedPrevTokLocation = PrevTokLocation;
ParseLexedPragmas(getCurrentClass());
ParseLexedAttributes(getCurrentClass());
@@ -3491,9 +3594,10 @@
do {
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
MemInitializers);
- return cutOffParsing();
+ return;
}
MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
@@ -4039,6 +4143,70 @@
}
}
+void Parser::ParseOpenMPAttributeArgs(IdentifierInfo *AttrName,
+ CachedTokens &OpenMPTokens) {
+ // Both 'sequence' and 'directive' attributes require arguments, so parse the
+ // open paren for the argument list.
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.consumeOpen()) {
+ Diag(Tok, diag::err_expected) << tok::l_paren;
+ return;
+ }
+
+ if (AttrName->isStr("directive")) {
+ // If the attribute is named `directive`, we can consume its argument list
+ // and push the tokens from it into the cached token stream for a new OpenMP
+ // pragma directive.
+ Token OMPBeginTok;
+ OMPBeginTok.startToken();
+ OMPBeginTok.setKind(tok::annot_attr_openmp);
+ OMPBeginTok.setLocation(Tok.getLocation());
+ OpenMPTokens.push_back(OMPBeginTok);
+
+ ConsumeAndStoreUntil(tok::r_paren, OpenMPTokens, /*StopAtSemi=*/false,
+ /*ConsumeFinalToken*/ false);
+ Token OMPEndTok;
+ OMPEndTok.startToken();
+ OMPEndTok.setKind(tok::annot_pragma_openmp_end);
+ OMPEndTok.setLocation(Tok.getLocation());
+ OpenMPTokens.push_back(OMPEndTok);
+ } else {
+ assert(AttrName->isStr("sequence") &&
+ "Expected either 'directive' or 'sequence'");
+ // If the attribute is named 'sequence', its argument is a list of one or
+ // more OpenMP attributes (either 'omp::directive' or 'omp::sequence',
+ // where the 'omp::' is optional).
+ do {
+ // We expect to see one of the following:
+ // * An identifier (omp) for the attribute namespace followed by ::
+ // * An identifier (directive) or an identifier (sequence).
+ SourceLocation IdentLoc;
+ IdentifierInfo *Ident = TryParseCXX11AttributeIdentifier(IdentLoc);
+
+ // If there is an identifier and it is 'omp', a double colon is required
+ // followed by the actual identifier we're after.
+ if (Ident && Ident->isStr("omp") && !ExpectAndConsume(tok::coloncolon))
+ Ident = TryParseCXX11AttributeIdentifier(IdentLoc);
+
+ // If we failed to find an identifier (scoped or otherwise), or we found
+ // an unexpected identifier, diagnose.
+ if (!Ident || (!Ident->isStr("directive") && !Ident->isStr("sequence"))) {
+ Diag(Tok.getLocation(), diag::err_expected_sequence_or_directive);
+ SkipUntil(tok::r_paren, StopBeforeMatch);
+ continue;
+ }
+ // We read an identifier. If the identifier is one of the ones we
+ // expected, we can recurse to parse the args.
+ ParseOpenMPAttributeArgs(Ident, OpenMPTokens);
+
+ // There may be a comma to signal that we expect another directive in the
+ // sequence.
+ } while (TryConsumeToken(tok::comma));
+ }
+ // Parse the closing paren for the argument list.
+ T.consumeClose();
+}
+
static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
IdentifierInfo *ScopeName) {
switch (
@@ -4079,7 +4247,8 @@
ParsedAttributes &Attrs,
SourceLocation *EndLoc,
IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc) {
+ SourceLocation ScopeLoc,
+ CachedTokens &OpenMPTokens) {
assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
SourceLocation LParenLoc = Tok.getLocation();
const LangOptions &LO = getLangOpts();
@@ -4104,6 +4273,18 @@
return true;
}
+ if (ScopeName && ScopeName->isStr("omp")) {
+ Diag(AttrNameLoc, getLangOpts().OpenMP >= 51
+ ? diag::warn_omp51_compat_attributes
+ : diag::ext_omp_attributes);
+
+ ParseOpenMPAttributeArgs(AttrName, OpenMPTokens);
+
+ // We claim that an attribute was parsed and added so that one is not
+ // created for us by the caller.
+ return true;
+ }
+
unsigned NumArgs;
// Some Clang-scoped attributes have some special parsing behavior.
if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")))
@@ -4163,11 +4344,12 @@
///
/// [C++11] attribute-namespace:
/// identifier
-void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
- SourceLocation *endLoc) {
+void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
+ CachedTokens &OpenMPTokens,
+ SourceLocation *EndLoc) {
if (Tok.is(tok::kw_alignas)) {
Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas);
- ParseAlignmentSpecifier(attrs, endLoc);
+ ParseAlignmentSpecifier(Attrs, EndLoc);
return;
}
@@ -4200,10 +4382,21 @@
llvm::SmallDenseMap<IdentifierInfo*, SourceLocation, 4> SeenAttrs;
- while (Tok.isNot(tok::r_square)) {
- // attribute not present
- if (TryConsumeToken(tok::comma))
- continue;
+ bool AttrParsed = false;
+ while (!Tok.isOneOf(tok::r_square, tok::semi)) {
+ if (AttrParsed) {
+ // If we parsed an attribute, a comma is required before parsing any
+ // additional attributes.
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
+ continue;
+ }
+ AttrParsed = false;
+ }
+
+ // Eat all remaining superfluous commas before parsing the next attribute.
+ while (TryConsumeToken(tok::comma))
+ ;
SourceLocation ScopeLoc, AttrLoc;
IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;
@@ -4236,38 +4429,39 @@
}
}
- bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName);
- bool AttrParsed = false;
-
- if (StandardAttr &&
- !SeenAttrs.insert(std::make_pair(AttrName, AttrLoc)).second)
- Diag(AttrLoc, diag::err_cxx11_attribute_repeated)
- << AttrName << SourceRange(SeenAttrs[AttrName]);
-
// Parse attribute arguments
if (Tok.is(tok::l_paren))
- AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc,
- ScopeName, ScopeLoc);
+ AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, OpenMPTokens);
- if (!AttrParsed)
- attrs.addNew(
+ if (!AttrParsed) {
+ Attrs.addNew(
AttrName,
SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc),
ScopeName, ScopeLoc, nullptr, 0,
getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x);
+ AttrParsed = true;
+ }
if (TryConsumeToken(tok::ellipsis))
Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
<< AttrName;
}
+ // If we hit an error and recovered by parsing up to a semicolon, eat the
+ // semicolon and don't issue further diagnostics about missing brackets.
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ return;
+ }
+
SourceLocation CloseLoc = Tok.getLocation();
if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
else if (Tok.is(tok::r_square))
checkCompoundToken(CloseLoc, tok::r_square, CompoundToken::AttrEnd);
- if (endLoc)
- *endLoc = Tok.getLocation();
+ if (EndLoc)
+ *EndLoc = Tok.getLocation();
if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
}
diff --git a/src/llvm-project/clang/lib/Parse/ParseExpr.cpp b/src/llvm-project/clang/lib/Parse/ParseExpr.cpp
index 6acf76d..22f3b76 100644
--- a/src/llvm-project/clang/lib/Parse/ParseExpr.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseExpr.cpp
@@ -159,9 +159,9 @@
/// Parse an expr that doesn't include (top-level) commas.
ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteExpression(getCurScope(),
PreferredType.get(Tok.getLocation()));
- cutOffParsing();
return ExprError();
}
@@ -1156,9 +1156,9 @@
ConsumeToken();
if (Tok.is(tok::code_completion) && &II != Ident_super) {
+ cutOffParsing();
Actions.CodeCompleteObjCClassPropertyRefExpr(
getCurScope(), II, ILoc, ExprStatementTokLoc == ILoc);
- cutOffParsing();
return ExprError();
}
// Allow either an identifier or the keyword 'class' (in C++).
@@ -1469,6 +1469,9 @@
case tok::kw_this:
Res = ParseCXXThis();
break;
+ case tok::kw___builtin_sycl_unique_stable_name:
+ Res = ParseSYCLUniqueStableNameExpression();
+ break;
case tok::annot_typename:
if (isStartOfObjCClassMessageMissingOpenBracket()) {
@@ -1724,9 +1727,9 @@
Res = ParseBlockLiteralExpression();
break;
case tok::code_completion: {
+ cutOffParsing();
Actions.CodeCompleteExpression(getCurScope(),
PreferredType.get(Tok.getLocation()));
- cutOffParsing();
return ExprError();
}
case tok::l_square:
@@ -1807,7 +1810,9 @@
// These can be followed by postfix-expr pieces.
PreferredType = SavedType;
Res = ParsePostfixExpressionSuffix(Res);
- if (getLangOpts().OpenCL)
+ if (getLangOpts().OpenCL &&
+ !getActions().getOpenCLOptions().isAvailableOption(
+ "__cl_clang_function_pointers", getLangOpts()))
if (Expr *PostfixExpr = Res.get()) {
QualType Ty = PostfixExpr->getType();
if (!Ty.isNull() && Ty->isFunctionType()) {
@@ -1854,9 +1859,9 @@
if (InMessageExpression)
return LHS;
+ cutOffParsing();
Actions.CodeCompletePostfixExpression(
getCurScope(), LHS, PreferredType.get(Tok.getLocation()));
- cutOffParsing();
return ExprError();
case tok::identifier:
@@ -2138,12 +2143,12 @@
CorrectedBase = Base;
// Code completion for a member access expression.
+ cutOffParsing();
Actions.CodeCompleteMemberReferenceExpr(
getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow,
Base && ExprStatementTokLoc == Base->getBeginLoc(),
PreferredType.get(Tok.getLocation()));
- cutOffParsing();
return ExprError();
}
@@ -2322,6 +2327,33 @@
return Operand;
}
+/// Parse a __builtin_sycl_unique_stable_name expression. Accepts a type-id as
+/// a parameter.
+ExprResult Parser::ParseSYCLUniqueStableNameExpression() {
+ assert(Tok.is(tok::kw___builtin_sycl_unique_stable_name) &&
+ "Not __bulitin_sycl_unique_stable_name");
+
+ SourceLocation OpLoc = ConsumeToken();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+
+ // __builtin_sycl_unique_stable_name expressions are always parenthesized.
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ "__builtin_sycl_unique_stable_name"))
+ return ExprError();
+
+ TypeResult Ty = ParseTypeName();
+
+ if (Ty.isInvalid()) {
+ T.skipToEnd();
+ return ExprError();
+ }
+
+ if (T.consumeClose())
+ return ExprError();
+
+ return Actions.ActOnSYCLUniqueStableNameExpr(OpLoc, T.getOpenLocation(),
+ T.getCloseLocation(), Ty.get());
+}
/// Parse a sizeof or alignof expression.
///
@@ -2776,10 +2808,10 @@
CastTy = nullptr;
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteExpression(
getCurScope(), PreferredType.get(Tok.getLocation()),
/*IsParenthesized=*/ExprType >= CompoundLiteral);
- cutOffParsing();
return ExprError();
}
@@ -3410,8 +3442,9 @@
/// \endverbatim
void Parser::ParseBlockId(SourceLocation CaretLoc) {
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
- return cutOffParsing();
+ return;
}
// Parse the specifier-qualifier-list piece.
@@ -3596,8 +3629,8 @@
} else {
// Parse the platform name.
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteAvailabilityPlatformName();
cutOffParsing();
+ Actions.CodeCompleteAvailabilityPlatformName();
return None;
}
if (Tok.isNot(tok::identifier)) {
diff --git a/src/llvm-project/clang/lib/Parse/ParseExprCXX.cpp b/src/llvm-project/clang/lib/Parse/ParseExprCXX.cpp
index 4b5703d..f3d10b4 100644
--- a/src/llvm-project/clang/lib/Parse/ParseExprCXX.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseExprCXX.cpp
@@ -9,7 +9,6 @@
// This file implements the Expression parsing implementation for C++.
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
@@ -17,6 +16,7 @@
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -235,6 +235,7 @@
while (true) {
if (HasScopeSpecifier) {
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
// Code completion for a nested-name-specifier, where the code
// completion token follows the '::'.
Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext,
@@ -245,7 +246,6 @@
// token will cause assertion in
// Preprocessor::AnnotatePreviousCachedTokens.
SS.setEndLoc(Tok.getLocation());
- cutOffParsing();
return true;
}
@@ -688,9 +688,9 @@
/// ParseLambdaExpression - Parse a C++11 lambda expression.
///
/// lambda-expression:
-/// lambda-introducer lambda-declarator[opt] compound-statement
+/// lambda-introducer lambda-declarator compound-statement
/// lambda-introducer '<' template-parameter-list '>'
-/// lambda-declarator[opt] compound-statement
+/// requires-clause[opt] lambda-declarator compound-statement
///
/// lambda-introducer:
/// '[' lambda-capture[opt] ']'
@@ -722,9 +722,13 @@
/// '&' identifier initializer
///
/// lambda-declarator:
-/// '(' parameter-declaration-clause ')' attribute-specifier[opt]
-/// 'mutable'[opt] exception-specification[opt]
-/// trailing-return-type[opt]
+/// lambda-specifiers [C++2b]
+/// '(' parameter-declaration-clause ')' lambda-specifiers
+/// requires-clause[opt]
+///
+/// lambda-specifiers:
+/// decl-specifier-seq[opt] noexcept-specifier[opt]
+/// attribute-specifier-seq[opt] trailing-return-type[opt]
///
ExprResult Parser::ParseLambdaExpression() {
// Parse lambda-introducer.
@@ -877,9 +881,9 @@
// expression parser perform the completion.
if (Tok.is(tok::code_completion) &&
!(getLangOpts().ObjC && Tentative)) {
+ cutOffParsing();
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
- cutOffParsing();
break;
}
@@ -891,6 +895,7 @@
}
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
// If we're in Objective-C++ and we have a bare '[', then this is more
// likely to be a message receiver.
if (getLangOpts().ObjC && Tentative && First)
@@ -898,7 +903,6 @@
else
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/false);
- cutOffParsing();
break;
}
@@ -943,9 +947,9 @@
ConsumeToken();
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteLambdaIntroducer(getCurScope(), Intro,
/*AfterAmpersand=*/true);
- cutOffParsing();
break;
}
}
@@ -1249,7 +1253,6 @@
Actions.PushLambdaScope();
ParsedAttributes Attr(AttrFactory);
- SourceLocation DeclLoc = Tok.getLocation();
if (getLangOpts().CUDA) {
// In CUDA code, GNU attributes are allowed to appear immediately after the
// "[...]", even if there is no "(...)" before the lambda body.
@@ -1302,13 +1305,99 @@
}
}
+ // Implement WG21 P2173, which allows attributes immediately before the
+ // lambda declarator and applies them to the corresponding function operator
+ // or operator template declaration. We accept this as a conforming extension
+ // in all language modes that support lambdas.
+ if (isCXX11AttributeSpecifier()) {
+ Diag(Tok, getLangOpts().CPlusPlus2b
+ ? diag::warn_cxx20_compat_decl_attrs_on_lambda
+ : diag::ext_decl_attrs_on_lambda);
+ MaybeParseCXX11Attributes(D);
+ }
+
TypeResult TrailingReturnType;
SourceLocation TrailingReturnTypeLoc;
+
+ auto ParseLambdaSpecifiers =
+ [&](SourceLocation LParenLoc, SourceLocation RParenLoc,
+ MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo,
+ SourceLocation EllipsisLoc) {
+ SourceLocation DeclEndLoc = RParenLoc;
+
+ // GNU-style attributes must be parsed before the mutable specifier to
+ // be compatible with GCC. MSVC-style attributes must be parsed before
+ // the mutable specifier to be compatible with MSVC.
+ MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attr);
+
+ // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update
+ // the DeclEndLoc.
+ SourceLocation MutableLoc;
+ SourceLocation ConstexprLoc;
+ SourceLocation ConstevalLoc;
+ tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc,
+ ConstevalLoc, DeclEndLoc);
+
+ addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
+ addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
+ // Parse exception-specification[opt].
+ ExceptionSpecificationType ESpecType = EST_None;
+ SourceRange ESpecRange;
+ SmallVector<ParsedType, 2> DynamicExceptions;
+ SmallVector<SourceRange, 2> DynamicExceptionRanges;
+ ExprResult NoexceptExpr;
+ CachedTokens *ExceptionSpecTokens;
+ ESpecType = tryParseExceptionSpecification(
+ /*Delayed=*/false, ESpecRange, DynamicExceptions,
+ DynamicExceptionRanges, NoexceptExpr, ExceptionSpecTokens);
+
+ if (ESpecType != EST_None)
+ DeclEndLoc = ESpecRange.getEnd();
+
+ // Parse attribute-specifier[opt].
+ MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
+
+ // Parse OpenCL addr space attribute.
+ if (Tok.isOneOf(tok::kw___private, tok::kw___global, tok::kw___local,
+ tok::kw___constant, tok::kw___generic)) {
+ ParseOpenCLQualifiers(DS.getAttributes());
+ ConsumeToken();
+ }
+
+ SourceLocation FunLocalRangeEnd = DeclEndLoc;
+
+ // Parse trailing-return-type[opt].
+ if (Tok.is(tok::arrow)) {
+ FunLocalRangeEnd = Tok.getLocation();
+ SourceRange Range;
+ TrailingReturnType = ParseTrailingReturnType(
+ Range, /*MayBeFollowedByDirectInit*/ false);
+ TrailingReturnTypeLoc = Range.getBegin();
+ if (Range.getEnd().isValid())
+ DeclEndLoc = Range.getEnd();
+ }
+
+ SourceLocation NoLoc;
+ D.AddTypeInfo(
+ DeclaratorChunk::getFunction(
+ /*HasProto=*/true,
+ /*IsAmbiguous=*/false, LParenLoc, ParamInfo.data(),
+ ParamInfo.size(), EllipsisLoc, RParenLoc,
+ /*RefQualifierIsLvalueRef=*/true,
+ /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType, ESpecRange,
+ DynamicExceptions.data(), DynamicExceptionRanges.data(),
+ DynamicExceptions.size(),
+ NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
+ /*ExceptionSpecTokens*/ nullptr,
+ /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D,
+ TrailingReturnType, TrailingReturnTypeLoc, &DS),
+ std::move(Attr), DeclEndLoc);
+ };
+
if (Tok.is(tok::l_paren)) {
- ParseScope PrototypeScope(this,
- Scope::FunctionPrototypeScope |
- Scope::FunctionDeclarationScope |
- Scope::DeclScope);
+ ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
+ Scope::FunctionDeclarationScope |
+ Scope::DeclScope);
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
@@ -1334,170 +1423,36 @@
}
T.consumeClose();
- SourceLocation RParenLoc = T.getCloseLocation();
- SourceLocation DeclEndLoc = RParenLoc;
- // GNU-style attributes must be parsed before the mutable specifier to be
- // compatible with GCC.
- MaybeParseGNUAttributes(Attr, &DeclEndLoc);
-
- // MSVC-style attributes must be parsed before the mutable specifier to be
- // compatible with MSVC.
- MaybeParseMicrosoftDeclSpecs(Attr, &DeclEndLoc);
-
- // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update the
- // DeclEndLoc.
- SourceLocation MutableLoc;
- SourceLocation ConstexprLoc;
- SourceLocation ConstevalLoc;
- tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc,
- ConstevalLoc, DeclEndLoc);
-
- addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
- addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
- // Parse exception-specification[opt].
- ExceptionSpecificationType ESpecType = EST_None;
- SourceRange ESpecRange;
- SmallVector<ParsedType, 2> DynamicExceptions;
- SmallVector<SourceRange, 2> DynamicExceptionRanges;
- ExprResult NoexceptExpr;
- CachedTokens *ExceptionSpecTokens;
- ESpecType = tryParseExceptionSpecification(/*Delayed=*/false,
- ESpecRange,
- DynamicExceptions,
- DynamicExceptionRanges,
- NoexceptExpr,
- ExceptionSpecTokens);
-
- if (ESpecType != EST_None)
- DeclEndLoc = ESpecRange.getEnd();
-
- // Parse attribute-specifier[opt].
- MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
-
- // Parse OpenCL addr space attribute.
- if (Tok.isOneOf(tok::kw___private, tok::kw___global, tok::kw___local,
- tok::kw___constant, tok::kw___generic)) {
- ParseOpenCLQualifiers(DS.getAttributes());
- ConsumeToken();
- }
-
- SourceLocation FunLocalRangeEnd = DeclEndLoc;
-
- // Parse trailing-return-type[opt].
- if (Tok.is(tok::arrow)) {
- FunLocalRangeEnd = Tok.getLocation();
- SourceRange Range;
- TrailingReturnType =
- ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false);
- TrailingReturnTypeLoc = Range.getBegin();
- if (Range.getEnd().isValid())
- DeclEndLoc = Range.getEnd();
- }
-
- SourceLocation NoLoc;
- D.AddTypeInfo(DeclaratorChunk::getFunction(
- /*HasProto=*/true,
- /*IsAmbiguous=*/false, LParenLoc, ParamInfo.data(),
- ParamInfo.size(), EllipsisLoc, RParenLoc,
- /*RefQualifierIsLvalueRef=*/true,
- /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType,
- ESpecRange, DynamicExceptions.data(),
- DynamicExceptionRanges.data(), DynamicExceptions.size(),
- NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
- /*ExceptionSpecTokens*/ nullptr,
- /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D,
- TrailingReturnType, TrailingReturnTypeLoc, &DS),
- std::move(Attr), DeclEndLoc);
+ // Parse lambda-specifiers.
+ ParseLambdaSpecifiers(LParenLoc, /*DeclEndLoc=*/T.getCloseLocation(),
+ ParamInfo, EllipsisLoc);
// Parse requires-clause[opt].
if (Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
-
- PrototypeScope.Exit();
-
- WarnIfHasCUDATargetAttr();
} else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute,
tok::kw_constexpr, tok::kw_consteval,
tok::kw___private, tok::kw___global, tok::kw___local,
tok::kw___constant, tok::kw___generic,
- tok::kw_requires) ||
+ tok::kw_requires, tok::kw_noexcept) ||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
- // It's common to forget that one needs '()' before 'mutable', an attribute
- // specifier, the result type, or the requires clause. Deal with this.
- unsigned TokKind = 0;
- switch (Tok.getKind()) {
- case tok::kw_mutable: TokKind = 0; break;
- case tok::arrow: TokKind = 1; break;
- case tok::kw___attribute:
- case tok::kw___private:
- case tok::kw___global:
- case tok::kw___local:
- case tok::kw___constant:
- case tok::kw___generic:
- case tok::l_square: TokKind = 2; break;
- case tok::kw_constexpr: TokKind = 3; break;
- case tok::kw_consteval: TokKind = 4; break;
- case tok::kw_requires: TokKind = 5; break;
- default: llvm_unreachable("Unknown token kind");
- }
-
- Diag(Tok, diag::err_lambda_missing_parens)
- << TokKind
- << FixItHint::CreateInsertion(Tok.getLocation(), "() ");
- SourceLocation DeclEndLoc = DeclLoc;
-
- // GNU-style attributes must be parsed before the mutable specifier to be
- // compatible with GCC.
- MaybeParseGNUAttributes(Attr, &DeclEndLoc);
-
- // Parse 'mutable', if it's there.
- SourceLocation MutableLoc;
- if (Tok.is(tok::kw_mutable)) {
- MutableLoc = ConsumeToken();
- DeclEndLoc = MutableLoc;
- }
-
- // Parse attribute-specifier[opt].
- MaybeParseCXX11Attributes(Attr, &DeclEndLoc);
-
- // Parse the return type, if there is one.
- if (Tok.is(tok::arrow)) {
- SourceRange Range;
- TrailingReturnType =
- ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false);
- if (Range.getEnd().isValid())
- DeclEndLoc = Range.getEnd();
- }
+ if (!getLangOpts().CPlusPlus2b)
+ // It's common to forget that one needs '()' before 'mutable', an
+ // attribute specifier, the result type, or the requires clause. Deal with
+ // this.
+ Diag(Tok, diag::ext_lambda_missing_parens)
+ << FixItHint::CreateInsertion(Tok.getLocation(), "() ");
SourceLocation NoLoc;
- D.AddTypeInfo(DeclaratorChunk::getFunction(
- /*HasProto=*/true,
- /*IsAmbiguous=*/false,
- /*LParenLoc=*/NoLoc,
- /*Params=*/nullptr,
- /*NumParams=*/0,
- /*EllipsisLoc=*/NoLoc,
- /*RParenLoc=*/NoLoc,
- /*RefQualifierIsLvalueRef=*/true,
- /*RefQualifierLoc=*/NoLoc, MutableLoc, EST_None,
- /*ESpecRange=*/SourceRange(),
- /*Exceptions=*/nullptr,
- /*ExceptionRanges=*/nullptr,
- /*NumExceptions=*/0,
- /*NoexceptExpr=*/nullptr,
- /*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None, DeclLoc, DeclEndLoc, D,
- TrailingReturnType),
- std::move(Attr), DeclEndLoc);
-
- // Parse the requires-clause, if present.
- if (Tok.is(tok::kw_requires))
- ParseTrailingRequiresClause(D);
-
- WarnIfHasCUDATargetAttr();
+ // Parse lambda-specifiers.
+ std::vector<DeclaratorChunk::ParamInfo> EmptyParamInfo;
+ ParseLambdaSpecifiers(/*LParenLoc=*/NoLoc, /*RParenLoc=*/NoLoc,
+ EmptyParamInfo, /*EllipsisLoc=*/NoLoc);
}
+ WarnIfHasCUDATargetAttr();
+
// FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
// it.
unsigned ScopeFlags = Scope::BlockScope | Scope::FnScope | Scope::DeclScope |
@@ -1979,17 +1934,36 @@
/// \param FRI If non-null, a for range declaration is permitted, and if
/// present will be parsed and stored here, and a null result will be returned.
///
+/// \param EnterForConditionScope If true, enter a continue/break scope at the
+/// appropriate moment for a 'for' loop.
+///
/// \returns The parsed condition.
Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
SourceLocation Loc,
Sema::ConditionKind CK,
- ForRangeInfo *FRI) {
+ ForRangeInfo *FRI,
+ bool EnterForConditionScope) {
+ // Helper to ensure we always enter a continue/break scope if requested.
+ struct ForConditionScopeRAII {
+ Scope *S;
+ void enter(bool IsConditionVariable) {
+ if (S) {
+ S->AddFlags(Scope::BreakScope | Scope::ContinueScope);
+ S->setIsConditionVarScope(IsConditionVariable);
+ }
+ }
+ ~ForConditionScopeRAII() {
+ if (S)
+ S->setIsConditionVarScope(false);
+ }
+ } ForConditionScope{EnterForConditionScope ? getCurScope() : nullptr};
+
ParenBraceBracketBalancer BalancerRAIIObj(*this);
PreferredType.enterCondition(Actions, Tok.getLocation());
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition);
cutOffParsing();
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition);
return Sema::ConditionError();
}
@@ -2006,6 +1980,9 @@
// Determine what kind of thing we have.
switch (isCXXConditionDeclarationOrInitStatement(InitStmt, FRI)) {
case ConditionOrInitStatement::Expression: {
+ // If this is a for loop, we're entering its condition.
+ ForConditionScope.enter(/*IsConditionVariable=*/false);
+
ProhibitAttributes(attrs);
// We can have an empty expression here.
@@ -2048,11 +2025,16 @@
}
case ConditionOrInitStatement::ForRangeDecl: {
+ // This is 'for (init-stmt; for-range-decl : range-expr)'.
+ // We're not actually in a for loop yet, so 'break' and 'continue' aren't
+ // permitted here.
assert(FRI && "should not parse a for range declaration here");
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy DG = ParseSimpleDeclaration(DeclaratorContext::ForInit,
DeclEnd, attrs, false, FRI);
FRI->LoopVar = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
+ assert((FRI->ColonLoc.isValid() || !DG) &&
+ "cannot find for range declaration");
return Sema::ConditionResult();
}
@@ -2061,6 +2043,9 @@
break;
}
+ // If this is a for loop, we're entering its condition.
+ ForConditionScope.enter(/*IsConditionVariable=*/true);
+
// type-specifier-seq
DeclSpec DS(AttrFactory);
DS.takeAttributesFrom(attrs);
@@ -2600,10 +2585,10 @@
}
case tok::code_completion: {
+ // Don't try to parse any further.
+ cutOffParsing();
// Code completion for the operator name.
Actions.CodeCompleteOperatorName(getCurScope());
- cutOffParsing();
- // Don't try to parse any further.
return true;
}
@@ -2651,9 +2636,10 @@
// Grab the literal operator's suffix, which will be either the next token
// or a ud-suffix from the string literal.
+ bool IsUDSuffix = !Literal.getUDSuffix().empty();
IdentifierInfo *II = nullptr;
SourceLocation SuffixLoc;
- if (!Literal.getUDSuffix().empty()) {
+ if (IsUDSuffix) {
II = &PP.getIdentifierTable().get(Literal.getUDSuffix());
SuffixLoc =
Lexer::AdvanceToTokenCharacter(TokLocs[Literal.getUDSuffixToken()],
@@ -2690,7 +2676,7 @@
Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc);
- return Actions.checkLiteralOperatorId(SS, Result);
+ return Actions.checkLiteralOperatorId(SS, Result, IsUDSuffix);
}
// Parse a conversion-function-id.
diff --git a/src/llvm-project/clang/lib/Parse/ParseInit.cpp b/src/llvm-project/clang/lib/Parse/ParseInit.cpp
index 9ac2b2e..9d9c03d 100644
--- a/src/llvm-project/clang/lib/Parse/ParseInit.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseInit.cpp
@@ -159,8 +159,7 @@
///
/// \p CodeCompleteCB is called with Designation parsed so far.
ExprResult Parser::ParseInitializerWithPotentialDesignator(
- llvm::function_ref<void(const Designation &)> CodeCompleteCB) {
-
+ DesignatorCompletionInfo DesignatorCompletion) {
// If this is the old-style GNU extension:
// designation ::= identifier ':'
// Handle it as a field designator. Otherwise, this must be the start of a
@@ -183,6 +182,8 @@
Designation D;
D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
+ PreferredType.enterDesignatedInitializer(
+ Tok.getLocation(), DesignatorCompletion.PreferredBaseType, D);
return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,
ParseInitializer());
}
@@ -199,8 +200,9 @@
SourceLocation DotLoc = ConsumeToken();
if (Tok.is(tok::code_completion)) {
- CodeCompleteCB(Desig);
cutOffParsing();
+ Actions.CodeCompleteDesignator(DesignatorCompletion.PreferredBaseType,
+ DesignatorCompletion.InitExprs, Desig);
return ExprError();
}
if (Tok.isNot(tok::identifier)) {
@@ -388,6 +390,8 @@
// Handle a normal designator sequence end, which is an equal.
if (Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken();
+ PreferredType.enterDesignatedInitializer(
+ Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);
return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false,
ParseInitializer());
}
@@ -396,6 +400,8 @@
// direct-list-initialization of the aggregate element. We allow this as an
// extension from C++11 onwards (when direct-list-initialization was added).
if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus11) {
+ PreferredType.enterDesignatedInitializer(
+ Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);
return Actions.ActOnDesignatedInitializer(Desig, SourceLocation(), false,
ParseBraceInitializer());
}
@@ -453,9 +459,9 @@
Actions, EnterExpressionEvaluationContext::InitList);
bool InitExprsOk = true;
- auto CodeCompleteDesignation = [&](const Designation &D) {
- Actions.CodeCompleteDesignator(PreferredType.get(T.getOpenLocation()),
- InitExprs, D);
+ DesignatorCompletionInfo DesignatorCompletion{
+ InitExprs,
+ PreferredType.get(T.getOpenLocation()),
};
while (1) {
@@ -476,7 +482,7 @@
// initializer directly.
ExprResult SubElt;
if (MayBeDesignationStart())
- SubElt = ParseInitializerWithPotentialDesignator(CodeCompleteDesignation);
+ SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);
else
SubElt = ParseInitializer();
@@ -556,9 +562,9 @@
return false;
}
- auto CodeCompleteDesignation = [&](const Designation &D) {
- Actions.CodeCompleteDesignator(PreferredType.get(Braces.getOpenLocation()),
- InitExprs, D);
+ DesignatorCompletionInfo DesignatorCompletion{
+ InitExprs,
+ PreferredType.get(Braces.getOpenLocation()),
};
while (!isEofOrEom()) {
trailingComma = false;
@@ -566,7 +572,7 @@
// initializer directly.
ExprResult SubElt;
if (MayBeDesignationStart())
- SubElt = ParseInitializerWithPotentialDesignator(CodeCompleteDesignation);
+ SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);
else
SubElt = ParseInitializer();
diff --git a/src/llvm-project/clang/lib/Parse/ParseObjc.cpp b/src/llvm-project/clang/lib/Parse/ParseObjc.cpp
index 88942ed..9e145f5 100644
--- a/src/llvm-project/clang/lib/Parse/ParseObjc.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseObjc.cpp
@@ -50,8 +50,8 @@
SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCAtDirective(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCAtDirective(getCurScope());
return nullptr;
}
@@ -219,8 +219,8 @@
// Code completion after '@interface'.
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
return nullptr;
}
@@ -253,8 +253,8 @@
SourceLocation categoryLoc;
IdentifierInfo *categoryId = nullptr;
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
cutOffParsing();
+ Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
return nullptr;
}
@@ -308,8 +308,8 @@
// Code completion of superclass names.
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
cutOffParsing();
+ Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
return nullptr;
}
@@ -472,8 +472,8 @@
if (Tok.is(tok::code_completion)) {
// FIXME: If these aren't protocol references, we'll need different
// completions.
- Actions.CodeCompleteObjCProtocolReferences(protocolIdents);
cutOffParsing();
+ Actions.CodeCompleteObjCProtocolReferences(protocolIdents);
// FIXME: Better recovery here?.
return nullptr;
@@ -635,10 +635,11 @@
// Code completion within an Objective-C interface.
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteOrdinaryName(getCurScope(),
CurParsedObjCImpl? Sema::PCC_ObjCImplementation
: Sema::PCC_ObjCInterface);
- return cutOffParsing();
+ return;
}
// If we don't have an @ directive, parse it as a function definition.
@@ -668,8 +669,9 @@
// Otherwise, we have an @ directive, eat the @.
SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteObjCAtDirective(getCurScope());
- return cutOffParsing();
+ return;
}
tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
@@ -778,8 +780,9 @@
// We break out of the big loop in two cases: when we see @end or when we see
// EOF. In the former case, eat the @end. In the later case, emit an error.
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteObjCAtDirective(getCurScope());
- return cutOffParsing();
+ return;
} else if (Tok.isObjCAtKeyword(tok::objc_end)) {
ConsumeToken(); // the "end" identifier
} else {
@@ -847,8 +850,9 @@
while (1) {
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS);
- return cutOffParsing();
+ return;
}
const IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -893,11 +897,12 @@
}
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
if (IsSetter)
Actions.CodeCompleteObjCPropertySetter(getCurScope());
else
Actions.CodeCompleteObjCPropertyGetter(getCurScope());
- return cutOffParsing();
+ return;
}
SourceLocation SelLoc;
@@ -1146,9 +1151,10 @@
while (1) {
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteObjCPassingType(
getCurScope(), DS, Context == DeclaratorContext::ObjCParameter);
- return cutOffParsing();
+ return;
}
if (Tok.isNot(tok::identifier))
@@ -1335,9 +1341,9 @@
ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
/*ReturnType=*/nullptr);
- cutOffParsing();
return nullptr;
}
@@ -1350,14 +1356,13 @@
// If attributes exist before the method, parse them.
ParsedAttributes methodAttrs(AttrFactory);
- if (getLangOpts().ObjC)
- MaybeParseGNUAttributes(methodAttrs);
- MaybeParseCXX11Attributes(methodAttrs);
+ MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
+ methodAttrs);
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
ReturnType);
- cutOffParsing();
return nullptr;
}
@@ -1377,9 +1382,8 @@
SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
if (Tok.isNot(tok::colon)) {
// If attributes exist after the method, parse them.
- if (getLangOpts().ObjC)
- MaybeParseGNUAttributes(methodAttrs);
- MaybeParseCXX11Attributes(methodAttrs);
+ MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
+ methodAttrs);
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
Decl *Result = Actions.ActOnMethodDeclaration(
@@ -1412,19 +1416,18 @@
// If attributes exist before the argument name, parse them.
// Regardless, collect all the attributes we've parsed so far.
- if (getLangOpts().ObjC)
- MaybeParseGNUAttributes(paramAttrs);
- MaybeParseCXX11Attributes(paramAttrs);
+ MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
+ paramAttrs);
ArgInfo.ArgAttrs = paramAttrs;
// Code completion for the next piece of the selector.
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
KeyIdents.push_back(SelIdent);
Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
mType == tok::minus,
/*AtParameterName=*/true,
ReturnType, KeyIdents);
- cutOffParsing();
return nullptr;
}
@@ -1444,11 +1447,11 @@
// Code completion for the next piece of the selector.
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
mType == tok::minus,
/*AtParameterName=*/false,
ReturnType, KeyIdents);
- cutOffParsing();
return nullptr;
}
@@ -1496,9 +1499,8 @@
// FIXME: Add support for optional parameter list...
// If attributes exist after the method, parse them.
- if (getLangOpts().ObjC)
- MaybeParseGNUAttributes(methodAttrs);
- MaybeParseCXX11Attributes(methodAttrs);
+ MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
+ methodAttrs);
if (KeyIdents.size() == 0)
return nullptr;
@@ -1531,8 +1533,8 @@
while (1) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents);
cutOffParsing();
+ Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents);
return true;
}
@@ -1630,12 +1632,12 @@
}
QualType BaseT = Actions.GetTypeFromParser(baseType);
+ cutOffParsing();
if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) {
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
} else {
Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs);
}
- cutOffParsing();
return;
}
@@ -1924,8 +1926,9 @@
// Set the default visibility to private.
if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteObjCAtVisibility(getCurScope());
- return cutOffParsing();
+ return;
}
switch (Tok.getObjCKeywordID()) {
@@ -1954,9 +1957,10 @@
}
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteOrdinaryName(getCurScope(),
Sema::PCC_ObjCInstanceVariableList);
- return cutOffParsing();
+ return;
}
// This needs to duplicate a small amount of code from
@@ -2021,8 +2025,8 @@
ConsumeToken(); // the "protocol" identifier
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCProtocolDecl(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCProtocolDecl(getCurScope());
return nullptr;
}
@@ -2105,8 +2109,8 @@
// Code completion after '@implementation'.
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCImplementationDecl(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCImplementationDecl(getCurScope());
return nullptr;
}
@@ -2143,8 +2147,8 @@
IdentifierInfo *categoryId = nullptr;
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
cutOffParsing();
+ Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
return nullptr;
}
@@ -2313,8 +2317,8 @@
while (true) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
return nullptr;
}
@@ -2331,8 +2335,8 @@
if (TryConsumeToken(tok::equal)) {
// property '=' ivar-name
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
cutOffParsing();
+ Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
return nullptr;
}
@@ -2391,8 +2395,8 @@
while (true) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCPropertyDefinition(getCurScope());
return nullptr;
}
@@ -2728,8 +2732,8 @@
StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc,
ParsedStmtContext StmtCtx) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCAtStatement(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCAtStatement(getCurScope());
return StmtError();
}
@@ -2769,8 +2773,8 @@
ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
switch (Tok.getKind()) {
case tok::code_completion:
- Actions.CodeCompleteObjCAtExpression(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCAtExpression(getCurScope());
return ExprError();
case tok::minus:
@@ -3016,8 +3020,8 @@
SourceLocation LBracLoc = ConsumeBracket(); // consume '['
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCMessageReceiver(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteObjCMessageReceiver(getCurScope());
return ExprError();
}
@@ -3153,6 +3157,7 @@
InMessageExpressionRAIIObject InMessage(*this, true);
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
if (SuperLoc.isValid())
Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None,
false);
@@ -3162,7 +3167,6 @@
else
Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
None, false);
- cutOffParsing();
return ExprError();
}
@@ -3191,6 +3195,7 @@
/// Parse the expression after ':'
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
if (SuperLoc.isValid())
Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
KeyIdents,
@@ -3204,7 +3209,6 @@
KeyIdents,
/*AtArgumentExpression=*/true);
- cutOffParsing();
return ExprError();
}
@@ -3229,6 +3233,7 @@
// Code completion after each argument.
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
if (SuperLoc.isValid())
Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
KeyIdents,
@@ -3241,7 +3246,6 @@
Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
KeyIdents,
/*AtArgumentExpression=*/false);
- cutOffParsing();
return ExprError();
}
@@ -3581,8 +3585,8 @@
ConsumeParen();
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
cutOffParsing();
+ Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
return ExprError();
}
@@ -3607,8 +3611,8 @@
break;
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
cutOffParsing();
+ Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
return ExprError();
}
diff --git a/src/llvm-project/clang/lib/Parse/ParseOpenMP.cpp b/src/llvm-project/clang/lib/Parse/ParseOpenMP.cpp
index db7e967..18e43c3 100644
--- a/src/llvm-project/clang/lib/Parse/ParseOpenMP.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseOpenMP.cpp
@@ -131,6 +131,7 @@
{OMPD_declare, OMPD_simd, OMPD_declare_simd},
{OMPD_declare, OMPD_target, OMPD_declare_target},
{OMPD_declare, OMPD_variant, OMPD_declare_variant},
+ {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
{OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
{OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
{OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
@@ -441,9 +442,9 @@
ConsumeToken();
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
Actions.FinalizeDeclaration(OmpPrivParm);
- cutOffParsing();
return;
}
@@ -1664,30 +1665,41 @@
return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
}
-Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
- // OpenMP 4.5 syntax with list of entities.
- Sema::NamedDeclSetType SameDirectiveDecls;
- SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation,
- NamedDecl *>,
- 4>
- DeclareTargetDecls;
- OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
+void Parser::ParseOMPDeclareTargetClauses(
+ Sema::DeclareTargetContextInfo &DTCI) {
SourceLocation DeviceTypeLoc;
+ bool RequiresToOrLinkClause = false;
+ bool HasToOrLinkClause = false;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
- if (Tok.is(tok::identifier)) {
+ bool HasIdentifier = Tok.is(tok::identifier);
+ if (HasIdentifier) {
+ // If we see any clause we need a to or link clause.
+ RequiresToOrLinkClause = true;
IdentifierInfo *II = Tok.getIdentifierInfo();
StringRef ClauseName = II->getName();
bool IsDeviceTypeClause =
getLangOpts().OpenMP >= 50 &&
getOpenMPClauseKind(ClauseName) == OMPC_device_type;
- // Parse 'to|link|device_type' clauses.
- if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
- !IsDeviceTypeClause) {
+
+ bool IsToOrLinkClause =
+ OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
+ assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!");
+
+ if (!IsDeviceTypeClause && DTCI.Kind == OMPD_begin_declare_target) {
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
- << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
+ << ClauseName << 0;
break;
}
+ if (!IsDeviceTypeClause && !IsToOrLinkClause) {
+ Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
+ << ClauseName << (getLangOpts().OpenMP >= 50 ? 2 : 1);
+ break;
+ }
+
+ if (IsToOrLinkClause)
+ HasToOrLinkClause = true;
+
// Parse 'device_type' clause and go to next clause if any.
if (IsDeviceTypeClause) {
Optional<SimpleClauseData> DevTypeData =
@@ -1697,16 +1709,17 @@
// We already saw another device_type clause, diagnose it.
Diag(DevTypeData.getValue().Loc,
diag::warn_omp_more_one_device_type_clause);
+ break;
}
switch (static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
case OMPC_DEVICE_TYPE_any:
- DT = OMPDeclareTargetDeclAttr::DT_Any;
+ DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
break;
case OMPC_DEVICE_TYPE_host:
- DT = OMPDeclareTargetDeclAttr::DT_Host;
+ DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
break;
case OMPC_DEVICE_TYPE_nohost:
- DT = OMPDeclareTargetDeclAttr::DT_NoHost;
+ DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
break;
case OMPC_DEVICE_TYPE_unknown:
llvm_unreachable("Unexpected device_type");
@@ -1717,37 +1730,47 @@
}
ConsumeToken();
}
- auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
- CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
- NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
- getCurScope(), SS, NameInfo, SameDirectiveDecls);
- if (ND)
- DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
- };
- if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
- /*AllowScopeSpecifier=*/true))
+
+ if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
+ auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
+ DeclarationNameInfo NameInfo) {
+ NamedDecl *ND =
+ Actions.lookupOpenMPDeclareTargetName(getCurScope(), SS, NameInfo);
+ if (!ND)
+ return;
+ Sema::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
+ bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
+ if (!FirstMapping)
+ Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
+ << NameInfo.getName();
+ };
+ if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
+ /*AllowScopeSpecifier=*/true))
+ break;
+ }
+
+ if (Tok.is(tok::l_paren)) {
+ Diag(Tok,
+ diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
break;
+ }
+ if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
+ Diag(Tok,
+ diag::err_omp_declare_target_unexpected_clause_after_implicit_to);
+ break;
+ }
// Consume optional ','.
if (Tok.is(tok::comma))
ConsumeToken();
}
+
+ // For declare target require at least 'to' or 'link' to be present.
+ if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkClause &&
+ !HasToOrLinkClause)
+ Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause);
+
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
- ConsumeAnyToken();
- for (auto &MTLocDecl : DeclareTargetDecls) {
- OMPDeclareTargetDeclAttr::MapTypeTy MT;
- SourceLocation Loc;
- NamedDecl *ND;
- std::tie(MT, Loc, ND) = MTLocDecl;
- // device_type clause is applied only to functions.
- Actions.ActOnOpenMPDeclareTargetName(
- ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
- }
- SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
- SameDirectiveDecls.end());
- if (Decls.empty())
- return DeclGroupPtrTy();
- return Actions.BuildDeclaratorGroup(Decls);
}
void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
@@ -1784,10 +1807,11 @@
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
-void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
+void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
+ OpenMPDirectiveKind EndDKind,
SourceLocation DKLoc) {
- parseOMPEndDirective(OMPD_declare_target, OMPD_end_declare_target, DKind,
- DKLoc, Tok.getLocation(),
+ parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
+ Tok.getLocation(),
/* SkipUntilOpenMPEnd */ false);
// Skip the last annot_pragma_openmp_end.
if (Tok.is(tok::annot_pragma_openmp_end))
@@ -1833,7 +1857,8 @@
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
DeclSpec::TST TagType, Decl *Tag) {
- assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
+ assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
+ "Not an OpenMP directive!");
ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -1851,7 +1876,7 @@
Toks.push_back(Tok);
while (Cnt && Tok.isNot(tok::eof)) {
(void)ConsumeAnyToken();
- if (Tok.is(tok::annot_pragma_openmp))
+ if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
++Cnt;
else if (Tok.is(tok::annot_pragma_openmp_end))
--Cnt;
@@ -2074,7 +2099,7 @@
ConsumeAnyToken();
DeclGroupPtrTy Ptr;
- if (Tok.is(tok::annot_pragma_openmp)) {
+ if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
TagType, Tag);
} else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
@@ -2101,58 +2126,48 @@
ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
return Ptr;
}
+ case OMPD_begin_declare_target:
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- return ParseOMPDeclareTargetClauses();
- }
+ bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
+ bool HasImplicitMappings =
+ DKind == OMPD_begin_declare_target || !HasClauses;
+ Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc);
+ if (HasClauses)
+ ParseOMPDeclareTargetClauses(DTCI);
// Skip the last annot_pragma_openmp_end.
ConsumeAnyToken();
- if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
- return DeclGroupPtrTy();
-
- ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
- llvm::SmallVector<Decl *, 4> Decls;
- DKind = parseOpenMPDirectiveKind(*this);
- while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
- Tok.isNot(tok::r_brace)) {
- DeclGroupPtrTy Ptr;
- // Here we expect to see some function declaration.
- if (AS == AS_none) {
- assert(TagType == DeclSpec::TST_unspecified);
- MaybeParseCXX11Attributes(Attrs);
- ParsingDeclSpec PDS(*this);
- Ptr = ParseExternalDeclaration(Attrs, &PDS);
- } else {
- Ptr =
- ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
- }
- if (Ptr) {
- DeclGroupRef Ref = Ptr.get();
- Decls.append(Ref.begin(), Ref.end());
- }
- if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
- TentativeParsingAction TPA(*this);
- ConsumeAnnotationToken();
- DKind = parseOpenMPDirectiveKind(*this);
- if (DKind != OMPD_end_declare_target)
- TPA.Revert();
- else
- TPA.Commit();
- }
+ if (HasImplicitMappings) {
+ Actions.ActOnStartOpenMPDeclareTargetContext(DTCI);
+ return nullptr;
}
- ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
- Actions.ActOnFinishOpenMPDeclareTargetDirective();
+ Actions.ActOnFinishedOpenMPDeclareTargetContext(DTCI);
+ llvm::SmallVector<Decl *, 4> Decls;
+ for (auto &It : DTCI.ExplicitlyMapped)
+ Decls.push_back(It.first);
return Actions.BuildDeclaratorGroup(Decls);
}
+ case OMPD_end_declare_target: {
+ if (!Actions.isInOpenMPDeclareTargetContext()) {
+ Diag(Tok, diag::err_omp_unexpected_directive)
+ << 1 << getOpenMPDirectiveName(DKind);
+ break;
+ }
+ const Sema::DeclareTargetContextInfo &DTCI =
+ Actions.ActOnOpenMPEndDeclareTargetDirective();
+ ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
+ return nullptr;
+ }
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
break;
case OMPD_parallel:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_task:
case OMPD_taskyield:
case OMPD_barrier:
@@ -2190,7 +2205,6 @@
case OMPD_parallel_master_taskloop:
case OMPD_parallel_master_taskloop_simd:
case OMPD_distribute:
- case OMPD_end_declare_target:
case OMPD_target_update:
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
@@ -2206,6 +2220,8 @@
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
case OMPD_target_teams_distribute_simd:
+ case OMPD_dispatch:
+ case OMPD_masked:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);
break;
@@ -2255,12 +2271,13 @@
/// simd' | 'teams distribute parallel for simd' | 'teams distribute
/// parallel for' | 'target teams' | 'target teams distribute' | 'target
/// teams distribute parallel for' | 'target teams distribute parallel
-/// for simd' | 'target teams distribute simd' {clause}
+/// for simd' | 'target teams distribute simd' | 'masked' {clause}
/// annot_pragma_openmp_end
///
StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
- assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
+ assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
+ "Not an OpenMP directive!");
ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<OMPClause *, 5> Clauses;
@@ -2377,6 +2394,7 @@
case OMPD_target_enter_data:
case OMPD_target_exit_data:
case OMPD_target_update:
+ case OMPD_interop:
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
ParsedStmtContext()) {
Diag(Tok, diag::err_omp_immediate_directive)
@@ -2387,6 +2405,8 @@
LLVM_FALLTHROUGH;
case OMPD_parallel:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
@@ -2427,7 +2447,9 @@
case OMPD_target_teams_distribute:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
- case OMPD_target_teams_distribute_simd: {
+ case OMPD_target_teams_distribute_simd:
+ case OMPD_dispatch:
+ case OMPD_masked: {
// Special processing for flush and depobj clauses.
Token ImplicitTok;
bool ImplicitClauseAllowed = false;
@@ -2521,6 +2543,11 @@
HasAssociatedStatement = false;
}
+ if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) {
+ Diag(Loc, diag::err_omp_required_clause)
+ << getOpenMPDirectiveName(OMPD_tile) << "sizes";
+ }
+
StmtResult AssociatedStmt;
if (HasAssociatedStatement) {
// The body is a block scope like in Lambdas and Blocks.
@@ -2529,7 +2556,15 @@
// the captured region. Code elsewhere assumes that any FunctionScopeInfo
// should have at least one compound statement scope within it.
ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
- AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
+ {
+ Sema::CompoundScopeRAII Scope(Actions);
+ AssociatedStmt = ParseStatement();
+
+ if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
+ getLangOpts().OpenMPIRBuilder)
+ AssociatedStmt =
+ Actions.ActOnOpenMPCanonicalLoop(AssociatedStmt.get());
+ }
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
} else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
DKind == OMPD_target_exit_data) {
@@ -2550,6 +2585,7 @@
}
case OMPD_declare_simd:
case OMPD_declare_target:
+ case OMPD_begin_declare_target:
case OMPD_end_declare_target:
case OMPD_requires:
case OMPD_begin_declare_variant:
@@ -2633,6 +2669,37 @@
return !IsCorrect;
}
+OMPClause *Parser::ParseOpenMPSizesClause() {
+ SourceLocation ClauseNameLoc = ConsumeToken();
+ SmallVector<Expr *, 4> ValExprs;
+
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.consumeOpen()) {
+ Diag(Tok, diag::err_expected) << tok::l_paren;
+ return nullptr;
+ }
+
+ while (true) {
+ ExprResult Val = ParseConstantExpression();
+ if (!Val.isUsable()) {
+ T.skipToEnd();
+ return nullptr;
+ }
+
+ ValExprs.push_back(Val.get());
+
+ if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
+ break;
+
+ ExpectAndConsume(tok::comma);
+ }
+
+ T.consumeClose();
+
+ return Actions.ActOnOpenMPSizesClause(
+ ValExprs, ClauseNameLoc, T.getOpenLocation(), T.getCloseLocation());
+}
+
OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
SourceLocation Loc = Tok.getLocation();
ConsumeAnyToken();
@@ -2643,7 +2710,8 @@
return nullptr;
SmallVector<Sema::UsesAllocatorsData, 4> Data;
do {
- ExprResult Allocator = ParseCXXIdExpression();
+ ExprResult Allocator =
+ getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
if (Allocator.isInvalid()) {
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
@@ -2655,7 +2723,8 @@
BalancedDelimiterTracker T(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
T.consumeOpen();
- ExprResult AllocatorTraits = ParseCXXIdExpression();
+ ExprResult AllocatorTraits =
+ getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
T.consumeClose();
if (AllocatorTraits.isInvalid()) {
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
@@ -2727,6 +2796,10 @@
case OMPC_allocator:
case OMPC_depobj:
case OMPC_detach:
+ case OMPC_novariants:
+ case OMPC_nocontext:
+ case OMPC_filter:
+ case OMPC_partial:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -2749,13 +2822,17 @@
// At most one allocator clause can appear on the directive.
// OpenMP 5.0, 2.10.1 task Construct, Restrictions.
// At most one detach clause can appear on the directive.
+ // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
+ // At most one novariants clause can appear on a dispatch directive.
+ // At most one nocontext clause can appear on a dispatch directive.
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
- if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
+ if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
+ PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
Clause = ParseOpenMPClause(CKind, WrongDirective);
else
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
@@ -2818,7 +2895,7 @@
case OMPC_unified_shared_memory:
case OMPC_reverse_offload:
case OMPC_dynamic_allocators:
- case OMPC_destroy:
+ case OMPC_full:
// OpenMP [2.7.1, Restrictions, p. 9]
// Only one ordered clause can appear on a loop directive.
// OpenMP [2.7.1, Restrictions, C/C++, p. 4]
@@ -2870,9 +2947,33 @@
case OMPC_affinity:
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
break;
+ case OMPC_sizes:
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+ ErrorFound = true;
+ }
+
+ Clause = ParseOpenMPSizesClause();
+ break;
case OMPC_uses_allocators:
Clause = ParseOpenMPUsesAllocatorClause(DKind);
break;
+ case OMPC_destroy:
+ if (DKind != OMPD_interop) {
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+ ErrorFound = true;
+ }
+ Clause = ParseOpenMPClause(CKind, WrongDirective);
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ case OMPC_init:
+ case OMPC_use:
+ Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
+ break;
case OMPC_device_type:
case OMPC_unknown:
skipUntilPragmaOpenMPEnd(DKind);
@@ -2969,6 +3070,144 @@
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
}
+/// Parsing of OpenMP clauses that use an interop-var.
+///
+/// init-clause:
+/// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
+///
+/// destroy-clause:
+/// destroy(interop-var)
+///
+/// use-clause:
+/// use(interop-var)
+///
+/// interop-modifier:
+/// prefer_type(preference-list)
+///
+/// preference-list:
+/// foreign-runtime-id [, foreign-runtime-id]...
+///
+/// foreign-runtime-id:
+/// <string-literal> | <constant-integral-expression>
+///
+/// interop-type:
+/// target | targetsync
+///
+OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
+ bool ParseOnly) {
+ SourceLocation Loc = ConsumeToken();
+ // Parse '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPClauseName(Kind).data()))
+ return nullptr;
+
+ bool IsTarget = false;
+ bool IsTargetSync = false;
+ SmallVector<Expr *, 4> Prefs;
+
+ if (Kind == OMPC_init) {
+
+ // Parse optional interop-modifier.
+ if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "prefer_type") {
+ ConsumeToken();
+ BalancedDelimiterTracker PT(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
+ return nullptr;
+
+ while (Tok.isNot(tok::r_paren)) {
+ SourceLocation Loc = Tok.getLocation();
+ ExprResult LHS = ParseCastExpression(AnyCastExpr);
+ ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
+ ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
+ /*DiscardedValue=*/false);
+ if (PTExpr.isUsable())
+ Prefs.push_back(PTExpr.get());
+ else
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ }
+ PT.consumeClose();
+ }
+
+ if (!Prefs.empty()) {
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ else
+ Diag(Tok, diag::err_omp_expected_punc_after_interop_mod);
+ }
+
+ // Parse the interop-types.
+ bool HasError = false;
+ while (Tok.is(tok::identifier)) {
+ if (PP.getSpelling(Tok) == "target") {
+ // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
+ // Each interop-type may be specified on an action-clause at most
+ // once.
+ if (IsTarget)
+ Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
+ IsTarget = true;
+ } else if (PP.getSpelling(Tok) == "targetsync") {
+ if (IsTargetSync)
+ Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
+ IsTargetSync = true;
+ } else {
+ HasError = true;
+ Diag(Tok, diag::err_omp_expected_interop_type);
+ }
+ ConsumeToken();
+
+ if (!Tok.is(tok::comma))
+ break;
+ ConsumeToken();
+ }
+ if (!HasError && !IsTarget && !IsTargetSync)
+ Diag(Tok, diag::err_omp_expected_interop_type);
+
+ if (Tok.is(tok::colon))
+ ConsumeToken();
+ else if (IsTarget || IsTargetSync)
+ Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
+ }
+
+ // Parse the variable.
+ SourceLocation VarLoc = Tok.getLocation();
+ ExprResult InteropVarExpr =
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+ if (!InteropVarExpr.isUsable()) {
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
+
+ // Parse ')'.
+ SourceLocation RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ RLoc = T.getCloseLocation();
+
+ if (ParseOnly || !InteropVarExpr.isUsable() ||
+ (Kind == OMPC_init && !IsTarget && !IsTargetSync))
+ return nullptr;
+
+ if (Kind == OMPC_init)
+ return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), Prefs, IsTarget,
+ IsTargetSync, Loc, T.getOpenLocation(),
+ VarLoc, RLoc);
+ if (Kind == OMPC_use)
+ return Actions.ActOnOpenMPUseClause(InteropVarExpr.get(), Loc,
+ T.getOpenLocation(), VarLoc, RLoc);
+
+ if (Kind == OMPC_destroy)
+ return Actions.ActOnOpenMPDestroyClause(InteropVarExpr.get(), Loc,
+ T.getOpenLocation(), VarLoc, RLoc);
+
+ llvm_unreachable("Unexpected interop variable clause.");
+}
+
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause:
diff --git a/src/llvm-project/clang/lib/Parse/ParsePragma.cpp b/src/llvm-project/clang/lib/Parse/ParsePragma.cpp
index f9b8528..42072fe 100644
--- a/src/llvm-project/clang/lib/Parse/ParsePragma.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParsePragma.cpp
@@ -14,11 +14,13 @@
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
#include "clang/Parse/LoopHint.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/Scope.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -292,6 +294,10 @@
Token &FirstToken) override;
};
+void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
+ for (auto &T : Toks)
+ T.setFlag(clang::Token::IsReinjected);
+}
} // end namespace
void Parser::initializePragmaHandlers() {
@@ -399,9 +405,11 @@
UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
PP.AddPragmaHandler(UnrollHintHandler.get());
+ PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
PP.AddPragmaHandler(NoUnrollHintHandler.get());
+ PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
UnrollAndJamHintHandler =
std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
@@ -517,9 +525,11 @@
LoopHintHandler.reset();
PP.RemovePragmaHandler(UnrollHintHandler.get());
+ PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
UnrollHintHandler.reset();
PP.RemovePragmaHandler(NoUnrollHintHandler.get());
+ PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
NoUnrollHintHandler.reset();
PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
@@ -771,22 +781,21 @@
// overriding all previously issued extension directives, but only if the
// behavior is set to disable."
if (Name == "all") {
- if (State == Disable) {
+ if (State == Disable)
Opt.disableAll();
- Opt.enableSupportedCore(getLangOpts());
- } else {
+ else
PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
- }
} else if (State == Begin) {
if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
Opt.support(Name);
+ // FIXME: Default behavior of the extension pragma is not defined.
+ // Therefore, it should never be added by default.
+ Opt.acceptsPragma(Name);
}
- Actions.setCurrentOpenCLExtension(Name);
} else if (State == End) {
- if (Name != Actions.getCurrentOpenCLExtension())
- PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
- Actions.setCurrentOpenCLExtension("");
- } else if (!Opt.isKnown(Name))
+ // There is no behavior for this directive. We only accept this for
+ // backward compatibility.
+ } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
else if (Opt.isSupportedExtension(Name, getLangOpts()))
Opt.enable(Name, State == Enable);
@@ -2618,6 +2627,7 @@
TokenVector.push_back(EoF);
// We must allocate this array with new because EnterTokenStream is going to
// delete it later.
+ markAsReinjectedForRelexing(TokenVector);
auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
auto Value = new (PP.getPreprocessorAllocator())
@@ -3175,6 +3185,7 @@
EOFTok.setLocation(Tok.getLocation());
ValueList.push_back(EOFTok); // Terminates expression for parsing.
+ markAsReinjectedForRelexing(ValueList);
Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Info.PragmaName = PragmaName;
@@ -3631,6 +3642,7 @@
EOFTok.setLocation(EndLoc);
AttributeTokens.push_back(EOFTok);
+ markAsReinjectedForRelexing(AttributeTokens);
Info->Tokens =
llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
}
diff --git a/src/llvm-project/clang/lib/Parse/ParseStmt.cpp b/src/llvm-project/clang/lib/Parse/ParseStmt.cpp
index 26a0257..ebfe048 100644
--- a/src/llvm-project/clang/lib/Parse/ParseStmt.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseStmt.cpp
@@ -20,6 +20,8 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
+#include "llvm/ADT/STLExtras.h"
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -98,10 +100,15 @@
ParenBraceBracketBalancer BalancerRAIIObj(*this);
+ // Because we're parsing either a statement or a declaration, the order of
+ // attribute parsing is important. [[]] attributes at the start of a
+ // statement are different from [[]] attributes that follow an __attribute__
+ // at the start of the statement. Thus, we're not using MaybeParseAttributes
+ // here because we don't want to allow arbitrary orderings.
ParsedAttributesWithRange Attrs(AttrFactory);
MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true);
- if (!MaybeParseOpenCLUnrollHintAttribute(Attrs))
- return StmtError();
+ if (getLangOpts().OpenCL)
+ MaybeParseGNUAttributes(Attrs);
StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
Stmts, StmtCtx, TrailingElseLoc, Attrs);
@@ -113,7 +120,7 @@
if (Attrs.empty() || Res.isInvalid())
return Res;
- return Actions.ProcessStmtAttributes(Res.get(), Attrs, Attrs.Range);
+ return Actions.ActOnAttributedStmt(Attrs, Res.get());
}
namespace {
@@ -165,14 +172,13 @@
switch (Kind) {
case tok::at: // May be a @try or @throw statement
{
- ProhibitAttributes(Attrs); // TODO: is it correct?
AtLoc = ConsumeToken(); // consume @
return ParseObjCAtStatement(AtLoc, StmtCtx);
}
case tok::code_completion:
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
cutOffParsing();
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
return StmtError();
case tok::identifier: {
@@ -210,7 +216,11 @@
if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
(StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
ParsedStmtContext()) &&
- (GNUAttributeLoc.isValid() || isDeclarationStatement())) {
+ ((GNUAttributeLoc.isValid() &&
+ !(!Attrs.empty() &&
+ llvm::all_of(
+ Attrs, [](ParsedAttr &Attr) { return Attr.isStmtAttr(); }))) ||
+ isDeclarationStatement())) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy Decl;
if (GNUAttributeLoc.isValid()) {
@@ -391,7 +401,12 @@
return HandlePragmaCaptured();
case tok::annot_pragma_openmp:
+ // Prohibit attributes that are not OpenMP attributes, but only before
+ // processing a #pragma omp clause.
ProhibitAttributes(Attrs);
+ LLVM_FALLTHROUGH;
+ case tok::annot_attr_openmp:
+ // Do not prohibit attributes if they were OpenMP attributes.
return ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx);
case tok::annot_pragma_ms_pointers_to_members:
@@ -638,19 +653,12 @@
// attributes as part of a statement in that case). That looks like a bug.
if (!getLangOpts().CPlusPlus || Tok.is(tok::semi))
attrs.takeAllFrom(TempAttrs);
- else if (isDeclarationStatement()) {
+ else {
StmtVector Stmts;
- // FIXME: We should do this whether or not we have a declaration
- // statement, but that doesn't work correctly (because ProhibitAttributes
- // can't handle GNU attributes), so only call it in the one case where
- // GNU attributes are allowed.
SubStmt = ParseStatementOrDeclarationAfterAttributes(Stmts, StmtCtx,
nullptr, TempAttrs);
if (!TempAttrs.empty() && !SubStmt.isInvalid())
- SubStmt = Actions.ProcessStmtAttributes(SubStmt.get(), TempAttrs,
- TempAttrs.Range);
- } else {
- Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi;
+ SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
}
}
@@ -715,8 +723,8 @@
ColonLoc = SourceLocation();
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteCase(getCurScope());
cutOffParsing();
+ Actions.CodeCompleteCase(getCurScope());
return StmtError();
}
@@ -1134,7 +1142,7 @@
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
R = handleExprStmt(Res, SubStmtCtx);
if (R.isUsable())
- R = Actions.ProcessStmtAttributes(R.get(), attrs, attrs.Range);
+ R = Actions.ActOnAttributedStmt(attrs, R.get());
}
}
@@ -1461,8 +1469,8 @@
// Pop the 'else' scope if needed.
InnerScope.Exit();
} else if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteAfterIf(getCurScope(), IsBracedThen);
cutOffParsing();
+ Actions.CodeCompleteAfterIf(getCurScope(), IsBracedThen);
return StmtError();
} else if (InnerStatementTrailingElseLoc.isValid()) {
Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
@@ -1816,10 +1824,10 @@
FullExprArg ThirdPart(Actions);
if (Tok.is(tok::code_completion)) {
+ cutOffParsing();
Actions.CodeCompleteOrdinaryName(getCurScope(),
C99orCXXorObjC? Sema::PCC_ForInit
: Sema::PCC_Expression);
- cutOffParsing();
return StmtError();
}
@@ -1887,8 +1895,8 @@
ConsumeToken(); // consume 'in'
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
cutOffParsing();
+ Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
return StmtError();
}
Collection = ParseExpression();
@@ -1923,8 +1931,8 @@
ConsumeToken(); // consume 'in'
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteObjCForCollection(getCurScope(), nullptr);
cutOffParsing();
+ Actions.CodeCompleteObjCForCollection(getCurScope(), nullptr);
return StmtError();
}
Collection = ParseExpression();
@@ -1948,7 +1956,6 @@
}
// Parse the second part of the for specifier.
- getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() &&
!SecondPart.isInvalid()) {
// Parse the second part of the for specifier.
@@ -1964,7 +1971,8 @@
ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
SecondPart =
ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean,
- MightBeForRangeStmt ? &ForRangeInfo : nullptr);
+ MightBeForRangeStmt ? &ForRangeInfo : nullptr,
+ /*EnterForConditionScope*/ true);
if (ForRangeInfo.ParsedForRangeDecl()) {
Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc()
@@ -1981,6 +1989,9 @@
}
}
} else {
+ // We permit 'continue' and 'break' in the condition of a for loop.
+ getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
+
ExprResult SecondExpr = ParseExpression();
if (SecondExpr.isInvalid())
SecondPart = Sema::ConditionError();
@@ -1992,6 +2003,11 @@
}
}
+ // Enter a break / continue scope, if we didn't already enter one while
+ // parsing the second part.
+ if (!(getCurScope()->getFlags() & Scope::ContinueScope))
+ getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
+
// Parse the third part of the for statement.
if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
if (Tok.isNot(tok::semi)) {
@@ -2177,9 +2193,9 @@
PreferredType.enterReturn(Actions, Tok.getLocation());
// FIXME: Code completion for co_return.
if (Tok.is(tok::code_completion) && !IsCoreturn) {
+ cutOffParsing();
Actions.CodeCompleteExpression(getCurScope(),
PreferredType.get(Tok.getLocation()));
- cutOffParsing();
return StmtError();
}
@@ -2548,19 +2564,3 @@
}
Braces.consumeClose();
}
-
-bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) {
- MaybeParseGNUAttributes(Attrs);
-
- if (Attrs.empty())
- return true;
-
- if (Attrs.begin()->getKind() != ParsedAttr::AT_OpenCLUnrollHint)
- return true;
-
- if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) {
- Diag(Tok, diag::err_opencl_unroll_hint_on_non_loop);
- return false;
- }
- return true;
-}
diff --git a/src/llvm-project/clang/lib/Parse/ParseStmtAsm.cpp b/src/llvm-project/clang/lib/Parse/ParseStmtAsm.cpp
index bdf40c2..e520151 100644
--- a/src/llvm-project/clang/lib/Parse/ParseStmtAsm.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseStmtAsm.cpp
@@ -577,19 +577,22 @@
TheTarget->createMCAsmInfo(*MRI, TT, MCOptions));
// Get the instruction descriptor.
std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
- std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
std::unique_ptr<llvm::MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TT, TO.CPU, FeaturesStr));
// Target MCTargetDesc may not be linked in clang-based tools.
- if (!MAI || !MII || !MOFI || !STI) {
+
+ if (!MAI || !MII || !STI) {
Diag(AsmLoc, diag::err_msasm_unable_to_create_target)
<< "target MC unavailable";
return EmptyStmt();
}
llvm::SourceMgr TempSrcMgr;
- llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
- MOFI->InitMCObjectFileInfo(TheTriple, /*PIC*/ false, Ctx);
+ llvm::MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &TempSrcMgr);
+ std::unique_ptr<llvm::MCObjectFileInfo> MOFI(
+ TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
+ Ctx.setObjectFileInfo(MOFI.get());
+
std::unique_ptr<llvm::MemoryBuffer> Buffer =
llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
@@ -630,9 +633,9 @@
SmallVector<std::pair<void *, bool>, 4> OpExprs;
SmallVector<std::string, 4> Constraints;
SmallVector<std::string, 4> Clobbers;
- if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs,
- NumInputs, OpExprs, Constraints, Clobbers,
- MII.get(), IP.get(), Callback))
+ if (Parser->parseMSInlineAsm(AsmStringIR, NumOutputs, NumInputs, OpExprs,
+ Constraints, Clobbers, MII.get(), IP.get(),
+ Callback))
return StmtError();
// Filter out "fpsw" and "mxcsr". They aren't valid GCC asm clobber
diff --git a/src/llvm-project/clang/lib/Parse/ParseTentative.cpp b/src/llvm-project/clang/lib/Parse/ParseTentative.cpp
index 3bf2bc4..c0bfbbd 100644
--- a/src/llvm-project/clang/lib/Parse/ParseTentative.cpp
+++ b/src/llvm-project/clang/lib/Parse/ParseTentative.cpp
@@ -353,8 +353,8 @@
if (CanBeForRangeDecl) {
// Skip until we hit a ')', ';', or a ':' with no matching '?'.
// The final case is a for range declaration, the rest are not.
+ unsigned QuestionColonDepth = 0;
while (true) {
- unsigned QuestionColonDepth = 0;
P.SkipUntil({tok::r_paren, tok::semi, tok::question, tok::colon},
StopBeforeMatch);
if (P.Tok.is(tok::question))
diff --git a/src/llvm-project/clang/lib/Parse/Parser.cpp b/src/llvm-project/clang/lib/Parse/Parser.cpp
index 9b0f921..c81dd03 100644
--- a/src/llvm-project/clang/lib/Parse/Parser.cpp
+++ b/src/llvm-project/clang/lib/Parse/Parser.cpp
@@ -49,10 +49,10 @@
}
Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
- : PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
- GreaterThanIsOperator(true), ColonIsSacred(false),
- InMessageExpression(false), TemplateParameterDepth(0),
- ParsingInObjCContainer(false) {
+ : PP(pp), PreferredType(pp.isCodeCompletionEnabled()), Actions(actions),
+ Diags(PP.getDiagnostics()), GreaterThanIsOperator(true),
+ ColonIsSacred(false), InMessageExpression(false),
+ TemplateParameterDepth(0), ParsingInObjCContainer(false) {
SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies;
Tok.startToken();
Tok.setKind(tok::eof);
@@ -309,6 +309,7 @@
return false;
case tok::annot_pragma_openmp:
+ case tok::annot_attr_openmp:
case tok::annot_pragma_openmp_end:
// Stop before an OpenMP pragma boundary.
if (OpenMPDirectiveParsing)
@@ -494,6 +495,7 @@
Ident_instancetype = nullptr;
Ident_final = nullptr;
Ident_sealed = nullptr;
+ Ident_abstract = nullptr;
Ident_override = nullptr;
Ident_GNU_final = nullptr;
Ident_import = nullptr;
@@ -503,10 +505,12 @@
Ident_vector = nullptr;
Ident_bool = nullptr;
+ Ident_Bool = nullptr;
Ident_pixel = nullptr;
if (getLangOpts().AltiVec || getLangOpts().ZVector) {
Ident_vector = &PP.getIdentifierTable().get("vector");
Ident_bool = &PP.getIdentifierTable().get("bool");
+ Ident_Bool = &PP.getIdentifierTable().get("_Bool");
}
if (getLangOpts().AltiVec)
Ident_pixel = &PP.getIdentifierTable().get("pixel");
@@ -795,6 +799,7 @@
case tok::annot_pragma_opencl_extension:
HandlePragmaOpenCLExtension();
return nullptr;
+ case tok::annot_attr_openmp:
case tok::annot_pragma_openmp: {
AccessSpecifier AS = AS_none;
return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, attrs);
@@ -870,6 +875,7 @@
SingleDecl = ParseObjCMethodDefinition();
break;
case tok::code_completion:
+ cutOffParsing();
if (CurParsedObjCImpl) {
// Code-complete Objective-C methods even without leading '-'/'+' prefix.
Actions.CodeCompleteObjCMethodDecl(getCurScope(),
@@ -879,7 +885,6 @@
Actions.CodeCompleteOrdinaryName(
getCurScope(),
CurParsedObjCImpl ? Sema::PCC_ObjCImplementation : Sema::PCC_Namespace);
- cutOffParsing();
return nullptr;
case tok::kw_import:
SingleDecl = ParseModuleImport(SourceLocation());
@@ -1079,8 +1084,6 @@
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
DS, AnonRecord);
DS.complete(TheDecl);
- if (getLangOpts().OpenCL)
- Actions.setCurrentOpenCLExtensionForDecl(TheDecl);
if (AnonRecord) {
Decl* decls[] = {AnonRecord, TheDecl};
return Actions.BuildDeclaratorGroup(decls);
@@ -1213,7 +1216,7 @@
// a definition. Late parsed attributes are checked at the end.
if (Tok.isNot(tok::equal)) {
for (const ParsedAttr &AL : D.getAttributes())
- if (AL.isKnownToGCC() && !AL.isCXX11Attribute())
+ if (AL.isKnownToGCC() && !AL.isStandardAttributeSyntax())
Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) << AL;
}
@@ -1695,6 +1698,11 @@
break;
case Sema::NC_Type: {
+ if (TryAltiVecVectorToken())
+ // vector has been found as a type id when altivec is enabled but
+ // this is followed by a declaration specifier so this is really the
+ // altivec vector token. Leave it unannotated.
+ break;
SourceLocation BeginLoc = NameLoc;
if (SS.isNotEmpty())
BeginLoc = SS.getBeginLoc();
@@ -1736,6 +1744,11 @@
return ANK_Success;
case Sema::NC_NonType:
+ if (TryAltiVecVectorToken())
+ // vector has been found as a non-type id when altivec is enabled but
+ // this is followed by a declaration specifier so this is really the
+ // altivec vector token. Leave it unannotated.
+ break;
Tok.setKind(tok::annot_non_type);
setNonTypeAnnotation(Tok, Classification.getNonTypeDecl());
Tok.setLocation(NameLoc);
@@ -2114,21 +2127,21 @@
for (Scope *S = getCurScope(); S; S = S->getParent()) {
if (S->getFlags() & Scope::FnScope) {
+ cutOffParsing();
Actions.CodeCompleteOrdinaryName(getCurScope(),
Sema::PCC_RecoveryInFunction);
- cutOffParsing();
return PrevTokLocation;
}
if (S->getFlags() & Scope::ClassScope) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Class);
cutOffParsing();
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Class);
return PrevTokLocation;
}
}
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace);
cutOffParsing();
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace);
return PrevTokLocation;
}
@@ -2452,8 +2465,8 @@
while (true) {
if (!Tok.is(tok::identifier)) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteModuleImport(UseLoc, Path);
cutOffParsing();
+ Actions.CodeCompleteModuleImport(UseLoc, Path);
return true;
}
diff --git a/src/llvm-project/clang/lib/Rewrite/DeltaTree.cpp b/src/llvm-project/clang/lib/Rewrite/DeltaTree.cpp
index d27795c2..61467f8 100644
--- a/src/llvm-project/clang/lib/Rewrite/DeltaTree.cpp
+++ b/src/llvm-project/clang/lib/Rewrite/DeltaTree.cpp
@@ -458,7 +458,10 @@
DeltaTreeNode::InsertResult InsertRes;
if (MyRoot->DoInsertion(FileIndex, Delta, &InsertRes)) {
- Root = MyRoot = new DeltaTreeInteriorNode(InsertRes);
+ Root = new DeltaTreeInteriorNode(InsertRes);
+#ifdef VERIFY_TREE
+ MyRoot = Root;
+#endif
}
#ifdef VERIFY_TREE
diff --git a/src/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp b/src/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
index edd9742..aa2602c 100644
--- a/src/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/src/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1506,6 +1506,25 @@
}
}
+namespace clang {
+namespace {
+typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
+typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
+typedef std::list<DelayedDiag> DiagList;
+
+struct SortDiagBySourceLocation {
+ SourceManager &SM;
+ SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
+
+ bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
+ // Although this call will be slow, this is only called when outputting
+ // multiple warnings.
+ return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
+ }
+};
+} // anonymous namespace
+} // namespace clang
+
namespace {
class UninitValsDiagReporter : public UninitVariablesHandler {
Sema &S;
@@ -1626,9 +1645,35 @@
}
};
+/// Inter-procedural data for the called-once checker.
+class CalledOnceInterProceduralData {
+public:
+ // Add the delayed warning for the given block.
+ void addDelayedWarning(const BlockDecl *Block,
+ PartialDiagnosticAt &&Warning) {
+ DelayedBlockWarnings[Block].emplace_back(std::move(Warning));
+ }
+ // Report all of the warnings we've gathered for the given block.
+ void flushWarnings(const BlockDecl *Block, Sema &S) {
+ for (const PartialDiagnosticAt &Delayed : DelayedBlockWarnings[Block])
+ S.Diag(Delayed.first, Delayed.second);
+
+ discardWarnings(Block);
+ }
+ // Discard all of the warnings we've gathered for the given block.
+ void discardWarnings(const BlockDecl *Block) {
+ DelayedBlockWarnings.erase(Block);
+ }
+
+private:
+ using DelayedDiagnostics = SmallVector<PartialDiagnosticAt, 2>;
+ llvm::DenseMap<const BlockDecl *, DelayedDiagnostics> DelayedBlockWarnings;
+};
+
class CalledOnceCheckReporter : public CalledOnceCheckHandler {
public:
- CalledOnceCheckReporter(Sema &S) : S(S) {}
+ CalledOnceCheckReporter(Sema &S, CalledOnceInterProceduralData &Data)
+ : S(S), Data(Data) {}
void handleDoubleCall(const ParmVarDecl *Parameter, const Expr *Call,
const Expr *PrevCall, bool IsCompletionHandler,
bool Poised) override {
@@ -1649,14 +1694,24 @@
<< Parameter << /* Captured */ false;
}
- void handleNeverCalled(const ParmVarDecl *Parameter, const Stmt *Where,
- NeverCalledReason Reason, bool IsCalledDirectly,
+ void handleNeverCalled(const ParmVarDecl *Parameter, const Decl *Function,
+ const Stmt *Where, NeverCalledReason Reason,
+ bool IsCalledDirectly,
bool IsCompletionHandler) override {
auto DiagToReport = IsCompletionHandler
? diag::warn_completion_handler_never_called_when
: diag::warn_called_once_never_called_when;
- S.Diag(Where->getBeginLoc(), DiagToReport)
- << Parameter << IsCalledDirectly << (unsigned)Reason;
+ PartialDiagnosticAt Warning(Where->getBeginLoc(), S.PDiag(DiagToReport)
+ << Parameter
+ << IsCalledDirectly
+ << (unsigned)Reason);
+
+ if (const auto *Block = dyn_cast<BlockDecl>(Function)) {
+ // We shouldn't report these warnings on blocks immediately
+ Data.addDelayedWarning(Block, std::move(Warning));
+ } else {
+ S.Diag(Warning.first, Warning.second);
+ }
}
void handleCapturedNeverCalled(const ParmVarDecl *Parameter,
@@ -1669,8 +1724,18 @@
<< Parameter << /* Captured */ true;
}
+ void
+ handleBlockThatIsGuaranteedToBeCalledOnce(const BlockDecl *Block) override {
+ Data.flushWarnings(Block, S);
+ }
+
+ void handleBlockWithNoGuarantees(const BlockDecl *Block) override {
+ Data.discardWarnings(Block);
+ }
+
private:
Sema &S;
+ CalledOnceInterProceduralData &Data;
};
constexpr unsigned CalledOnceWarnings[] = {
@@ -1703,25 +1768,6 @@
}
} // anonymous namespace
-namespace clang {
-namespace {
-typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
-typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
-typedef std::list<DelayedDiag> DiagList;
-
-struct SortDiagBySourceLocation {
- SourceManager &SM;
- SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
-
- bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
- // Although this call will be slow, this is only called when outputting
- // multiple warnings.
- return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
- }
-};
-} // anonymous namespace
-} // namespace clang
-
//===----------------------------------------------------------------------===//
// -Wthread-safety
//===----------------------------------------------------------------------===//
@@ -2107,54 +2153,68 @@
// warnings on a function, method, or block.
//===----------------------------------------------------------------------===//
-clang::sema::AnalysisBasedWarnings::Policy::Policy() {
+sema::AnalysisBasedWarnings::Policy::Policy() {
enableCheckFallThrough = 1;
enableCheckUnreachable = 0;
enableThreadSafetyAnalysis = 0;
enableConsumedAnalysis = 0;
}
+/// InterProceduralData aims to be a storage of whatever data should be passed
+/// between analyses of different functions.
+///
+/// At the moment, its primary goal is to make the information gathered during
+/// the analysis of the blocks available during the analysis of the enclosing
+/// function. This is important due to the fact that blocks are analyzed before
+/// the enclosed function is even parsed fully, so it is not viable to access
+/// anything in the outer scope while analyzing the block. On the other hand,
+/// re-building CFG for blocks and re-analyzing them when we do have all the
+/// information (i.e. during the analysis of the enclosing function) seems to be
+/// ill-designed.
+class sema::AnalysisBasedWarnings::InterProceduralData {
+public:
+ // It is important to analyze blocks within functions because it's a very
+ // common pattern to capture completion handler parameters by blocks.
+ CalledOnceInterProceduralData CalledOnceData;
+};
+
static unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) {
return (unsigned)!D.isIgnored(diag, SourceLocation());
}
-clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
- : S(s),
- NumFunctionsAnalyzed(0),
- NumFunctionsWithBadCFGs(0),
- NumCFGBlocks(0),
- MaxCFGBlocksPerFunction(0),
- NumUninitAnalysisFunctions(0),
- NumUninitAnalysisVariables(0),
- MaxUninitAnalysisVariablesPerFunction(0),
- NumUninitAnalysisBlockVisits(0),
- MaxUninitAnalysisBlockVisitsPerFunction(0) {
+sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
+ : S(s), IPData(std::make_unique<InterProceduralData>()),
+ NumFunctionsAnalyzed(0), NumFunctionsWithBadCFGs(0), NumCFGBlocks(0),
+ MaxCFGBlocksPerFunction(0), NumUninitAnalysisFunctions(0),
+ NumUninitAnalysisVariables(0), MaxUninitAnalysisVariablesPerFunction(0),
+ NumUninitAnalysisBlockVisits(0),
+ MaxUninitAnalysisBlockVisitsPerFunction(0) {
using namespace diag;
DiagnosticsEngine &D = S.getDiagnostics();
DefaultPolicy.enableCheckUnreachable =
- isEnabled(D, warn_unreachable) ||
- isEnabled(D, warn_unreachable_break) ||
- isEnabled(D, warn_unreachable_return) ||
- isEnabled(D, warn_unreachable_loop_increment);
+ isEnabled(D, warn_unreachable) || isEnabled(D, warn_unreachable_break) ||
+ isEnabled(D, warn_unreachable_return) ||
+ isEnabled(D, warn_unreachable_loop_increment);
- DefaultPolicy.enableThreadSafetyAnalysis =
- isEnabled(D, warn_double_lock);
+ DefaultPolicy.enableThreadSafetyAnalysis = isEnabled(D, warn_double_lock);
DefaultPolicy.enableConsumedAnalysis =
- isEnabled(D, warn_use_in_invalid_state);
+ isEnabled(D, warn_use_in_invalid_state);
}
+// We need this here for unique_ptr with forward declared class.
+sema::AnalysisBasedWarnings::~AnalysisBasedWarnings() = default;
+
static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
for (const auto &D : fscope->PossiblyUnreachableDiags)
S.Diag(D.Loc, D.PD);
}
-void clang::sema::
-AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
- sema::FunctionScopeInfo *fscope,
- const Decl *D, QualType BlockType) {
+void clang::sema::AnalysisBasedWarnings::IssueWarnings(
+ sema::AnalysisBasedWarnings::Policy P, sema::FunctionScopeInfo *fscope,
+ const Decl *D, QualType BlockType) {
// We avoid doing analysis-based warnings when there are errors for
// two reasons:
@@ -2343,10 +2403,10 @@
}
// Check for violations of "called once" parameter properties.
- if (S.getLangOpts().ObjC &&
+ if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus &&
shouldAnalyzeCalledOnceParameters(Diags, D->getBeginLoc())) {
if (AC.getCFG()) {
- CalledOnceCheckReporter Reporter(S);
+ CalledOnceCheckReporter Reporter(S, IPData->CalledOnceData);
checkCalledOnceParameters(
AC, Reporter,
shouldAnalyzeCalledOnceConventions(Diags, D->getBeginLoc()));
diff --git a/src/llvm-project/clang/lib/Sema/CMakeLists.txt b/src/llvm-project/clang/lib/Sema/CMakeLists.txt
index 251856c..0e0681a 100644
--- a/src/llvm-project/clang/lib/Sema/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/Sema/CMakeLists.txt
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS
Core
FrontendOpenMP
+ MC
Support
)
diff --git a/src/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp b/src/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp
index 678a09b..3ab2a18 100644
--- a/src/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/src/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -755,7 +755,7 @@
std::string XSaved, YSaved;
StringRef XStr = X.getOrderedName(XSaved);
StringRef YStr = Y.getOrderedName(YSaved);
- int cmp = XStr.compare_lower(YStr);
+ int cmp = XStr.compare_insensitive(YStr);
if (cmp)
return cmp < 0;
diff --git a/src/llvm-project/clang/lib/Sema/DeclSpec.cpp b/src/llvm-project/clang/lib/Sema/DeclSpec.cpp
index da42db3..72d9ea6 100644
--- a/src/llvm-project/clang/lib/Sema/DeclSpec.cpp
+++ b/src/llvm-project/clang/lib/Sema/DeclSpec.cpp
@@ -625,7 +625,8 @@
// OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
// specifiers are not supported."
if (S.getLangOpts().OpenCL &&
- !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
+ !S.getOpenCLOptions().isAvailableOption(
+ "cl_clang_storage_class_specifiers", S.getLangOpts())) {
switch (SC) {
case SCS_extern:
case SCS_private_extern:
@@ -1474,6 +1475,7 @@
case VS_GNU_Final:
case VS_Sealed:
case VS_Final: VS_finalLoc = Loc; break;
+ case VS_Abstract: VS_abstractLoc = Loc; break;
}
return false;
@@ -1486,5 +1488,6 @@
case VS_Final: return "final";
case VS_GNU_Final: return "__final";
case VS_Sealed: return "sealed";
+ case VS_Abstract: return "abstract";
}
}
diff --git a/src/llvm-project/clang/lib/Sema/JumpDiagnostics.cpp b/src/llvm-project/clang/lib/Sema/JumpDiagnostics.cpp
index d33b14a..999c2a4 100644
--- a/src/llvm-project/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/src/llvm-project/clang/lib/Sema/JumpDiagnostics.cpp
@@ -11,13 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/BitVector.h"
using namespace clang;
@@ -29,6 +30,10 @@
/// int a[n];
/// L:
///
+/// We also detect jumps out of protected scopes when it's not possible to do
+/// cleanups properly. Indirect jumps and ASM jumps can't do cleanups because
+/// the target is unknown. Return statements with \c [[clang::musttail]] cannot
+/// handle any cleanups due to the nature of a tail call.
class JumpScopeChecker {
Sema &S;
@@ -68,6 +73,7 @@
SmallVector<Stmt*, 4> IndirectJumps;
SmallVector<Stmt*, 4> AsmJumps;
+ SmallVector<AttributedStmt *, 4> MustTailStmts;
SmallVector<LabelDecl*, 4> IndirectJumpTargets;
SmallVector<LabelDecl*, 4> AsmJumpTargets;
public:
@@ -81,6 +87,7 @@
void VerifyJumps();
void VerifyIndirectOrAsmJumps(bool IsAsmGoto);
+ void VerifyMustTailStmts();
void NoteJumpIntoScopes(ArrayRef<unsigned> ToScopes);
void DiagnoseIndirectOrAsmJump(Stmt *IG, unsigned IGScope, LabelDecl *Target,
unsigned TargetScope);
@@ -88,6 +95,7 @@
unsigned JumpDiag, unsigned JumpDiagWarning,
unsigned JumpDiagCXX98Compat);
void CheckGotoStmt(GotoStmt *GS);
+ const Attr *GetMustTailAttr(AttributedStmt *AS);
unsigned GetDeepestCommonScope(unsigned A, unsigned B);
};
@@ -109,6 +117,7 @@
VerifyJumps();
VerifyIndirectOrAsmJumps(false);
VerifyIndirectOrAsmJumps(true);
+ VerifyMustTailStmts();
}
/// GetDeepestCommonScope - Finds the innermost scope enclosing the
@@ -580,6 +589,15 @@
LabelAndGotoScopes[S] = ParentScope;
break;
+ case Stmt::AttributedStmtClass: {
+ AttributedStmt *AS = cast<AttributedStmt>(S);
+ if (GetMustTailAttr(AS)) {
+ LabelAndGotoScopes[AS] = ParentScope;
+ MustTailStmts.push_back(AS);
+ }
+ break;
+ }
+
default:
if (auto *ED = dyn_cast<OMPExecutableDirective>(S)) {
if (!ED->isStandaloneDirective()) {
@@ -947,6 +965,9 @@
if (!ToScopesWarning.empty()) {
S.Diag(DiagLoc, JumpDiagWarning);
NoteJumpIntoScopes(ToScopesWarning);
+ assert(isa<LabelStmt>(To));
+ LabelStmt *Label = cast<LabelStmt>(To);
+ Label->setSideEntry(true);
}
// Handle errors.
@@ -971,6 +992,24 @@
}
}
+void JumpScopeChecker::VerifyMustTailStmts() {
+ for (AttributedStmt *AS : MustTailStmts) {
+ for (unsigned I = LabelAndGotoScopes[AS]; I; I = Scopes[I].ParentScope) {
+ if (Scopes[I].OutDiag) {
+ S.Diag(AS->getBeginLoc(), diag::err_musttail_scope);
+ S.Diag(Scopes[I].Loc, Scopes[I].OutDiag);
+ }
+ }
+ }
+}
+
+const Attr *JumpScopeChecker::GetMustTailAttr(AttributedStmt *AS) {
+ ArrayRef<const Attr *> Attrs = AS->getAttrs();
+ const auto *Iter =
+ llvm::find_if(Attrs, [](const Attr *A) { return isa<MustTailAttr>(A); });
+ return Iter != Attrs.end() ? *Iter : nullptr;
+}
+
void Sema::DiagnoseInvalidJumps(Stmt *Body) {
(void)JumpScopeChecker(Body, *this);
}
diff --git a/src/llvm-project/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/src/llvm-project/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 252008c..0727756 100644
--- a/src/llvm-project/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/src/llvm-project/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/MultiplexExternalSemaSource.h"
-#include "clang/AST/DeclContextInternals.h"
#include "clang/Sema/Lookup.h"
using namespace clang;
@@ -269,7 +268,7 @@
}
void MultiplexExternalSemaSource::ReadDeclsToCheckForDeferredDiags(
- llvm::SmallVector<Decl *, 4> &Decls) {
+ llvm::SmallSetVector<Decl *, 4> &Decls) {
for(size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadDeclsToCheckForDeferredDiags(Decls);
}
diff --git a/src/llvm-project/clang/lib/Sema/OpenCLBuiltins.td b/src/llvm-project/clang/lib/Sema/OpenCLBuiltins.td
index 745363a..cd704fe 100644
--- a/src/llvm-project/clang/lib/Sema/OpenCLBuiltins.td
+++ b/src/llvm-project/clang/lib/Sema/OpenCLBuiltins.td
@@ -50,9 +50,29 @@
// Extension associated to a builtin function.
class FunctionExtension<string _Ext> : AbstractExtension<_Ext>;
+// Extension associated to a type. This enables implicit conditionalization of
+// builtin function overloads containing a type that depends on an extension.
+// During overload resolution, when a builtin function overload contains a type
+// with a TypeExtension, those overloads are skipped when the extension is
+// disabled.
+class TypeExtension<string _Ext> : AbstractExtension<_Ext>;
+
+// TypeExtension definitions.
+def NoTypeExt : TypeExtension<"">;
+def Fp16TypeExt : TypeExtension<"cl_khr_fp16">;
+def Fp64TypeExt : TypeExtension<"cl_khr_fp64">;
+
// FunctionExtension definitions.
def FuncExtNone : FunctionExtension<"">;
def FuncExtKhrSubgroups : FunctionExtension<"cl_khr_subgroups">;
+def FuncExtKhrSubgroupExtendedTypes : FunctionExtension<"cl_khr_subgroup_extended_types">;
+def FuncExtKhrSubgroupNonUniformVote : FunctionExtension<"cl_khr_subgroup_non_uniform_vote">;
+def FuncExtKhrSubgroupBallot : FunctionExtension<"cl_khr_subgroup_ballot">;
+def FuncExtKhrSubgroupNonUniformArithmetic: FunctionExtension<"cl_khr_subgroup_non_uniform_arithmetic">;
+def FuncExtKhrSubgroupShuffle : FunctionExtension<"cl_khr_subgroup_shuffle">;
+def FuncExtKhrSubgroupShuffleRelative : FunctionExtension<"cl_khr_subgroup_shuffle_relative">;
+def FuncExtKhrSubgroupClusteredReduce : FunctionExtension<"cl_khr_subgroup_clustered_reduce">;
+def FuncExtKhrExtendedBitOps : FunctionExtension<"cl_khr_extended_bit_ops">;
def FuncExtKhrGlobalInt32BaseAtomics : FunctionExtension<"cl_khr_global_int32_base_atomics">;
def FuncExtKhrGlobalInt32ExtendedAtomics : FunctionExtension<"cl_khr_global_int32_extended_atomics">;
def FuncExtKhrLocalInt32BaseAtomics : FunctionExtension<"cl_khr_local_int32_base_atomics">;
@@ -63,6 +83,9 @@
def FuncExtKhrMipmapImageWrites : FunctionExtension<"cl_khr_mipmap_image_writes">;
def FuncExtKhrGlMsaaSharing : FunctionExtension<"cl_khr_gl_msaa_sharing">;
+// Not a real extension, but a workaround to add C++ for OpenCL specific builtins.
+def FuncExtOpenCLCxx : FunctionExtension<"__cplusplus">;
+
// Multiple extensions
def FuncExtKhrMipmapWritesAndWrite3d : FunctionExtension<"cl_khr_mipmap_image_writes cl_khr_3d_image_writes">;
@@ -73,10 +96,10 @@
def ArmIntegerDotProductAccumulateSaturateInt8 : FunctionExtension<"cl_arm_integer_dot_product_accumulate_saturate_int8">;
// Qualified Type. These map to ASTContext::QualType.
-class QualType<string _Name, bit _IsAbstract=0> {
- // Name of the field or function in a clang::ASTContext
- // E.g. Name="IntTy" for the int type, and "getIntPtrType()" for an intptr_t
- string Name = _Name;
+class QualType<string _TypeExpr, bit _IsAbstract=0> {
+ // Expression to obtain the QualType inside OCL2Qual.
+ // E.g. TypeExpr="Context.IntTy" for the int type.
+ string TypeExpr = _TypeExpr;
// Some QualTypes in this file represent an abstract type for which there is
// no corresponding AST QualType, e.g. a GenType or an `image2d_t` type
// without access qualifiers.
@@ -95,11 +118,11 @@
// OpenCL C basic data types (int, float, image2d_t, ...).
// Its child classes can represent concrete types (e.g. VectorType) or
// abstract types (e.g. GenType).
-class Type<string _Name, QualType _QTName> {
+class Type<string _Name, QualType _QTExpr> {
// Name of the Type.
string Name = _Name;
// QualType associated with this type.
- QualType QTName = _QTName;
+ QualType QTExpr = _QTExpr;
// Size of the vector (if applicable).
int VecWidth = 1;
// Is a pointer.
@@ -112,10 +135,12 @@
string AccessQualifier = "";
// Address space.
string AddrSpace = DefaultAS.Name;
+ // Extension that needs to be enabled to expose a builtin that uses this type.
+ TypeExtension Extension = NoTypeExt;
}
// OpenCL vector types (e.g. int2, int3, int16, float8, ...).
-class VectorType<Type _Ty, int _VecWidth> : Type<_Ty.Name, _Ty.QTName> {
+class VectorType<Type _Ty, int _VecWidth> : Type<_Ty.Name, _Ty.QTExpr> {
let VecWidth = _VecWidth;
let AccessQualifier = "";
// Inherited fields
@@ -123,11 +148,12 @@
let IsConst = _Ty.IsConst;
let IsVolatile = _Ty.IsVolatile;
let AddrSpace = _Ty.AddrSpace;
+ let Extension = _Ty.Extension;
}
// OpenCL pointer types (e.g. int*, float*, ...).
class PointerType<Type _Ty, AddressSpace _AS = DefaultAS> :
- Type<_Ty.Name, _Ty.QTName> {
+ Type<_Ty.Name, _Ty.QTExpr> {
let AddrSpace = _AS.Name;
// Inherited fields
let VecWidth = _Ty.VecWidth;
@@ -135,10 +161,11 @@
let IsConst = _Ty.IsConst;
let IsVolatile = _Ty.IsVolatile;
let AccessQualifier = _Ty.AccessQualifier;
+ let Extension = _Ty.Extension;
}
// OpenCL const types (e.g. const int).
-class ConstType<Type _Ty> : Type<_Ty.Name, _Ty.QTName> {
+class ConstType<Type _Ty> : Type<_Ty.Name, _Ty.QTExpr> {
let IsConst = 1;
// Inherited fields
let VecWidth = _Ty.VecWidth;
@@ -146,10 +173,11 @@
let IsVolatile = _Ty.IsVolatile;
let AccessQualifier = _Ty.AccessQualifier;
let AddrSpace = _Ty.AddrSpace;
+ let Extension = _Ty.Extension;
}
// OpenCL volatile types (e.g. volatile int).
-class VolatileType<Type _Ty> : Type<_Ty.Name, _Ty.QTName> {
+class VolatileType<Type _Ty> : Type<_Ty.Name, _Ty.QTExpr> {
let IsVolatile = 1;
// Inherited fields
let VecWidth = _Ty.VecWidth;
@@ -157,11 +185,12 @@
let IsConst = _Ty.IsConst;
let AccessQualifier = _Ty.AccessQualifier;
let AddrSpace = _Ty.AddrSpace;
+ let Extension = _Ty.Extension;
}
// OpenCL image types (e.g. image2d).
class ImageType<Type _Ty, string _AccessQualifier> :
- Type<_Ty.Name, QualType<_Ty.QTName.Name#_AccessQualifier#"Ty", 0>> {
+ Type<_Ty.Name, QualType<_Ty.QTExpr.TypeExpr # _AccessQualifier # "Ty", 0>> {
let VecWidth = 0;
let AccessQualifier = _AccessQualifier;
// Inherited fields
@@ -169,6 +198,17 @@
let IsConst = _Ty.IsConst;
let IsVolatile = _Ty.IsVolatile;
let AddrSpace = _Ty.AddrSpace;
+ let Extension = _Ty.Extension;
+}
+
+// OpenCL enum type (e.g. memory_scope).
+class EnumType<string _Name> :
+ Type<_Name, QualType<"getOpenCLEnumType(S, \"" # _Name # "\")", 0>> {
+}
+
+// OpenCL typedef type (e.g. cl_mem_fence_flags).
+class TypedefType<string _Name> :
+ Type<_Name, QualType<"getOpenCLTypedefType(S, \"" # _Name # "\")", 0>> {
}
// List of Types.
@@ -250,23 +290,27 @@
//===----------------------------------------------------------------------===//
// OpenCL v1.0/1.2/2.0 s6.1.1: Built-in Scalar Data Types.
-def Bool : Type<"bool", QualType<"BoolTy">>;
-def Char : Type<"char", QualType<"CharTy">>;
-def UChar : Type<"uchar", QualType<"UnsignedCharTy">>;
-def Short : Type<"short", QualType<"ShortTy">>;
-def UShort : Type<"ushort", QualType<"UnsignedShortTy">>;
-def Int : Type<"int", QualType<"IntTy">>;
-def UInt : Type<"uint", QualType<"UnsignedIntTy">>;
-def Long : Type<"long", QualType<"LongTy">>;
-def ULong : Type<"ulong", QualType<"UnsignedLongTy">>;
-def Float : Type<"float", QualType<"FloatTy">>;
-def Double : Type<"double", QualType<"DoubleTy">>;
-def Half : Type<"half", QualType<"HalfTy">>;
-def Size : Type<"size_t", QualType<"getSizeType()">>;
-def PtrDiff : Type<"ptrdiff_t", QualType<"getPointerDiffType()">>;
-def IntPtr : Type<"intptr_t", QualType<"getIntPtrType()">>;
-def UIntPtr : Type<"uintptr_t", QualType<"getUIntPtrType()">>;
-def Void : Type<"void", QualType<"VoidTy">>;
+def Bool : Type<"bool", QualType<"Context.BoolTy">>;
+def Char : Type<"char", QualType<"Context.CharTy">>;
+def UChar : Type<"uchar", QualType<"Context.UnsignedCharTy">>;
+def Short : Type<"short", QualType<"Context.ShortTy">>;
+def UShort : Type<"ushort", QualType<"Context.UnsignedShortTy">>;
+def Int : Type<"int", QualType<"Context.IntTy">>;
+def UInt : Type<"uint", QualType<"Context.UnsignedIntTy">>;
+def Long : Type<"long", QualType<"Context.LongTy">>;
+def ULong : Type<"ulong", QualType<"Context.UnsignedLongTy">>;
+def Float : Type<"float", QualType<"Context.FloatTy">>;
+let Extension = Fp64TypeExt in {
+ def Double : Type<"double", QualType<"Context.DoubleTy">>;
+}
+let Extension = Fp16TypeExt in {
+ def Half : Type<"half", QualType<"Context.HalfTy">>;
+}
+def Size : Type<"size_t", QualType<"Context.getSizeType()">>;
+def PtrDiff : Type<"ptrdiff_t", QualType<"Context.getPointerDiffType()">>;
+def IntPtr : Type<"intptr_t", QualType<"Context.getIntPtrType()">>;
+def UIntPtr : Type<"uintptr_t", QualType<"Context.getUIntPtrType()">>;
+def Void : Type<"void", QualType<"Context.VoidTy">>;
// OpenCL v1.0/1.2/2.0 s6.1.2: Built-in Vector Data Types.
// Built-in vector data types are created by TableGen's OpenCLBuiltinEmitter.
@@ -274,36 +318,43 @@
// OpenCL v1.0/1.2/2.0 s6.1.3: Other Built-in Data Types.
// The image definitions are "abstract". They should not be used without
// specifying an access qualifier (RO/WO/RW).
-def Image1d : Type<"image1d_t", QualType<"OCLImage1d", 1>>;
-def Image2d : Type<"image2d_t", QualType<"OCLImage2d", 1>>;
-def Image3d : Type<"image3d_t", QualType<"OCLImage3d", 1>>;
-def Image1dArray : Type<"image1d_array_t", QualType<"OCLImage1dArray", 1>>;
-def Image1dBuffer : Type<"image1d_buffer_t", QualType<"OCLImage1dBuffer", 1>>;
-def Image2dArray : Type<"image2d_array_t", QualType<"OCLImage2dArray", 1>>;
-def Image2dDepth : Type<"image2d_depth_t", QualType<"OCLImage2dDepth", 1>>;
-def Image2dArrayDepth : Type<"image2d_array_depth_t", QualType<"OCLImage2dArrayDepth", 1>>;
-def Image2dMsaa : Type<"image2d_msaa_t", QualType<"OCLImage2dMSAA", 1>>;
-def Image2dArrayMsaa : Type<"image2d_array_msaa_t", QualType<"OCLImage2dArrayMSAA", 1>>;
-def Image2dMsaaDepth : Type<"image2d_msaa_depth_t", QualType<"OCLImage2dMSAADepth", 1>>;
-def Image2dArrayMsaaDepth : Type<"image2d_array_msaa_depth_t", QualType<"OCLImage2dArrayMSAADepth", 1>>;
+def Image1d : Type<"image1d_t", QualType<"Context.OCLImage1d", 1>>;
+def Image2d : Type<"image2d_t", QualType<"Context.OCLImage2d", 1>>;
+def Image3d : Type<"image3d_t", QualType<"Context.OCLImage3d", 1>>;
+def Image1dArray : Type<"image1d_array_t", QualType<"Context.OCLImage1dArray", 1>>;
+def Image1dBuffer : Type<"image1d_buffer_t", QualType<"Context.OCLImage1dBuffer", 1>>;
+def Image2dArray : Type<"image2d_array_t", QualType<"Context.OCLImage2dArray", 1>>;
+def Image2dDepth : Type<"image2d_depth_t", QualType<"Context.OCLImage2dDepth", 1>>;
+def Image2dArrayDepth : Type<"image2d_array_depth_t", QualType<"Context.OCLImage2dArrayDepth", 1>>;
+def Image2dMsaa : Type<"image2d_msaa_t", QualType<"Context.OCLImage2dMSAA", 1>>;
+def Image2dArrayMsaa : Type<"image2d_array_msaa_t", QualType<"Context.OCLImage2dArrayMSAA", 1>>;
+def Image2dMsaaDepth : Type<"image2d_msaa_depth_t", QualType<"Context.OCLImage2dMSAADepth", 1>>;
+def Image2dArrayMsaaDepth : Type<"image2d_array_msaa_depth_t", QualType<"Context.OCLImage2dArrayMSAADepth", 1>>;
-def Sampler : Type<"sampler_t", QualType<"OCLSamplerTy">>;
-def ClkEvent : Type<"clk_event_t", QualType<"OCLClkEventTy">>;
-def Event : Type<"event_t", QualType<"OCLEventTy">>;
-def Queue : Type<"queue_t", QualType<"OCLQueueTy">>;
-def ReserveId : Type<"reserve_id_t", QualType<"OCLReserveIDTy">>;
+def Sampler : Type<"sampler_t", QualType<"Context.OCLSamplerTy">>;
+def ClkEvent : Type<"clk_event_t", QualType<"Context.OCLClkEventTy">>;
+def Event : Type<"event_t", QualType<"Context.OCLEventTy">>;
+def Queue : Type<"queue_t", QualType<"Context.OCLQueueTy">>;
+def ReserveId : Type<"reserve_id_t", QualType<"Context.OCLReserveIDTy">>;
+def MemFenceFlags : TypedefType<"cl_mem_fence_flags">;
+def ClkProfilingInfo : TypedefType<"clk_profiling_info">;
+def NDRange : TypedefType<"ndrange_t">;
// OpenCL v2.0 s6.13.11: Atomic integer and floating-point types.
-def AtomicInt : Type<"atomic_int", QualType<"getAtomicType(Context.IntTy)">>;
-def AtomicUInt : Type<"atomic_uint", QualType<"getAtomicType(Context.UnsignedIntTy)">>;
-def AtomicLong : Type<"atomic_long", QualType<"getAtomicType(Context.LongTy)">>;
-def AtomicULong : Type<"atomic_ulong", QualType<"getAtomicType(Context.UnsignedLongTy)">>;
-def AtomicFloat : Type<"atomic_float", QualType<"getAtomicType(Context.FloatTy)">>;
-def AtomicDouble : Type<"atomic_double", QualType<"getAtomicType(Context.DoubleTy)">>;
-def AtomicIntPtr : Type<"atomic_intptr_t", QualType<"getAtomicType(Context.getIntPtrType())">>;
-def AtomicUIntPtr : Type<"atomic_uintptr_t", QualType<"getAtomicType(Context.getUIntPtrType())">>;
-def AtomicSize : Type<"atomic_size_t", QualType<"getAtomicType(Context.getSizeType())">>;
-def AtomicPtrDiff : Type<"atomic_ptrdiff_t", QualType<"getAtomicType(Context.getPointerDiffType())">>;
+def AtomicInt : Type<"atomic_int", QualType<"Context.getAtomicType(Context.IntTy)">>;
+def AtomicUInt : Type<"atomic_uint", QualType<"Context.getAtomicType(Context.UnsignedIntTy)">>;
+def AtomicLong : Type<"atomic_long", QualType<"Context.getAtomicType(Context.LongTy)">>;
+def AtomicULong : Type<"atomic_ulong", QualType<"Context.getAtomicType(Context.UnsignedLongTy)">>;
+def AtomicFloat : Type<"atomic_float", QualType<"Context.getAtomicType(Context.FloatTy)">>;
+def AtomicDouble : Type<"atomic_double", QualType<"Context.getAtomicType(Context.DoubleTy)">>;
+def AtomicIntPtr : Type<"atomic_intptr_t", QualType<"Context.getAtomicType(Context.getIntPtrType())">>;
+def AtomicUIntPtr : Type<"atomic_uintptr_t", QualType<"Context.getAtomicType(Context.getUIntPtrType())">>;
+def AtomicSize : Type<"atomic_size_t", QualType<"Context.getAtomicType(Context.getSizeType())">>;
+def AtomicPtrDiff : Type<"atomic_ptrdiff_t", QualType<"Context.getAtomicType(Context.getPointerDiffType())">>;
+
+def AtomicFlag : TypedefType<"atomic_flag">;
+def MemoryOrder : EnumType<"memory_order">;
+def MemoryScope : EnumType<"memory_scope">;
//===----------------------------------------------------------------------===//
// Definitions of OpenCL gentype variants
@@ -319,15 +370,10 @@
def VecAndScalar: IntList<"VecAndScalar", [1, 2, 3, 4, 8, 16]>;
def VecNoScalar : IntList<"VecNoScalar", [2, 3, 4, 8, 16]>;
def Vec1 : IntList<"Vec1", [1]>;
-def Vec2 : IntList<"Vec2", [2]>;
-def Vec4 : IntList<"Vec4", [4]>;
-def Vec8 : IntList<"Vec8", [8]>;
-def Vec16 : IntList<"Vec16", [16]>;
def Vec1234 : IntList<"Vec1234", [1, 2, 3, 4]>;
// Type lists.
def TLAll : TypeList<[Char, UChar, Short, UShort, Int, UInt, Long, ULong, Float, Double, Half]>;
-def TLAllUnsigned : TypeList<[UChar, UChar, UShort, UShort, UInt, UInt, ULong, ULong, UInt, ULong, UShort]>;
def TLFloat : TypeList<[Float, Double, Half]>;
def TLSignedInts : TypeList<[Char, Short, Int, Long]>;
def TLUnsignedInts : TypeList<[UChar, UShort, UInt, ULong]>;
@@ -344,6 +390,7 @@
// GenType definitions for multiple base types (e.g. all floating point types,
// or all integer types).
// All types
+def AGenType1 : GenericType<"AGenType1", TLAll, Vec1>;
def AGenTypeN : GenericType<"AGenTypeN", TLAll, VecAndScalar>;
def AGenTypeNNoScalar : GenericType<"AGenTypeNNoScalar", TLAll, VecNoScalar>;
// All integer
@@ -360,6 +407,9 @@
def FGenTypeN : GenericType<"FGenTypeN", TLFloat, VecAndScalar>;
// (u)int, (u)long, and all floats
def IntLongFloatGenType1 : GenericType<"IntLongFloatGenType1", TLIntLongFloats, Vec1>;
+// (u)char and (u)short
+def CharShortGenType1 : GenericType<"CharShortGenType1",
+ TypeList<[Char, UChar, Short, UShort]>, Vec1>;
// GenType definitions for every single base type (e.g. fp32 only).
// Names are like: GenTypeFloatVecAndScalar.
@@ -551,12 +601,13 @@
foreach name = ["abs"] in {
def : Builtin<name, [AI2UGenTypeN, AIGenTypeN], Attr.Const>;
}
-foreach name = ["clz", "popcount"] in {
- def : Builtin<name, [AIGenTypeN, AIGenTypeN], Attr.Const>;
+def : Builtin<"clz", [AIGenTypeN, AIGenTypeN], Attr.Const>;
+let MinVersion = CL12 in {
+ def : Builtin<"popcount", [AIGenTypeN, AIGenTypeN], Attr.Const>;
}
let MinVersion = CL20 in {
foreach name = ["ctz"] in {
- def : Builtin<name, [AIGenTypeN, AIGenTypeN]>;
+ def : Builtin<name, [AIGenTypeN, AIGenTypeN], Attr.Const>;
}
}
@@ -623,12 +674,18 @@
}
// --- 3 arguments ---
-foreach name = ["clamp", "mix"] in {
+foreach name = ["clamp"] in {
def : Builtin<name, [FGenTypeN, FGenTypeN, FGenTypeN, FGenTypeN], Attr.Const>;
def : Builtin<name, [GenTypeFloatVecNoScalar, GenTypeFloatVecNoScalar, Float, Float], Attr.Const>;
def : Builtin<name, [GenTypeDoubleVecNoScalar, GenTypeDoubleVecNoScalar, Double, Double], Attr.Const>;
def : Builtin<name, [GenTypeHalfVecNoScalar, GenTypeHalfVecNoScalar, Half, Half], Attr.Const>;
}
+foreach name = ["mix"] in {
+ def : Builtin<name, [FGenTypeN, FGenTypeN, FGenTypeN, FGenTypeN], Attr.Const>;
+ def : Builtin<name, [GenTypeFloatVecNoScalar, GenTypeFloatVecNoScalar, GenTypeFloatVecNoScalar, Float], Attr.Const>;
+ def : Builtin<name, [GenTypeDoubleVecNoScalar, GenTypeDoubleVecNoScalar, GenTypeDoubleVecNoScalar, Double], Attr.Const>;
+ def : Builtin<name, [GenTypeHalfVecNoScalar, GenTypeHalfVecNoScalar, GenTypeHalfVecNoScalar, Half], Attr.Const>;
+}
foreach name = ["smoothstep"] in {
def : Builtin<name, [FGenTypeN, FGenTypeN, FGenTypeN, FGenTypeN], Attr.Const>;
def : Builtin<name, [GenTypeFloatVecNoScalar, Float, Float, GenTypeFloatVecNoScalar], Attr.Const>;
@@ -886,6 +943,29 @@
}
}
+// OpenCL v3.0 s6.15.8 - Synchronization Functions.
+def : Builtin<"barrier", [Void, MemFenceFlags], Attr.Convergent>;
+let MinVersion = CL20 in {
+ def : Builtin<"work_group_barrier", [Void, MemFenceFlags], Attr.Convergent>;
+ def : Builtin<"work_group_barrier", [Void, MemFenceFlags, MemoryScope], Attr.Convergent>;
+}
+
+// OpenCL v3.0 s6.15.9 - Legacy Explicit Memory Fence Functions.
+def : Builtin<"mem_fence", [Void, MemFenceFlags]>;
+def : Builtin<"read_mem_fence", [Void, MemFenceFlags]>;
+def : Builtin<"write_mem_fence", [Void, MemFenceFlags]>;
+
+// OpenCL v3.0 s6.15.10 - Address Space Qualifier Functions.
+// to_global, to_local, to_private are declared in Builtins.def.
+
+let MinVersion = CL20 in {
+ // The OpenCL 3.0 specification defines these with a "gentype" argument indicating any builtin
+ // type or user-defined type, which cannot be represented currently. Hence we slightly diverge
+ // by providing only the following overloads with a void pointer.
+ def : Builtin<"get_fence", [MemFenceFlags, PointerType<Void, GenericAS>]>;
+ def : Builtin<"get_fence", [MemFenceFlags, PointerType<ConstType<Void>, GenericAS>]>;
+}
+
//--------------------------------------------------------------------
// OpenCL v1.1 s6.11.10, v1.2 s6.12.10, v2.0 s6.13.10: Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch
// OpenCL Extension v2.0 s5.1.7 and s6.1.7: Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch
@@ -986,6 +1066,7 @@
}
// OpenCL v1.1 s6.11.1, v1.2 s6.12.11 - Atomic Functions
foreach AS = [GlobalAS, LocalAS] in {
+ def : Builtin<"atomic_xchg", [Float, PointerType<VolatileType<Float>, AS>, Float]>;
foreach Type = [Int, UInt] in {
foreach name = ["atomic_add", "atomic_sub", "atomic_xchg",
"atomic_min", "atomic_max", "atomic_and",
@@ -1000,8 +1081,27 @@
}
}
}
+
+let Extension = FuncExtOpenCLCxx in {
+ foreach Type = [Int, UInt] in {
+ foreach name = ["atomic_add", "atomic_sub", "atomic_xchg",
+ "atomic_min", "atomic_max", "atomic_and",
+ "atomic_or", "atomic_xor"] in {
+ def : Builtin<name, [Type, PointerType<VolatileType<Type>, GenericAS>, Type]>;
+ }
+ foreach name = ["atomic_inc", "atomic_dec"] in {
+ def : Builtin<name, [Type, PointerType<VolatileType<Type>, GenericAS>]>;
+ }
+ foreach name = ["atomic_cmpxchg"] in {
+ def : Builtin<name, [Type, PointerType<VolatileType<Type>, GenericAS>, Type, Type]>;
+ }
+ }
+}
+
// OpenCL v2.0 s6.13.11 - Atomic Functions.
let MinVersion = CL20 in {
+ def : Builtin<"atomic_work_item_fence", [Void, MemFenceFlags, MemoryOrder, MemoryScope]>;
+
foreach TypePair = [[AtomicInt, Int], [AtomicUInt, UInt],
[AtomicLong, Long], [AtomicULong, ULong],
[AtomicFloat, Float], [AtomicDouble, Double]] in {
@@ -1009,55 +1109,104 @@
[Void, PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[1]]>;
def : Builtin<"atomic_store",
[Void, PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[1]]>;
+ def : Builtin<"atomic_store_explicit",
+ [Void, PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[1], MemoryOrder]>;
+ def : Builtin<"atomic_store_explicit",
+ [Void, PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[1], MemoryOrder, MemoryScope]>;
def : Builtin<"atomic_load",
[TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>]>;
+ def : Builtin<"atomic_load_explicit",
+ [TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, MemoryOrder]>;
+ def : Builtin<"atomic_load_explicit",
+ [TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, MemoryOrder, MemoryScope]>;
def : Builtin<"atomic_exchange",
[TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[1]]>;
+ def : Builtin<"atomic_exchange_explicit",
+ [TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[1], MemoryOrder]>;
+ def : Builtin<"atomic_exchange_explicit",
+ [TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[1], MemoryOrder, MemoryScope]>;
foreach Variant = ["weak", "strong"] in {
def : Builtin<"atomic_compare_exchange_" # Variant,
[Bool, PointerType<VolatileType<TypePair[0]>, GenericAS>,
PointerType<TypePair[1], GenericAS>, TypePair[1]]>;
+ def : Builtin<"atomic_compare_exchange_" # Variant # "_explicit",
+ [Bool, PointerType<VolatileType<TypePair[0]>, GenericAS>,
+ PointerType<TypePair[1], GenericAS>, TypePair[1], MemoryOrder, MemoryOrder]>;
+ def : Builtin<"atomic_compare_exchange_" # Variant # "_explicit",
+ [Bool, PointerType<VolatileType<TypePair[0]>, GenericAS>,
+ PointerType<TypePair[1], GenericAS>, TypePair[1], MemoryOrder, MemoryOrder, MemoryScope]>;
}
}
foreach TypePair = [[AtomicInt, Int, Int], [AtomicUInt, UInt, UInt],
[AtomicLong, Long, Long], [AtomicULong, ULong, ULong],
- [AtomicIntPtr, IntPtr, PtrDiff],
[AtomicUIntPtr, UIntPtr, PtrDiff]] in {
foreach ModOp = ["add", "sub"] in {
def : Builtin<"atomic_fetch_" # ModOp,
[TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[2]]>;
+ def : Builtin<"atomic_fetch_" # ModOp # "_explicit",
+ [TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[2], MemoryOrder]>;
+ def : Builtin<"atomic_fetch_" # ModOp # "_explicit",
+ [TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[2], MemoryOrder, MemoryScope]>;
}
}
foreach TypePair = [[AtomicInt, Int, Int], [AtomicUInt, UInt, UInt],
- [AtomicLong, Long, Long], [AtomicULong, ULong, ULong],
- [AtomicIntPtr, IntPtr, IntPtr],
- [AtomicUIntPtr, UIntPtr, UIntPtr]] in {
+ [AtomicLong, Long, Long], [AtomicULong, ULong, ULong]] in {
foreach ModOp = ["or", "xor", "and", "min", "max"] in {
def : Builtin<"atomic_fetch_" # ModOp,
[TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[2]]>;
+ def : Builtin<"atomic_fetch_" # ModOp # "_explicit",
+ [TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[2], MemoryOrder]>;
+ def : Builtin<"atomic_fetch_" # ModOp # "_explicit",
+ [TypePair[1], PointerType<VolatileType<TypePair[0]>, GenericAS>, TypePair[2], MemoryOrder, MemoryScope]>;
}
}
+
+ def : Builtin<"atomic_flag_clear",
+ [Void, PointerType<VolatileType<AtomicFlag>, GenericAS>]>;
+ def : Builtin<"atomic_flag_clear_explicit",
+ [Void, PointerType<VolatileType<AtomicFlag>, GenericAS>, MemoryOrder]>;
+ def : Builtin<"atomic_flag_clear_explicit",
+ [Void, PointerType<VolatileType<AtomicFlag>, GenericAS>, MemoryOrder, MemoryScope]>;
+
+ def : Builtin<"atomic_flag_test_and_set",
+ [Bool, PointerType<VolatileType<AtomicFlag>, GenericAS>]>;
+ def : Builtin<"atomic_flag_test_and_set_explicit",
+ [Bool, PointerType<VolatileType<AtomicFlag>, GenericAS>, MemoryOrder]>;
+ def : Builtin<"atomic_flag_test_and_set_explicit",
+ [Bool, PointerType<VolatileType<AtomicFlag>, GenericAS>, MemoryOrder, MemoryScope]>;
}
//--------------------------------------------------------------------
// OpenCL v1.1 s6.11.12, v1.2 s6.12.12, v2.0 s6.13.12 - Miscellaneous Vector Functions
// --- Table 19 ---
-foreach VSize1 = [Vec2, Vec4, Vec8, Vec16] in {
- foreach VSize2 = [Vec2, Vec4, Vec8, Vec16] in {
- def : Builtin<"shuffle", [GenericType<"TLAll" # VSize1.Name, TLAll, VSize1>,
- GenericType<"TLAll" # VSize2.Name, TLAll, VSize2>,
- GenericType<"TLAllUnsigned" # VSize1.Name, TLAllUnsigned, VSize1>],
- Attr.Const>;
+foreach VSize1 = [2, 4, 8, 16] in {
+ foreach VSize2 = [2, 4, 8, 16] in {
+ foreach VecAndMaskType = [[Char, UChar], [UChar, UChar],
+ [Short, UShort], [UShort, UShort],
+ [Int, UInt], [UInt, UInt],
+ [Long, ULong], [ULong, ULong],
+ [Float, UInt], [Double, ULong], [Half, UShort]] in {
+ def : Builtin<"shuffle", [VectorType<VecAndMaskType[0], VSize1>,
+ VectorType<VecAndMaskType[0], VSize2>,
+ VectorType<VecAndMaskType[1], VSize1>],
+ Attr.Const>;
+ }
}
}
-foreach VSize1 = [Vec2, Vec4, Vec8, Vec16] in {
- foreach VSize2 = [Vec2, Vec4, Vec8, Vec16] in {
- def : Builtin<"shuffle2", [GenericType<"TLAll" # VSize1.Name, TLAll, VSize1>,
- GenericType<"TLAll" # VSize2.Name, TLAll, VSize2>,
- GenericType<"TLAll" # VSize2.Name, TLAll, VSize2>,
- GenericType<"TLAllUnsigned" # VSize1.Name, TLAllUnsigned, VSize1>],
- Attr.Const>;
+foreach VSize1 = [2, 4, 8, 16] in {
+ foreach VSize2 = [2, 4, 8, 16] in {
+ foreach VecAndMaskType = [[Char, UChar], [UChar, UChar],
+ [Short, UShort], [UShort, UShort],
+ [Int, UInt], [UInt, UInt],
+ [Long, ULong], [ULong, ULong],
+ [Float, UInt], [Double, ULong], [Half, UShort]] in {
+ def : Builtin<"shuffle2", [VectorType<VecAndMaskType[0], VSize1>,
+ VectorType<VecAndMaskType[0], VSize2>,
+ VectorType<VecAndMaskType[0], VSize2>,
+ VectorType<VecAndMaskType[1], VSize1>],
+ Attr.Const>;
+ }
}
}
@@ -1092,24 +1241,26 @@
}
// --- Table 23: Sampler-less Read Functions ---
-foreach aQual = ["RO", "RW"] in {
- foreach imgTy = [Image2d, Image1dArray] in {
- def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
- def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
- def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
+let MinVersion = CL12 in {
+ foreach aQual = ["RO", "RW"] in {
+ foreach imgTy = [Image2d, Image1dArray] in {
+ def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
+ def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
+ def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
+ }
+ foreach imgTy = [Image3d, Image2dArray] in {
+ def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
+ def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
+ def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
+ }
+ foreach imgTy = [Image1d, Image1dBuffer] in {
+ def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
+ def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
+ def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
+ }
+ def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, aQual>, VectorType<Int, 2>], Attr.Pure>;
+ def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, aQual>, VectorType<Int, 4>], Attr.Pure>;
}
- foreach imgTy = [Image3d, Image2dArray] in {
- def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
- def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
- def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
- }
- foreach imgTy = [Image1d, Image1dBuffer] in {
- def : Builtin<"read_imagef", [VectorType<Float, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
- def : Builtin<"read_imagei", [VectorType<Int, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
- def : Builtin<"read_imageui", [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
- }
- def : Builtin<"read_imagef", [Float, ImageType<Image2dDepth, aQual>, VectorType<Int, 2>], Attr.Pure>;
- def : Builtin<"read_imagef", [Float, ImageType<Image2dArrayDepth, aQual>, VectorType<Int, 4>], Attr.Pure>;
}
// --- Table 24: Image Write Functions ---
@@ -1150,21 +1301,21 @@
Image2dArrayDepth] in {
foreach name = ["get_image_width", "get_image_channel_data_type",
"get_image_channel_order"] in {
- def : Builtin<name, [Int, ImageType<imgTy, aQual>]>;
+ def : Builtin<name, [Int, ImageType<imgTy, aQual>], Attr.Const>;
}
}
foreach imgTy = [Image2d, Image3d, Image2dArray, Image2dDepth,
Image2dArrayDepth] in {
- def : Builtin<"get_image_height", [Int, ImageType<imgTy, aQual>]>;
+ def : Builtin<"get_image_height", [Int, ImageType<imgTy, aQual>], Attr.Const>;
}
- def : Builtin<"get_image_depth", [Int, ImageType<Image3d, aQual>]>;
+ def : Builtin<"get_image_depth", [Int, ImageType<Image3d, aQual>], Attr.Const>;
foreach imgTy = [Image2d, Image2dArray, Image2dDepth,
Image2dArrayDepth] in {
- def : Builtin<"get_image_dim", [VectorType<Int, 2>, ImageType<imgTy, aQual>]>;
+ def : Builtin<"get_image_dim", [VectorType<Int, 2>, ImageType<imgTy, aQual>], Attr.Const>;
}
- def : Builtin<"get_image_dim", [VectorType<Int, 4>, ImageType<Image3d, aQual>]>;
+ def : Builtin<"get_image_dim", [VectorType<Int, 4>, ImageType<Image3d, aQual>], Attr.Const>;
foreach imgTy = [Image1dArray, Image2dArray, Image2dArrayDepth] in {
- def : Builtin<"get_image_array_size", [Size, ImageType<imgTy, aQual>]>;
+ def : Builtin<"get_image_array_size", [Size, ImageType<imgTy, aQual>], Attr.Const>;
}
}
@@ -1187,16 +1338,18 @@
}
// OpenCL extension v2.0 s5.1.10: Built-in Image Sampler-less Read Functions
// --- Table 9 ---
-foreach aQual = ["RO", "RW"] in {
- foreach name = ["read_imageh"] in {
- foreach imgTy = [Image2d, Image1dArray] in {
- def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
- }
- foreach imgTy = [Image3d, Image2dArray] in {
- def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
- }
- foreach imgTy = [Image1d, Image1dBuffer] in {
- def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
+let MinVersion = CL12 in {
+ foreach aQual = ["RO", "RW"] in {
+ foreach name = ["read_imageh"] in {
+ foreach imgTy = [Image2d, Image1dArray] in {
+ def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 2>], Attr.Pure>;
+ }
+ foreach imgTy = [Image3d, Image2dArray] in {
+ def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, VectorType<Int, 4>], Attr.Pure>;
+ }
+ foreach imgTy = [Image1d, Image1dBuffer] in {
+ def : Builtin<name, [VectorType<Half, 4>, ImageType<imgTy, aQual>, Int], Attr.Pure>;
+ }
}
}
}
@@ -1257,20 +1410,38 @@
// Defined in Builtins.def
// --- Table 33 ---
-def : Builtin<"enqueue_marker",
- [Int, Queue, UInt, PointerType<ConstType<ClkEvent>, GenericAS>, PointerType<ClkEvent, GenericAS>]>;
+let MinVersion = CL20 in {
+ def : Builtin<"enqueue_marker",
+ [Int, Queue, UInt, PointerType<ConstType<ClkEvent>, GenericAS>, PointerType<ClkEvent, GenericAS>]>;
-// --- Table 34 ---
-def : Builtin<"retain_event", [Void, ClkEvent]>;
-def : Builtin<"release_event", [Void, ClkEvent]>;
-def : Builtin<"create_user_event", [ClkEvent]>;
-def : Builtin<"is_valid_event", [Bool, ClkEvent]>;
-def : Builtin<"set_user_event_status", [Void, ClkEvent, Int]>;
-// TODO: capture_event_profiling_info
+ // --- Table 34 ---
+ def : Builtin<"retain_event", [Void, ClkEvent]>;
+ def : Builtin<"release_event", [Void, ClkEvent]>;
+ def : Builtin<"create_user_event", [ClkEvent]>;
+ def : Builtin<"is_valid_event", [Bool, ClkEvent]>;
+ def : Builtin<"set_user_event_status", [Void, ClkEvent, Int]>;
+ def : Builtin<"capture_event_profiling_info",
+ [Void, ClkEvent, ClkProfilingInfo, PointerType<Void, GlobalAS>]>;
-// --- Table 35 ---
-def : Builtin<"get_default_queue", [Queue]>;
-// TODO: ndrange functions
+ // --- Table 35 ---
+ def : Builtin<"get_default_queue", [Queue]>;
+
+ def : Builtin<"ndrange_1D", [NDRange, Size]>;
+ def : Builtin<"ndrange_1D", [NDRange, Size, Size]>;
+ def : Builtin<"ndrange_1D", [NDRange, Size, Size, Size]>;
+ def : Builtin<"ndrange_2D", [NDRange, PointerType<ConstType<Size>, PrivateAS>]>;
+ def : Builtin<"ndrange_2D", [NDRange, PointerType<ConstType<Size>, PrivateAS>,
+ PointerType<ConstType<Size>, PrivateAS>]>;
+ def : Builtin<"ndrange_2D", [NDRange, PointerType<ConstType<Size>, PrivateAS>,
+ PointerType<ConstType<Size>, PrivateAS>,
+ PointerType<ConstType<Size>, PrivateAS>]>;
+ def : Builtin<"ndrange_3D", [NDRange, PointerType<ConstType<Size>, PrivateAS>]>;
+ def : Builtin<"ndrange_3D", [NDRange, PointerType<ConstType<Size>, PrivateAS>,
+ PointerType<ConstType<Size>, PrivateAS>]>;
+ def : Builtin<"ndrange_3D", [NDRange, PointerType<ConstType<Size>, PrivateAS>,
+ PointerType<ConstType<Size>, PrivateAS>,
+ PointerType<ConstType<Size>, PrivateAS>]>;
+}
//--------------------------------------------------------------------
@@ -1324,11 +1495,11 @@
}
foreach name = ["read_imagei"] in {
def : Builtin<name, [VectorType<Int, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, VectorType<Float, 4>, VectorType<Float, 4>], Attr.Pure>;
- def : Builtin<name, [VectorType<Float, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, Float], Attr.Pure>;
+ def : Builtin<name, [VectorType<Int, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, Float], Attr.Pure>;
}
foreach name = ["read_imageui"] in {
def : Builtin<name, [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, VectorType<Float, 4>, VectorType<Float, 4>], Attr.Pure>;
- def : Builtin<name, [VectorType<Float, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, Float], Attr.Pure>;
+ def : Builtin<name, [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, Float], Attr.Pure>;
}
}
foreach imgTy = [Image1dArray] in {
@@ -1361,8 +1532,8 @@
}
foreach imgTy = [Image2dArrayDepth] in {
foreach name = ["read_imagef"] in {
- def : Builtin<name, [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, Float], Attr.Pure>;
- def : Builtin<name, [VectorType<UInt, 4>, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, VectorType<Float, 2>, VectorType<Float, 2>], Attr.Pure>;
+ def : Builtin<name, [Float, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, Float], Attr.Pure>;
+ def : Builtin<name, [Float, ImageType<imgTy, aQual>, Sampler, VectorType<Float, 4>, VectorType<Float, 2>, VectorType<Float, 2>], Attr.Pure>;
}
}
}
@@ -1464,7 +1635,10 @@
}
// --- Table 28.2.2 ---
-// TODO: sub_group_barrier
+let Extension = FuncExtKhrSubgroups in {
+ def : Builtin<"sub_group_barrier", [Void, MemFenceFlags], Attr.Convergent>;
+ def : Builtin<"sub_group_barrier", [Void, MemFenceFlags, MemoryScope], Attr.Convergent>;
+}
// --- Table 28.2.4 ---
let Extension = FuncExtKhrSubgroups in {
@@ -1482,6 +1656,124 @@
}
}
+// OpenCL Extension v3.0 s38 - Extended Subgroup Functions
+
+// Section 38.4.1 - cl_khr_subgroup_extended_types
+let Extension = FuncExtKhrSubgroupExtendedTypes in {
+ // For sub_group_broadcast, add scalar char, uchar, short, and ushort support,
+ def : Builtin<"sub_group_broadcast", [CharShortGenType1, CharShortGenType1, UInt], Attr.Convergent>;
+ // gentype may additionally be one of the supported built-in vector data types.
+ def : Builtin<"sub_group_broadcast", [AGenTypeNNoScalar, AGenTypeNNoScalar, UInt], Attr.Convergent>;
+
+ foreach name = ["sub_group_reduce_", "sub_group_scan_exclusive_",
+ "sub_group_scan_inclusive_"] in {
+ foreach op = ["add", "min", "max"] in {
+ def : Builtin<name # op, [CharShortGenType1, CharShortGenType1], Attr.Convergent>;
+ }
+ }
+}
+
+// Section 38.5.1 - cl_khr_subgroup_non_uniform_vote
+let Extension = FuncExtKhrSubgroupNonUniformVote in {
+ def : Builtin<"sub_group_elect", [Int]>;
+ def : Builtin<"sub_group_non_uniform_all", [Int, Int]>;
+ def : Builtin<"sub_group_non_uniform_any", [Int, Int]>;
+ def : Builtin<"sub_group_non_uniform_all_equal", [Int, AGenType1]>;
+}
+
+// Section 38.6.1 - cl_khr_subgroup_ballot
+let Extension = FuncExtKhrSubgroupBallot in {
+ def : Builtin<"sub_group_non_uniform_broadcast", [AGenTypeN, AGenTypeN, UInt]>;
+ def : Builtin<"sub_group_broadcast_first", [AGenType1, AGenType1]>;
+ def : Builtin<"sub_group_ballot", [VectorType<UInt, 4>, Int]>;
+ def : Builtin<"sub_group_inverse_ballot", [Int, VectorType<UInt, 4>], Attr.Const>;
+ def : Builtin<"sub_group_ballot_bit_extract", [Int, VectorType<UInt, 4>, UInt], Attr.Const>;
+ def : Builtin<"sub_group_ballot_bit_count", [UInt, VectorType<UInt, 4>], Attr.Const>;
+ def : Builtin<"sub_group_ballot_inclusive_scan", [UInt, VectorType<UInt, 4>]>;
+ def : Builtin<"sub_group_ballot_exclusive_scan", [UInt, VectorType<UInt, 4>]>;
+ def : Builtin<"sub_group_ballot_find_lsb", [UInt, VectorType<UInt, 4>]>;
+ def : Builtin<"sub_group_ballot_find_msb", [UInt, VectorType<UInt, 4>]>;
+
+ foreach op = ["eq", "ge", "gt", "le", "lt"] in {
+ def : Builtin<"get_sub_group_" # op # "_mask", [VectorType<UInt, 4>], Attr.Const>;
+ }
+}
+
+// Section 38.7.1 - cl_khr_subgroup_non_uniform_arithmetic
+let Extension = FuncExtKhrSubgroupNonUniformArithmetic in {
+ foreach name = ["reduce_", "scan_exclusive_", "scan_inclusive_"] in {
+ foreach op = ["add", "min", "max", "mul"] in {
+ def : Builtin<"sub_group_non_uniform_" # name # op, [AGenType1, AGenType1]>;
+ }
+ foreach op = ["and", "or", "xor"] in {
+ def : Builtin<"sub_group_non_uniform_" # name # op, [AIGenType1, AIGenType1]>;
+ }
+ foreach op = ["and", "or", "xor"] in {
+ def : Builtin<"sub_group_non_uniform_" # name # "logical_" # op, [Int, Int]>;
+ }
+ }
+}
+
+// Section 38.8.1 - cl_khr_subgroup_shuffle
+let Extension = FuncExtKhrSubgroupShuffle in {
+ def : Builtin<"sub_group_shuffle", [AGenType1, AGenType1, UInt]>;
+ def : Builtin<"sub_group_shuffle_xor", [AGenType1, AGenType1, UInt]>;
+}
+
+// Section 38.9.1 - cl_khr_subgroup_shuffle_relative
+let Extension = FuncExtKhrSubgroupShuffleRelative in {
+ def : Builtin<"sub_group_shuffle_up", [AGenType1, AGenType1, UInt]>;
+ def : Builtin<"sub_group_shuffle_down", [AGenType1, AGenType1, UInt]>;
+}
+
+// Section 38.10.1 - cl_khr_subgroup_clustered_reduce
+let Extension = FuncExtKhrSubgroupClusteredReduce in {
+ foreach op = ["add", "min", "max", "mul"] in {
+ def : Builtin<"sub_group_clustered_reduce_" # op, [AGenType1, AGenType1, UInt]>;
+ }
+ foreach op = ["and", "or", "xor"] in {
+ def : Builtin<"sub_group_clustered_reduce_" # op, [AIGenType1, AIGenType1, UInt]>;
+ }
+ foreach op = ["and", "or", "xor"] in {
+ def : Builtin<"sub_group_clustered_reduce_logical_" # op, [Int, Int, UInt]>;
+ }
+}
+
+// Section 40.3.1 - cl_khr_extended_bit_ops
+let Extension = FuncExtKhrExtendedBitOps in {
+ def : Builtin<"bitfield_insert", [AIGenTypeN, AIGenTypeN, AIGenTypeN, UInt, UInt], Attr.Const>;
+ def : Builtin<"bitfield_extract_signed", [SGenTypeN, SGenTypeN, UInt, UInt], Attr.Const>;
+ def : Builtin<"bitfield_extract_signed", [SGenTypeN, UGenTypeN, UInt, UInt], Attr.Const>;
+ def : Builtin<"bitfield_extract_unsigned", [UGenTypeN, SGenTypeN, UInt, UInt], Attr.Const>;
+ def : Builtin<"bitfield_extract_unsigned", [UGenTypeN, UGenTypeN, UInt, UInt], Attr.Const>;
+ def : Builtin<"bit_reverse", [AIGenTypeN, AIGenTypeN], Attr.Const>;
+}
+
+// Section 42.3 - cl_khr_integer_dot_product
+let Extension = FunctionExtension<"__opencl_c_integer_dot_product_input_4x8bit"> in {
+ def : Builtin<"dot", [UInt, VectorType<UChar, 4>, VectorType<UChar, 4>], Attr.Const>;
+ def : Builtin<"dot", [Int, VectorType<Char, 4>, VectorType<Char, 4>], Attr.Const>;
+ def : Builtin<"dot", [Int, VectorType<UChar, 4>, VectorType<Char, 4>], Attr.Const>;
+ def : Builtin<"dot", [Int, VectorType<Char, 4>, VectorType<UChar, 4>], Attr.Const>;
+
+ def : Builtin<"dot_acc_sat", [UInt, VectorType<UChar, 4>, VectorType<UChar, 4>, UInt], Attr.Const>;
+ def : Builtin<"dot_acc_sat", [Int, VectorType<Char, 4>, VectorType<Char, 4>, Int], Attr.Const>;
+ def : Builtin<"dot_acc_sat", [Int, VectorType<UChar, 4>, VectorType<Char, 4>, Int], Attr.Const>;
+ def : Builtin<"dot_acc_sat", [Int, VectorType<Char, 4>, VectorType<UChar, 4>, Int], Attr.Const>;
+}
+
+let Extension = FunctionExtension<"__opencl_c_integer_dot_product_input_4x8bit_packed"> in {
+ def : Builtin<"dot_4x8packed_uu_uint", [UInt, UInt, UInt], Attr.Const>;
+ def : Builtin<"dot_4x8packed_ss_int", [Int, UInt, UInt], Attr.Const>;
+ def : Builtin<"dot_4x8packed_us_int", [Int, UInt, UInt], Attr.Const>;
+ def : Builtin<"dot_4x8packed_su_int", [Int, UInt, UInt], Attr.Const>;
+
+ def : Builtin<"dot_acc_sat_4x8packed_uu_uint", [UInt, UInt, UInt, UInt], Attr.Const>;
+ def : Builtin<"dot_acc_sat_4x8packed_ss_int", [Int, UInt, UInt, Int], Attr.Const>;
+ def : Builtin<"dot_acc_sat_4x8packed_us_int", [Int, UInt, UInt, Int], Attr.Const>;
+ def : Builtin<"dot_acc_sat_4x8packed_su_int", [Int, UInt, UInt, Int], Attr.Const>;
+}
+
//--------------------------------------------------------------------
// Arm extensions.
let Extension = ArmIntegerDotProductInt8 in {
diff --git a/src/llvm-project/clang/lib/Sema/ParsedAttr.cpp b/src/llvm-project/clang/lib/Sema/ParsedAttr.cpp
index 3ef8498..ed03b0c 100644
--- a/src/llvm-project/clang/lib/Sema/ParsedAttr.cpp
+++ b/src/llvm-project/clang/lib/Sema/ParsedAttr.cpp
@@ -159,6 +159,14 @@
return getInfo().diagAppertainsToDecl(S, *this, D);
}
+bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
+ return getInfo().diagAppertainsToStmt(S, *this, St);
+}
+
+bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
+ return getInfo().diagMutualExclusion(S, *this, D);
+}
+
bool ParsedAttr::appliesToDecl(const Decl *D,
attr::SubjectMatchRule MatchRule) const {
return checkAttributeMatchRuleAppliesTo(D, MatchRule);
@@ -204,3 +212,35 @@
// whether it's truly variadic or not.
return getInfo().OptArgs == 15;
}
+
+static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
+ // FIXME: Include the type in the argument list.
+ return AL.getNumArgs() + AL.hasParsedType();
+}
+
+template <typename Compare>
+static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
+ unsigned Num, unsigned Diag,
+ Compare Comp) {
+ if (Comp(getNumAttributeArgs(AL), Num)) {
+ S.Diag(AL.getLoc(), Diag) << AL << Num;
+ return false;
+ }
+ return true;
+}
+
+bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
+ return checkAttributeNumArgsImpl(S, *this, Num,
+ diag::err_attribute_wrong_number_arguments,
+ std::not_equal_to<unsigned>());
+}
+bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
+ return checkAttributeNumArgsImpl(S, *this, Num,
+ diag::err_attribute_too_few_arguments,
+ std::less<unsigned>());
+}
+bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
+ return checkAttributeNumArgsImpl(S, *this, Num,
+ diag::err_attribute_too_many_arguments,
+ std::greater<unsigned>());
+}
diff --git a/src/llvm-project/clang/lib/Sema/Sema.cpp b/src/llvm-project/clang/lib/Sema/Sema.cpp
index 450f9c0..a54bd87 100644
--- a/src/llvm-project/clang/lib/Sema/Sema.cpp
+++ b/src/llvm-project/clang/lib/Sema/Sema.cpp
@@ -22,12 +22,14 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/StmtCXX.h"
+#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DelayedDiagnostic.h"
@@ -55,6 +57,26 @@
ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
+DarwinSDKInfo *
+Sema::getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
+ StringRef Platform) {
+ if (CachedDarwinSDKInfo)
+ return CachedDarwinSDKInfo->get();
+ auto SDKInfo = parseDarwinSDKInfo(
+ PP.getFileManager().getVirtualFileSystem(),
+ PP.getHeaderSearchInfo().getHeaderSearchOpts().Sysroot);
+ if (SDKInfo && *SDKInfo) {
+ CachedDarwinSDKInfo = std::make_unique<DarwinSDKInfo>(std::move(**SDKInfo));
+ return CachedDarwinSDKInfo->get();
+ }
+ if (!SDKInfo)
+ llvm::consumeError(SDKInfo.takeError());
+ Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking)
+ << Platform;
+ CachedDarwinSDKInfo = std::unique_ptr<DarwinSDKInfo>();
+ return nullptr;
+}
+
IdentifierInfo *
Sema::InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
unsigned int Index) {
@@ -183,6 +205,7 @@
DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
+ assert(pp.TUKind == TUKind);
TUScope = nullptr;
isConstantEvaluatedOverride = false;
@@ -299,35 +322,22 @@
if (getLangOpts().OpenCL) {
getOpenCLOptions().addSupport(
Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts());
- getOpenCLOptions().enableSupportedCore(getLangOpts());
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) {
addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
addImplicitTypedef("queue_t", Context.OCLQueueTy);
- addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
+ if (getLangOpts().OpenCLPipes)
+ addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
addImplicitTypedef("atomic_uint",
Context.getAtomicType(Context.UnsignedIntTy));
- auto AtomicLongT = Context.getAtomicType(Context.LongTy);
- addImplicitTypedef("atomic_long", AtomicLongT);
- auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
- addImplicitTypedef("atomic_ulong", AtomicULongT);
addImplicitTypedef("atomic_float",
Context.getAtomicType(Context.FloatTy));
- auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy);
- addImplicitTypedef("atomic_double", AtomicDoubleT);
// OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as
// 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide.
addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));
- auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
- addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
- auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
- addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
- auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
- addImplicitTypedef("atomic_size_t", AtomicSizeT);
- auto AtomicPtrDiffT = Context.getAtomicType(Context.getPointerDiffType());
- addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
+
// OpenCL v2.0 s6.13.11.6:
// - The atomic_long and atomic_ulong types are supported if the
@@ -340,31 +350,50 @@
// atomic_intptr_t, atomic_uintptr_t, atomic_size_t and
// atomic_ptrdiff_t are supported if the cl_khr_int64_base_atomics and
// cl_khr_int64_extended_atomics extensions are supported.
- std::vector<QualType> Atomic64BitTypes;
- Atomic64BitTypes.push_back(AtomicLongT);
- Atomic64BitTypes.push_back(AtomicULongT);
- Atomic64BitTypes.push_back(AtomicDoubleT);
- if (Context.getTypeSize(AtomicSizeT) == 64) {
- Atomic64BitTypes.push_back(AtomicSizeT);
- Atomic64BitTypes.push_back(AtomicIntPtrT);
- Atomic64BitTypes.push_back(AtomicUIntPtrT);
- Atomic64BitTypes.push_back(AtomicPtrDiffT);
- }
- for (auto &I : Atomic64BitTypes)
- setOpenCLExtensionForType(I,
- "cl_khr_int64_base_atomics cl_khr_int64_extended_atomics");
- setOpenCLExtensionForType(AtomicDoubleT, "cl_khr_fp64");
+ auto AddPointerSizeDependentTypes = [&]() {
+ auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
+ auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
+ auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
+ auto AtomicPtrDiffT =
+ Context.getAtomicType(Context.getPointerDiffType());
+ addImplicitTypedef("atomic_size_t", AtomicSizeT);
+ addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
+ addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
+ addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
+ };
+
+ if (Context.getTypeSize(Context.getSizeType()) == 32) {
+ AddPointerSizeDependentTypes();
+ }
+
+ std::vector<QualType> Atomic64BitTypes;
+ if (getOpenCLOptions().isSupported("cl_khr_int64_base_atomics",
+ getLangOpts()) &&
+ getOpenCLOptions().isSupported("cl_khr_int64_extended_atomics",
+ getLangOpts())) {
+ if (getOpenCLOptions().isSupported("cl_khr_fp64", getLangOpts())) {
+ auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy);
+ addImplicitTypedef("atomic_double", AtomicDoubleT);
+ Atomic64BitTypes.push_back(AtomicDoubleT);
+ }
+ auto AtomicLongT = Context.getAtomicType(Context.LongTy);
+ auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
+ addImplicitTypedef("atomic_long", AtomicLongT);
+ addImplicitTypedef("atomic_ulong", AtomicULongT);
+
+
+ if (Context.getTypeSize(Context.getSizeType()) == 64) {
+ AddPointerSizeDependentTypes();
+ }
+ }
}
- setOpenCLExtensionForType(Context.DoubleTy, "cl_khr_fp64");
-#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \
- setOpenCLExtensionForType(Context.Id, Ext);
-#include "clang/Basic/OpenCLImageTypes.def"
-#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
- addImplicitTypedef(#ExtType, Context.Id##Ty); \
- setOpenCLExtensionForType(Context.Id##Ty, #Ext);
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
+ if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) { \
+ addImplicitTypedef(#ExtType, Context.Id##Ty); \
+ }
#include "clang/Basic/OpenCLExtensionTypes.def"
}
@@ -386,6 +415,12 @@
#include "clang/Basic/PPCTypes.def"
}
+ if (Context.getTargetInfo().hasRISCVVTypes()) {
+#define RVV_TYPE(Name, Id, SingletonId) \
+ addImplicitTypedef(Name, Context.SingletonId);
+#include "clang/Basic/RISCVVTypes.def"
+ }
+
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
if (IdResolver.begin(MSVaList) == IdResolver.end())
@@ -565,13 +600,14 @@
const CXXCastPath *BasePath,
CheckedConversionKind CCK) {
#ifndef NDEBUG
- if (VK == VK_RValue && !E->isRValue()) {
+ if (VK == VK_PRValue && !E->isPRValue()) {
switch (Kind) {
default:
- llvm_unreachable(("can't implicitly cast lvalue to rvalue with this cast "
- "kind: " +
- std::string(CastExpr::getCastKindName(Kind)))
- .c_str());
+ llvm_unreachable(
+ ("can't implicitly cast glvalue to prvalue with this cast "
+ "kind: " +
+ std::string(CastExpr::getCastKindName(Kind)))
+ .c_str());
case CK_Dependent:
case CK_LValueToRValue:
case CK_ArrayToPointerDecay:
@@ -581,8 +617,8 @@
break;
}
}
- assert((VK == VK_RValue || Kind == CK_Dependent || !E->isRValue()) &&
- "can't cast rvalue to lvalue");
+ assert((VK == VK_PRValue || Kind == CK_Dependent || !E->isPRValue()) &&
+ "can't cast prvalue to glvalue");
#endif
diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc());
@@ -594,16 +630,36 @@
if (ExprTy == TypeTy)
return E;
- // C++1z [conv.array]: The temporary materialization conversion is applied.
- // We also use this to fuel C++ DR1213, which applies to C++11 onwards.
- if (Kind == CK_ArrayToPointerDecay && getLangOpts().CPlusPlus &&
- E->getValueKind() == VK_RValue) {
- // The temporary is an lvalue in C++98 and an xvalue otherwise.
- ExprResult Materialized = CreateMaterializeTemporaryExpr(
- E->getType(), E, !getLangOpts().CPlusPlus11);
- if (Materialized.isInvalid())
- return ExprError();
- E = Materialized.get();
+ if (Kind == CK_ArrayToPointerDecay) {
+ // C++1z [conv.array]: The temporary materialization conversion is applied.
+ // We also use this to fuel C++ DR1213, which applies to C++11 onwards.
+ if (getLangOpts().CPlusPlus && E->isPRValue()) {
+ // The temporary is an lvalue in C++98 and an xvalue otherwise.
+ ExprResult Materialized = CreateMaterializeTemporaryExpr(
+ E->getType(), E, !getLangOpts().CPlusPlus11);
+ if (Materialized.isInvalid())
+ return ExprError();
+ E = Materialized.get();
+ }
+ // C17 6.7.1p6 footnote 124: The implementation can treat any register
+ // declaration simply as an auto declaration. However, whether or not
+ // addressable storage is actually used, the address of any part of an
+ // object declared with storage-class specifier register cannot be
+ // computed, either explicitly(by use of the unary & operator as discussed
+ // in 6.5.3.2) or implicitly(by converting an array name to a pointer as
+ // discussed in 6.3.2.1).Thus, the only operator that can be applied to an
+ // array declared with storage-class specifier register is sizeof.
+ if (VK == VK_PRValue && !getLangOpts().CPlusPlus && !E->isPRValue()) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (VD->getStorageClass() == SC_Register) {
+ Diag(E->getExprLoc(), diag::err_typecheck_address_of)
+ << /*register variable*/ 3 << E->getSourceRange();
+ return ExprError();
+ }
+ }
+ }
+ }
}
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
@@ -800,8 +856,21 @@
// FIXME: We can promote this to an error. The function or variable can't
// be defined anywhere else, so the program must necessarily violate the
// one definition rule.
- S.Diag(VD->getLocation(), diag::warn_undefined_internal)
- << isa<VarDecl>(VD) << VD;
+ bool IsImplicitBase = false;
+ if (const auto *BaseD = dyn_cast<FunctionDecl>(VD)) {
+ auto *DVAttr = BaseD->getAttr<OMPDeclareVariantAttr>();
+ if (DVAttr && !DVAttr->getTraitInfo().isExtensionActive(
+ llvm::omp::TraitProperty::
+ implementation_extension_disable_implicit_base)) {
+ const auto *Func = cast<FunctionDecl>(
+ cast<DeclRefExpr>(DVAttr->getVariantFuncRef())->getDecl());
+ IsImplicitBase = BaseD->isImplicit() &&
+ Func->getIdentifier()->isMangledOpenMPVariantName();
+ }
+ }
+ if (!S.getLangOpts().OpenMP || !IsImplicitBase)
+ S.Diag(VD->getLocation(), diag::warn_undefined_internal)
+ << isa<VarDecl>(VD) << VD;
} else if (auto *FD = dyn_cast<FunctionDecl>(VD)) {
(void)FD;
assert(FD->getMostRecentDecl()->isInlined() &&
@@ -1556,6 +1625,8 @@
DeferredDiagnosticsEmitter(Sema &S)
: Inherited(S), ShouldEmitRootNode(false), InOMPDeviceContext(0) {}
+ bool shouldVisitDiscardedStmt() const { return false; }
+
void VisitOMPTargetDirective(OMPTargetDirective *Node) {
++InOMPDeviceContext;
Inherited::VisitOMPTargetDirective(Node);
@@ -1763,7 +1834,7 @@
bool IsError = Diags.getDiagnosticIDs()->isDefaultMappingAsError(DiagID);
bool ShouldDefer = getLangOpts().CUDA && LangOpts.GPUDeferDiag &&
DiagnosticIDs::isDeferrable(DiagID) &&
- (DeferHint || !IsError);
+ (DeferHint || DeferDiags || !IsError);
auto SetIsLastErrorImmediate = [&](bool Flag) {
if (IsError)
IsLastErrorImmediate = Flag;
@@ -1928,6 +1999,9 @@
// Check that the type of the VarDecl has an accessible copy constructor and
// resolve its destructor's exception specification.
+// This also performs initialization of block variables when they are moved
+// to the heap. It uses the same rules as applicable for implicit moves
+// according to the C++ standard in effect ([class.copy.elision]p3).
static void checkEscapingByref(VarDecl *VD, Sema &S) {
QualType T = VD->getType();
EnterExpressionEvaluationContext scope(
@@ -1935,9 +2009,18 @@
SourceLocation Loc = VD->getLocation();
Expr *VarRef =
new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc);
- ExprResult Result = S.PerformMoveOrCopyInitialization(
- InitializedEntity::InitializeBlock(Loc, T, false), VD, VD->getType(),
- VarRef, /*AllowNRVO=*/true);
+ ExprResult Result;
+ auto IE = InitializedEntity::InitializeBlock(Loc, T, false);
+ if (S.getLangOpts().CPlusPlus2b) {
+ auto *E = ImplicitCastExpr::Create(S.Context, T, CK_NoOp, VarRef, nullptr,
+ VK_XValue, FPOptionsOverride());
+ Result = S.PerformCopyInitialization(IE, SourceLocation(), E);
+ } else {
+ Result = S.PerformMoveOrCopyInitialization(
+ IE, Sema::NamedReturnInfo{VD, Sema::NamedReturnInfo::MoveEligible},
+ VarRef);
+ }
+
if (!Result.isInvalid()) {
Result = S.MaybeCreateExprWithCleanups(Result);
Expr *Init = Result.getAs<Expr>();
@@ -2062,6 +2145,11 @@
FunctionScopes.back()->setHasIndirectGoto();
}
+void Sema::setFunctionHasMustTail() {
+ if (!FunctionScopes.empty())
+ FunctionScopes.back()->setHasMustTail();
+}
+
BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
return nullptr;
@@ -2302,13 +2390,11 @@
/// ill-formed expression.
static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads,
const SourceLocation FinalNoteLoc) {
- int ShownOverloads = 0;
- int SuppressedOverloads = 0;
+ unsigned ShownOverloads = 0;
+ unsigned SuppressedOverloads = 0;
for (UnresolvedSetImpl::iterator It = Overloads.begin(),
DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
- // FIXME: Magic number for max shown overloads stolen from
- // OverloadCandidateSet::NoteCandidates.
- if (ShownOverloads >= 4 && S.Diags.getShowOverloads() == Ovl_Best) {
+ if (ShownOverloads >= S.Diags.getNumOverloadCandidatesToShow()) {
++SuppressedOverloads;
continue;
}
@@ -2324,6 +2410,8 @@
++ShownOverloads;
}
+ S.Diags.overloadCandidatesShown(ShownOverloads);
+
if (SuppressedOverloads)
S.Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates)
<< SuppressedOverloads;
@@ -2448,114 +2536,3 @@
Sema::getMismatchingDeleteExpressions() const {
return DeleteExprs;
}
-
-void Sema::setOpenCLExtensionForType(QualType T, llvm::StringRef ExtStr) {
- if (ExtStr.empty())
- return;
- llvm::SmallVector<StringRef, 1> Exts;
- ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
- auto CanT = T.getCanonicalType().getTypePtr();
- for (auto &I : Exts)
- OpenCLTypeExtMap[CanT].insert(I.str());
-}
-
-void Sema::setOpenCLExtensionForDecl(Decl *FD, StringRef ExtStr) {
- llvm::SmallVector<StringRef, 1> Exts;
- ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
- if (Exts.empty())
- return;
- for (auto &I : Exts)
- OpenCLDeclExtMap[FD].insert(I.str());
-}
-
-void Sema::setCurrentOpenCLExtensionForType(QualType T) {
- if (CurrOpenCLExtension.empty())
- return;
- setOpenCLExtensionForType(T, CurrOpenCLExtension);
-}
-
-void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) {
- if (CurrOpenCLExtension.empty())
- return;
- setOpenCLExtensionForDecl(D, CurrOpenCLExtension);
-}
-
-std::string Sema::getOpenCLExtensionsFromDeclExtMap(FunctionDecl *FD) {
- if (!OpenCLDeclExtMap.empty())
- return getOpenCLExtensionsFromExtMap(FD, OpenCLDeclExtMap);
-
- return "";
-}
-
-std::string Sema::getOpenCLExtensionsFromTypeExtMap(FunctionType *FT) {
- if (!OpenCLTypeExtMap.empty())
- return getOpenCLExtensionsFromExtMap(FT, OpenCLTypeExtMap);
-
- return "";
-}
-
-template <typename T, typename MapT>
-std::string Sema::getOpenCLExtensionsFromExtMap(T *FDT, MapT &Map) {
- auto Loc = Map.find(FDT);
- return llvm::join(Loc->second, " ");
-}
-
-bool Sema::isOpenCLDisabledDecl(Decl *FD) {
- auto Loc = OpenCLDeclExtMap.find(FD);
- if (Loc == OpenCLDeclExtMap.end())
- return false;
- for (auto &I : Loc->second) {
- if (!getOpenCLOptions().isEnabled(I))
- return true;
- }
- return false;
-}
-
-template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
-bool Sema::checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc,
- DiagInfoT DiagInfo, MapT &Map,
- unsigned Selector,
- SourceRange SrcRange) {
- auto Loc = Map.find(D);
- if (Loc == Map.end())
- return false;
- bool Disabled = false;
- for (auto &I : Loc->second) {
- if (I != CurrOpenCLExtension && !getOpenCLOptions().isEnabled(I)) {
- Diag(DiagLoc, diag::err_opencl_requires_extension) << Selector << DiagInfo
- << I << SrcRange;
- Disabled = true;
- }
- }
- return Disabled;
-}
-
-bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
- // Check extensions for declared types.
- Decl *Decl = nullptr;
- if (auto TypedefT = dyn_cast<TypedefType>(QT.getTypePtr()))
- Decl = TypedefT->getDecl();
- if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr()))
- Decl = TagT->getDecl();
- auto Loc = DS.getTypeSpecTypeLoc();
-
- // Check extensions for vector types.
- // e.g. double4 is not allowed when cl_khr_fp64 is absent.
- if (QT->isExtVectorType()) {
- auto TypePtr = QT->castAs<ExtVectorType>()->getElementType().getTypePtr();
- return checkOpenCLDisabledTypeOrDecl(TypePtr, Loc, QT, OpenCLTypeExtMap);
- }
-
- if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap))
- return true;
-
- // Check extensions for builtin types.
- return checkOpenCLDisabledTypeOrDecl(QT.getCanonicalType().getTypePtr(), Loc,
- QT, OpenCLTypeExtMap);
-}
-
-bool Sema::checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E) {
- IdentifierInfo *FnName = D.getIdentifier();
- return checkOpenCLDisabledTypeOrDecl(&D, E.getBeginLoc(), FnName,
- OpenCLDeclExtMap, 1, D.getSourceRange());
-}
diff --git a/src/llvm-project/clang/lib/Sema/SemaAccess.cpp b/src/llvm-project/clang/lib/Sema/SemaAccess.cpp
index be30445..580305c 100644
--- a/src/llvm-project/clang/lib/Sema/SemaAccess.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaAccess.cpp
@@ -84,6 +84,20 @@
: Inner(DC),
Dependent(DC->isDependentContext()) {
+ // An implicit deduction guide is semantically in the context enclosing the
+ // class template, but for access purposes behaves like the constructor
+ // from which it was produced.
+ if (auto *DGD = dyn_cast<CXXDeductionGuideDecl>(DC)) {
+ if (DGD->isImplicit()) {
+ DC = DGD->getCorrespondingConstructor();
+ if (!DC) {
+ // The copy deduction candidate doesn't have a corresponding
+ // constructor.
+ DC = cast<DeclContext>(DGD->getDeducedTemplate()->getTemplatedDecl());
+ }
+ }
+ }
+
// C++11 [class.access.nest]p1:
// A nested class is a member and as such has the same access
// rights as any other member.
@@ -1294,17 +1308,18 @@
SourceLocation AccessLoc,
AccessTarget &Entity) {
if (UsingShadowDecl *Shadow =
- dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
- const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
- if (Entity.getTargetDecl()->getAccess() == AS_private &&
- (OrigDecl->getAccess() == AS_public ||
- OrigDecl->getAccess() == AS_protected)) {
- S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
- << Shadow->getUsingDecl()->getQualifiedNameAsString()
- << OrigDecl->getQualifiedNameAsString();
- return true;
+ dyn_cast<UsingShadowDecl>(Entity.getTargetDecl()))
+ if (UsingDecl *UD = dyn_cast<UsingDecl>(Shadow->getIntroducer())) {
+ const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
+ if (Entity.getTargetDecl()->getAccess() == AS_private &&
+ (OrigDecl->getAccess() == AS_public ||
+ OrigDecl->getAccess() == AS_protected)) {
+ S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
+ << UD->getQualifiedNameAsString()
+ << OrigDecl->getQualifiedNameAsString();
+ return true;
+ }
}
- }
return false;
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaAttr.cpp b/src/llvm-project/clang/lib/Sema/SemaAttr.cpp
index 6e441a0..fe8f02f 100644
--- a/src/llvm-project/clang/lib/Sema/SemaAttr.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaAttr.cpp
@@ -269,8 +269,10 @@
AlignPackStack.Act(PragmaLoc, Action, StringRef(), Info);
}
-void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action,
- PragmaClangSectionKind SecKind, StringRef SecName) {
+void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc,
+ PragmaClangSectionAction Action,
+ PragmaClangSectionKind SecKind,
+ StringRef SecName) {
PragmaClangSection *CSec;
int SectionFlags = ASTContext::PSF_Read;
switch (SecKind) {
@@ -301,6 +303,13 @@
return;
}
+ if (llvm::Error E = isValidSectionSpecifier(SecName)) {
+ Diag(PragmaLoc, diag::err_pragma_section_invalid_for_target)
+ << toString(std::move(E));
+ CSec->Valid = false;
+ return;
+ }
+
if (UnifySection(SecName, SectionFlags, PragmaLoc))
return;
@@ -867,12 +876,33 @@
}
Rules.clear();
} else {
- for (const auto &Rule : StrictSubjectMatchRuleSet) {
- if (Rules.erase(Rule.first)) {
+ // Each rule in Rules must be a strict subset of the attribute's
+ // SubjectMatch rules. I.e. we're allowed to use
+ // `apply_to=variables(is_global)` on an attrubute with SubjectList<[Var]>,
+ // but should not allow `apply_to=variables` on an attribute which has
+ // `SubjectList<[GlobalVar]>`.
+ for (const auto &StrictRule : StrictSubjectMatchRuleSet) {
+ // First, check for exact match.
+ if (Rules.erase(StrictRule.first)) {
// Add the rule to the set of attribute receivers only if it's supported
// in the current language mode.
- if (Rule.second)
- SubjectMatchRules.push_back(Rule.first);
+ if (StrictRule.second)
+ SubjectMatchRules.push_back(StrictRule.first);
+ }
+ }
+ // Check remaining rules for subset matches.
+ auto RulesToCheck = Rules;
+ for (const auto &Rule : RulesToCheck) {
+ attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
+ if (auto ParentRule = getParentAttrMatcherRule(MatchRule)) {
+ if (llvm::any_of(StrictSubjectMatchRuleSet,
+ [ParentRule](const auto &StrictRule) {
+ return StrictRule.first == *ParentRule &&
+ StrictRule.second; // IsEnabled
+ })) {
+ SubjectMatchRules.push_back(MatchRule);
+ Rules.erase(MatchRule);
+ }
}
}
}
@@ -1180,3 +1210,55 @@
if (Stack->empty())
FreeVisContext();
}
+
+template <typename Ty>
+static bool checkCommonAttributeFeatures(Sema& S, const Ty *Node,
+ const ParsedAttr& A) {
+ // Several attributes carry different semantics than the parsing requires, so
+ // those are opted out of the common argument checks.
+ //
+ // We also bail on unknown and ignored attributes because those are handled
+ // as part of the target-specific handling logic.
+ if (A.getKind() == ParsedAttr::UnknownAttribute)
+ return false;
+ // Check whether the attribute requires specific language extensions to be
+ // enabled.
+ if (!A.diagnoseLangOpts(S))
+ return true;
+ // Check whether the attribute appertains to the given subject.
+ if (!A.diagnoseAppertainsTo(S, Node))
+ return true;
+ // Check whether the attribute is mutually exclusive with other attributes
+ // that have already been applied to the declaration.
+ if (!A.diagnoseMutualExclusion(S, Node))
+ return true;
+ // Check whether the attribute exists in the target architecture.
+ if (S.CheckAttrTarget(A))
+ return true;
+
+ if (A.hasCustomParsing())
+ return false;
+
+ if (A.getMinArgs() == A.getMaxArgs()) {
+ // If there are no optional arguments, then checking for the argument count
+ // is trivial.
+ if (!A.checkExactlyNumArgs(S, A.getMinArgs()))
+ return true;
+ } else {
+ // There are optional arguments, so checking is slightly more involved.
+ if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, A.getMinArgs()))
+ return true;
+ else if (!A.hasVariadicArg() && A.getMaxArgs() &&
+ !A.checkAtMostNumArgs(S, A.getMaxArgs()))
+ return true;
+ }
+
+ return false;
+}
+
+bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A) {
+ return ::checkCommonAttributeFeatures(*this, D, A);
+}
+bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A) {
+ return ::checkCommonAttributeFeatures(*this, S, A);
+}
diff --git a/src/llvm-project/clang/lib/Sema/SemaAvailability.cpp b/src/llvm-project/clang/lib/Sema/SemaAvailability.cpp
index 74c4b9e..bb704b1 100644
--- a/src/llvm-project/clang/lib/Sema/SemaAvailability.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaAvailability.cpp
@@ -666,13 +666,6 @@
SemaRef.Context.getTargetInfo().getPlatformMinVersion());
}
- bool TraverseDecl(Decl *D) {
- // Avoid visiting nested functions to prevent duplicate warnings.
- if (!D || isa<FunctionDecl>(D))
- return true;
- return Base::TraverseDecl(D);
- }
-
bool TraverseStmt(Stmt *S) {
if (!S)
return true;
@@ -686,17 +679,11 @@
bool TraverseIfStmt(IfStmt *If);
- bool TraverseLambdaExpr(LambdaExpr *E) { return true; }
-
// for 'case X:' statements, don't bother looking at the 'X'; it can't lead
// to any useful diagnostics.
bool TraverseCaseStmt(CaseStmt *CS) { return TraverseStmt(CS->getSubStmt()); }
- bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) {
- if (PRE->isClassReceiver())
- DiagnoseDeclAvailability(PRE->getClassReceiver(), PRE->getReceiverLocation());
- return true;
- }
+ bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) { return true; }
bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) {
if (ObjCMethodDecl *D = Msg->getMethodDecl()) {
@@ -919,6 +906,17 @@
DiagnoseUnguardedAvailability(*this, D).IssueDiagnostics(Body);
}
+FunctionScopeInfo *Sema::getCurFunctionAvailabilityContext() {
+ if (FunctionScopes.empty())
+ return nullptr;
+
+ // Conservatively search the entire current function scope context for
+ // availability violations. This ensures we always correctly analyze nested
+ // classes, blocks, lambdas, etc. that may or may not be inside if(@available)
+ // checks themselves.
+ return FunctionScopes.front();
+}
+
void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D,
ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
@@ -941,11 +939,8 @@
// We need to know the @available context in the current function to
// diagnose this use, let DiagnoseUnguardedAvailabilityViolations do that
// when we're done parsing the current function.
- if (getCurFunctionOrMethodDecl()) {
- getEnclosingFunction()->HasPotentialAvailabilityViolations = true;
- return;
- } else if (getCurBlock() || getCurLambda()) {
- getCurFunction()->HasPotentialAvailabilityViolations = true;
+ if (FunctionScopeInfo *Context = getCurFunctionAvailabilityContext()) {
+ Context->HasPotentialAvailabilityViolations = true;
return;
}
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaCUDA.cpp b/src/llvm-project/clang/lib/Sema/SemaCUDA.cpp
index ee91eb4..75364c1 100644
--- a/src/llvm-project/clang/lib/Sema/SemaCUDA.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaCUDA.cpp
@@ -26,6 +26,14 @@
#include "llvm/ADT/SmallVector.h"
using namespace clang;
+template <typename AttrT> static bool hasExplicitAttr(const VarDecl *D) {
+ if (!D)
+ return false;
+ if (auto *A = D->getAttr<AttrT>())
+ return !A->isImplicit();
+ return false;
+}
+
void Sema::PushForceCUDAHostDevice() {
assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
ForceCUDAHostDeviceDepth++;
@@ -133,6 +141,38 @@
return CFT_Host;
}
+/// IdentifyTarget - Determine the CUDA compilation target for this variable.
+Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) {
+ if (Var->hasAttr<HIPManagedAttr>())
+ return CVT_Unified;
+ if (Var->isConstexpr() && !hasExplicitAttr<CUDAConstantAttr>(Var))
+ return CVT_Both;
+ if (Var->getType().isConstQualified() && Var->hasAttr<CUDAConstantAttr>() &&
+ !hasExplicitAttr<CUDAConstantAttr>(Var))
+ return CVT_Both;
+ if (Var->hasAttr<CUDADeviceAttr>() || Var->hasAttr<CUDAConstantAttr>() ||
+ Var->hasAttr<CUDASharedAttr>() ||
+ Var->getType()->isCUDADeviceBuiltinSurfaceType() ||
+ Var->getType()->isCUDADeviceBuiltinTextureType())
+ return CVT_Device;
+ // Function-scope static variable without explicit device or constant
+ // attribute are emitted
+ // - on both sides in host device functions
+ // - on device side in device or global functions
+ if (auto *FD = dyn_cast<FunctionDecl>(Var->getDeclContext())) {
+ switch (IdentifyCUDATarget(FD)) {
+ case CFT_HostDevice:
+ return CVT_Both;
+ case CFT_Device:
+ case CFT_Global:
+ return CVT_Device;
+ default:
+ return CVT_Host;
+ }
+ }
+ return CVT_Host;
+}
+
// * CUDA Call preference table
//
// F - from,
@@ -512,44 +552,78 @@
return true;
}
+namespace {
+enum CUDAInitializerCheckKind {
+ CICK_DeviceOrConstant, // Check initializer for device/constant variable
+ CICK_Shared, // Check initializer for shared variable
+};
+
+bool IsDependentVar(VarDecl *VD) {
+ if (VD->getType()->isDependentType())
+ return true;
+ if (const auto *Init = VD->getInit())
+ return Init->isValueDependent();
+ return false;
+}
+
+// Check whether a variable has an allowed initializer for a CUDA device side
+// variable with global storage. \p VD may be a host variable to be checked for
+// potential promotion to device side variable.
+//
+// CUDA/HIP allows only empty constructors as initializers for global
+// variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all
+// __shared__ variables whether they are local or not (they all are implicitly
+// static in CUDA). One exception is that CUDA allows constant initializers
+// for __constant__ and __device__ variables.
+bool HasAllowedCUDADeviceStaticInitializer(Sema &S, VarDecl *VD,
+ CUDAInitializerCheckKind CheckKind) {
+ assert(!VD->isInvalidDecl() && VD->hasGlobalStorage());
+ assert(!IsDependentVar(VD) && "do not check dependent var");
+ const Expr *Init = VD->getInit();
+ auto IsEmptyInit = [&](const Expr *Init) {
+ if (!Init)
+ return true;
+ if (const auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
+ return S.isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor());
+ }
+ return false;
+ };
+ auto IsConstantInit = [&](const Expr *Init) {
+ assert(Init);
+ return Init->isConstantInitializer(S.Context,
+ VD->getType()->isReferenceType());
+ };
+ auto HasEmptyDtor = [&](VarDecl *VD) {
+ if (const auto *RD = VD->getType()->getAsCXXRecordDecl())
+ return S.isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor());
+ return true;
+ };
+ if (CheckKind == CICK_Shared)
+ return IsEmptyInit(Init) && HasEmptyDtor(VD);
+ return S.LangOpts.GPUAllowDeviceInit ||
+ ((IsEmptyInit(Init) || IsConstantInit(Init)) && HasEmptyDtor(VD));
+}
+} // namespace
+
void Sema::checkAllowedCUDAInitializer(VarDecl *VD) {
- if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage())
+ // Do not check dependent variables since the ctor/dtor/initializer are not
+ // determined. Do it after instantiation.
+ if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage() ||
+ IsDependentVar(VD))
return;
const Expr *Init = VD->getInit();
- if (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>() ||
- VD->hasAttr<CUDASharedAttr>()) {
- if (LangOpts.GPUAllowDeviceInit)
+ bool IsSharedVar = VD->hasAttr<CUDASharedAttr>();
+ bool IsDeviceOrConstantVar =
+ !IsSharedVar &&
+ (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>());
+ if (IsDeviceOrConstantVar || IsSharedVar) {
+ if (HasAllowedCUDADeviceStaticInitializer(
+ *this, VD, IsSharedVar ? CICK_Shared : CICK_DeviceOrConstant))
return;
- bool AllowedInit = false;
- if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init))
- AllowedInit =
- isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor());
- // We'll allow constant initializers even if it's a non-empty
- // constructor according to CUDA rules. This deviates from NVCC,
- // but allows us to handle things like constexpr constructors.
- if (!AllowedInit &&
- (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>())) {
- auto *Init = VD->getInit();
- AllowedInit =
- ((VD->getType()->isDependentType() || Init->isValueDependent()) &&
- VD->isConstexpr()) ||
- Init->isConstantInitializer(Context,
- VD->getType()->isReferenceType());
- }
-
- // Also make sure that destructor, if there is one, is empty.
- if (AllowedInit)
- if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl())
- AllowedInit =
- isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor());
-
- if (!AllowedInit) {
- Diag(VD->getLocation(), VD->hasAttr<CUDASharedAttr>()
- ? diag::err_shared_var_init
- : diag::err_dynamic_var_init)
- << Init->getSourceRange();
- VD->setInvalidDecl();
- }
+ Diag(VD->getLocation(),
+ IsSharedVar ? diag::err_shared_var_init : diag::err_dynamic_var_init)
+ << Init->getSourceRange();
+ VD->setInvalidDecl();
} else {
// This is a host-side global variable. Check that the initializer is
// callable from the host side.
@@ -632,9 +706,19 @@
NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
}
+// TODO: `__constant__` memory may be a limited resource for certain targets.
+// A safeguard may be needed at the end of compilation pipeline if
+// `__constant__` memory usage goes beyond limit.
void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) {
- if (getLangOpts().CUDAIsDevice && VD->isConstexpr() &&
- (VD->isFileVarDecl() || VD->isStaticDataMember())) {
+ // Do not promote dependent variables since the cotr/dtor/initializer are
+ // not determined. Do it after instantiation.
+ if (getLangOpts().CUDAIsDevice && !VD->hasAttr<CUDAConstantAttr>() &&
+ !VD->hasAttr<CUDAConstantAttr>() && !VD->hasAttr<CUDASharedAttr>() &&
+ (VD->isFileVarDecl() || VD->isStaticDataMember()) &&
+ !IsDependentVar(VD) &&
+ (VD->isConstexpr() || (VD->getType().isConstQualified() &&
+ HasAllowedCUDADeviceStaticInitializer(
+ *this, VD, CICK_DeviceOrConstant)))) {
VD->addAttr(CUDAConstantAttr::CreateImplicit(getASTContext()));
}
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaCXXScopeSpec.cpp b/src/llvm-project/clang/lib/Sema/SemaCXXScopeSpec.cpp
index a4421d2..1c8f632 100644
--- a/src/llvm-project/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -227,12 +227,19 @@
return true;
}
- // Fixed enum types are complete, but they aren't valid as scopes
- // until we see a definition, so awkwardly pull out this special
- // case.
- auto *EnumD = dyn_cast<EnumDecl>(tag);
- if (!EnumD)
- return false;
+ if (auto *EnumD = dyn_cast<EnumDecl>(tag))
+ // Fixed enum types and scoped enum instantiations are complete, but they
+ // aren't valid as scopes until we see or instantiate their definition.
+ return RequireCompleteEnumDecl(EnumD, loc, &SS);
+
+ return false;
+}
+
+/// Require that the EnumDecl is completed with its enumerators defined or
+/// instantiated. SS, if provided, is the ScopeRef parsed.
+///
+bool Sema::RequireCompleteEnumDecl(EnumDecl *EnumD, SourceLocation L,
+ CXXScopeSpec *SS) {
if (EnumD->isCompleteDefinition()) {
// If we know about the definition but it is not visible, complain.
NamedDecl *SuggestedDef = nullptr;
@@ -241,8 +248,8 @@
// If the user is going to see an error here, recover by making the
// definition visible.
bool TreatAsComplete = !isSFINAEContext();
- diagnoseMissingImport(loc, SuggestedDef, MissingImportKind::Definition,
- /*Recover*/TreatAsComplete);
+ diagnoseMissingImport(L, SuggestedDef, MissingImportKind::Definition,
+ /*Recover*/ TreatAsComplete);
return !TreatAsComplete;
}
return false;
@@ -253,19 +260,26 @@
if (EnumDecl *Pattern = EnumD->getInstantiatedFromMemberEnum()) {
MemberSpecializationInfo *MSI = EnumD->getMemberSpecializationInfo();
if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
- if (InstantiateEnum(loc, EnumD, Pattern,
+ if (InstantiateEnum(L, EnumD, Pattern,
getTemplateInstantiationArgs(EnumD),
TSK_ImplicitInstantiation)) {
- SS.SetInvalid(SS.getRange());
+ if (SS)
+ SS->SetInvalid(SS->getRange());
return true;
}
return false;
}
}
- Diag(loc, diag::err_incomplete_nested_name_spec)
- << type << SS.getRange();
- SS.SetInvalid(SS.getRange());
+ if (SS) {
+ Diag(L, diag::err_incomplete_nested_name_spec)
+ << QualType(EnumD->getTypeForDecl(), 0) << SS->getRange();
+ SS->SetInvalid(SS->getRange());
+ } else {
+ Diag(L, diag::err_incomplete_enum) << QualType(EnumD->getTypeForDecl(), 0);
+ Diag(EnumD->getLocation(), diag::note_declared_at);
+ }
+
return true;
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaCast.cpp b/src/llvm-project/clang/lib/Sema/SemaCast.cpp
index 671820a..cac4307 100644
--- a/src/llvm-project/clang/lib/Sema/SemaCast.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaCast.cpp
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -23,6 +23,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallVector.h"
#include <set>
using namespace clang;
@@ -60,6 +61,15 @@
ValueKind(Expr::getValueKindForType(destType)),
Kind(CK_Dependent), IsARCUnbridgedCast(false) {
+ // C++ [expr.type]/8.2.2:
+ // If a pr-value initially has the type cv-T, where T is a
+ // cv-unqualified non-class, non-array type, the type of the
+ // expression is adjusted to T prior to any further analysis.
+ if (!S.Context.getLangOpts().ObjC && !DestType->isRecordType() &&
+ !DestType->isArrayType()) {
+ DestType = DestType.getUnqualifiedType();
+ }
+
if (const BuiltinType *placeholder =
src.get()->getType()->getAsPlaceholderType()) {
PlaceholderKind = placeholder->getKind();
@@ -746,7 +756,7 @@
void CastOperation::CheckDynamicCast() {
CheckNoDerefRAII NoderefCheck(*this);
- if (ValueKind == VK_RValue)
+ if (ValueKind == VK_PRValue)
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
else if (isPlaceholder())
SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get());
@@ -814,7 +824,7 @@
} else {
// If we're dynamic_casting from a prvalue to an rvalue reference, we need
// to materialize the prvalue before we bind the reference to it.
- if (SrcExpr.get()->isRValue())
+ if (SrcExpr.get()->isPRValue())
SrcExpr = Self.CreateMaterializeTemporaryExpr(
SrcType, SrcExpr.get(), /*IsLValueReference*/ false);
SrcPointee = SrcType;
@@ -913,7 +923,7 @@
void CastOperation::CheckConstCast() {
CheckNoDerefRAII NoderefCheck(*this);
- if (ValueKind == VK_RValue)
+ if (ValueKind == VK_PRValue)
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
else if (isPlaceholder())
SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get());
@@ -1035,13 +1045,97 @@
<< FixItHint::CreateReplacement(BeginLoc, "static_cast");
}
+static bool argTypeIsABIEquivalent(QualType SrcType, QualType DestType,
+ ASTContext &Context) {
+ if (SrcType->isPointerType() && DestType->isPointerType())
+ return true;
+
+ // Allow integral type mismatch if their size are equal.
+ if (SrcType->isIntegralType(Context) && DestType->isIntegralType(Context))
+ if (Context.getTypeInfoInChars(SrcType).Width ==
+ Context.getTypeInfoInChars(DestType).Width)
+ return true;
+
+ return Context.hasSameUnqualifiedType(SrcType, DestType);
+}
+
+static bool checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr,
+ QualType DestType) {
+ if (Self.Diags.isIgnored(diag::warn_cast_function_type,
+ SrcExpr.get()->getExprLoc()))
+ return true;
+
+ QualType SrcType = SrcExpr.get()->getType();
+ const FunctionType *SrcFTy = nullptr;
+ const FunctionType *DstFTy = nullptr;
+ if (((SrcType->isBlockPointerType() || SrcType->isFunctionPointerType()) &&
+ DestType->isFunctionPointerType()) ||
+ (SrcType->isMemberFunctionPointerType() &&
+ DestType->isMemberFunctionPointerType())) {
+ SrcFTy = SrcType->getPointeeType()->castAs<FunctionType>();
+ DstFTy = DestType->getPointeeType()->castAs<FunctionType>();
+ } else if (SrcType->isFunctionType() && DestType->isFunctionReferenceType()) {
+ SrcFTy = SrcType->castAs<FunctionType>();
+ DstFTy = DestType.getNonReferenceType()->castAs<FunctionType>();
+ } else {
+ return true;
+ }
+ assert(SrcFTy && DstFTy);
+
+ auto IsVoidVoid = [](const FunctionType *T) {
+ if (!T->getReturnType()->isVoidType())
+ return false;
+ if (const auto *PT = T->getAs<FunctionProtoType>())
+ return !PT->isVariadic() && PT->getNumParams() == 0;
+ return false;
+ };
+
+ // Skip if either function type is void(*)(void)
+ if (IsVoidVoid(SrcFTy) || IsVoidVoid(DstFTy))
+ return true;
+
+ // Check return type.
+ if (!argTypeIsABIEquivalent(SrcFTy->getReturnType(), DstFTy->getReturnType(),
+ Self.Context))
+ return false;
+
+ // Check if either has unspecified number of parameters
+ if (SrcFTy->isFunctionNoProtoType() || DstFTy->isFunctionNoProtoType())
+ return true;
+
+ // Check parameter types.
+
+ const auto *SrcFPTy = cast<FunctionProtoType>(SrcFTy);
+ const auto *DstFPTy = cast<FunctionProtoType>(DstFTy);
+
+ // In a cast involving function types with a variable argument list only the
+ // types of initial arguments that are provided are considered.
+ unsigned NumParams = SrcFPTy->getNumParams();
+ unsigned DstNumParams = DstFPTy->getNumParams();
+ if (NumParams > DstNumParams) {
+ if (!DstFPTy->isVariadic())
+ return false;
+ NumParams = DstNumParams;
+ } else if (NumParams < DstNumParams) {
+ if (!SrcFPTy->isVariadic())
+ return false;
+ }
+
+ for (unsigned i = 0; i < NumParams; ++i)
+ if (!argTypeIsABIEquivalent(SrcFPTy->getParamType(i),
+ DstFPTy->getParamType(i), Self.Context))
+ return false;
+
+ return true;
+}
+
/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is
/// valid.
/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code
/// like this:
/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
void CastOperation::CheckReinterpretCast() {
- if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload))
+ if (ValueKind == VK_PRValue && !isPlaceholder(BuiltinType::Overload))
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
else
checkNonOverloadPlaceholders();
@@ -1072,6 +1166,10 @@
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
checkObjCConversion(Sema::CCK_OtherCast);
DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange);
+
+ if (!checkCastFunctionType(Self, SrcExpr, DestType))
+ Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type)
+ << SrcExpr.get()->getType() << DestType << OpRange;
} else {
SrcExpr = ExprError();
}
@@ -1109,7 +1207,7 @@
return;
}
- if (ValueKind == VK_RValue && !DestType->isRecordType() &&
+ if (ValueKind == VK_PRValue && !DestType->isRecordType() &&
!isPlaceholder(BuiltinType::Overload)) {
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
@@ -1356,6 +1454,14 @@
DestPointer->getPointeeType()->getAs<RecordType>())
msg = diag::err_bad_cxx_cast_unrelated_class;
+ if (SrcType->isMatrixType() && DestType->isMatrixType()) {
+ if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind)) {
+ SrcExpr = ExprError();
+ return TC_Failed;
+ }
+ return TC_Success;
+ }
+
// We tried everything. Everything! Nothing works! :-(
return TC_NotApplicable;
}
@@ -1800,7 +1906,7 @@
return TC_NotApplicable;
}
- if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isRValue()) {
+ if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isPRValue()) {
if (!SrcType->isRecordType()) {
// Cannot const_cast non-class prvalue to rvalue reference type. But if
// this is C-style, static_cast can do this.
@@ -2072,7 +2178,8 @@
// like it?
if (Self.ResolveAndFixSingleFunctionTemplateSpecialization(
Result,
- Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr
+ Expr::getValueKindForType(DestType) ==
+ VK_PRValue // Convert Fun to Ptr
) &&
Result.isUsable())
return true;
@@ -2239,6 +2346,16 @@
return TC_Success;
}
+ if (Self.LangOpts.OpenCL && !CStyle) {
+ if (DestType->isExtVectorType() || SrcType->isExtVectorType()) {
+ // FIXME: Allow for reinterpret cast between 3 and 4 element vectors
+ if (Self.areVectorTypesSameSize(SrcType, DestType)) {
+ Kind = CK_BitCast;
+ return TC_Success;
+ }
+ }
+ }
+
// Otherwise, pick a reasonable diagnostic.
if (!destIsVector)
msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
@@ -2507,6 +2624,19 @@
}
}
+bool Sema::ShouldSplatAltivecScalarInCast(const VectorType *VecTy) {
+ bool SrcCompatXL = this->getLangOpts().getAltivecSrcCompat() ==
+ LangOptions::AltivecSrcCompatKind::XL;
+ VectorType::VectorKind VKind = VecTy->getVectorKind();
+
+ if ((VKind == VectorType::AltiVecVector) ||
+ (SrcCompatXL && ((VKind == VectorType::AltiVecBool) ||
+ (VKind == VectorType::AltiVecPixel)))) {
+ return true;
+ }
+ return false;
+}
+
void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
bool ListInitialization) {
assert(Self.getLangOpts().CPlusPlus);
@@ -2552,7 +2682,7 @@
return;
}
- if (ValueKind == VK_RValue && !DestType->isRecordType() &&
+ if (ValueKind == VK_PRValue && !DestType->isRecordType() &&
!isPlaceholder(BuiltinType::Overload)) {
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
if (SrcExpr.isInvalid())
@@ -2561,9 +2691,9 @@
// AltiVec vector initialization with a single literal.
if (const VectorType *vecTy = DestType->getAs<VectorType>())
- if (vecTy->getVectorKind() == VectorType::AltiVecVector
- && (SrcExpr.get()->getType()->isIntegerType()
- || SrcExpr.get()->getType()->isFloatingType())) {
+ if (Self.ShouldSplatAltivecScalarInCast(vecTy) &&
+ (SrcExpr.get()->getType()->isIntegerType() ||
+ SrcExpr.get()->getType()->isFloatingType())) {
Kind = CK_VectorSplat;
SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get());
return;
@@ -2645,6 +2775,11 @@
if (isValidCast(tcr)) {
if (Kind == CK_BitCast)
checkCastAlign();
+
+ if (!checkCastFunctionType(Self, SrcExpr, DestType))
+ Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type)
+ << SrcExpr.get()->getType() << DestType << OpRange;
+
} else {
SrcExpr = ExprError();
}
@@ -2765,7 +2900,8 @@
return;
}
- if (!DestType->isScalarType() && !DestType->isVectorType()) {
+ if (!DestType->isScalarType() && !DestType->isVectorType() &&
+ !DestType->isMatrixType()) {
const RecordType *DestRecordTy = DestType->getAs<RecordType>();
if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){
@@ -2803,7 +2939,7 @@
}
Self.Diag(OpRange.getBegin(),
diag::err_opencl_cast_non_zero_to_event_t)
- << CastInt.toString(10) << SrcExpr.get()->getSourceRange();
+ << toString(CastInt, 10) << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
return;
}
@@ -2816,10 +2952,11 @@
return;
}
- // The type we're casting to is known to be a scalar or vector.
+ // The type we're casting to is known to be a scalar, a vector, or a matrix.
- // Require the operand to be a scalar or vector.
- if (!SrcType->isScalarType() && !SrcType->isVectorType()) {
+ // Require the operand to be a scalar, a vector, or a matrix.
+ if (!SrcType->isScalarType() && !SrcType->isVectorType() &&
+ !SrcType->isMatrixType()) {
Self.Diag(SrcExpr.get()->getExprLoc(),
diag::err_typecheck_expect_scalar_operand)
<< SrcType << SrcExpr.get()->getSourceRange();
@@ -2832,9 +2969,15 @@
return;
}
+ if (DestType->getAs<MatrixType>() || SrcType->getAs<MatrixType>()) {
+ if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind))
+ SrcExpr = ExprError();
+ return;
+ }
+
if (const VectorType *DestVecTy = DestType->getAs<VectorType>()) {
- if (DestVecTy->getVectorKind() == VectorType::AltiVecVector &&
- (SrcType->isIntegerType() || SrcType->isFloatingType())) {
+ if (Self.ShouldSplatAltivecScalarInCast(DestVecTy) &&
+ (SrcType->isIntegerType() || SrcType->isFloatingType())) {
Kind = CK_VectorSplat;
SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get());
} else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) {
@@ -2916,8 +3059,8 @@
}
}
- if (Self.getLangOpts().OpenCL &&
- !Self.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
+ if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().isAvailableOption(
+ "cl_khr_fp16", Self.getLangOpts())) {
if (DestType->isHalfType()) {
Self.Diag(SrcExpr.get()->getBeginLoc(), diag::err_opencl_cast_to_half)
<< DestType << SrcExpr.get()->getSourceRange();
@@ -2957,6 +3100,10 @@
}
}
+ if (!checkCastFunctionType(Self, SrcExpr, DestType))
+ Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type)
+ << SrcType << DestType << OpRange;
+
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
DiagnoseCallingConvCast(Self, SrcExpr, DestType, OpRange);
DiagnoseBadFunctionCast(Self, SrcExpr, DestType);
@@ -2979,7 +3126,7 @@
return;
}
- if (SrcExpr.get()->isRValue())
+ if (SrcExpr.get()->isPRValue())
SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcType, SrcExpr.get(),
/*IsLValueReference=*/false);
diff --git a/src/llvm-project/clang/lib/Sema/SemaChecking.cpp b/src/llvm-project/clang/lib/Sema/SemaChecking.cpp
index 2b55712..de75c10 100644
--- a/src/llvm-project/clang/lib/Sema/SemaChecking.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaChecking.cpp
@@ -91,6 +91,7 @@
#include <algorithm>
#include <bitset>
#include <cassert>
+#include <cctype>
#include <cstddef>
#include <cstdint>
#include <functional>
@@ -252,7 +253,7 @@
}
if (llvm::APSInt::compareValues(AlignValue, MaxValue) > 0) {
S.Diag(AlignOp->getExprLoc(), diag::err_alignment_too_big)
- << MaxValue.toString(10);
+ << toString(MaxValue, 10);
return true;
}
if (!AlignValue.isPowerOf2()) {
@@ -771,8 +772,8 @@
DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
PDiag(DiagID)
- << FunctionName << ObjectSize.toString(/*Radix=*/10)
- << UsedSize.getValue().toString(/*Radix=*/10));
+ << FunctionName << toString(ObjectSize, /*Radix=*/10)
+ << toString(UsedSize.getValue(), /*Radix=*/10));
}
static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall,
@@ -837,7 +838,7 @@
}
static bool checkOpenCLSubgroupExt(Sema &S, CallExpr *Call) {
- if (!S.getOpenCLOptions().isEnabled("cl_khr_subgroups")) {
+ if (!S.getOpenCLOptions().isSupported("cl_khr_subgroups", S.getLangOpts())) {
S.Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension)
<< 1 << Call->getDirectCallee() << "cl_khr_subgroups";
return true;
@@ -1429,6 +1430,9 @@
return CheckPPCBuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::amdgcn:
return CheckAMDGCNBuiltinFunctionCall(BuiltinID, TheCall);
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ return CheckRISCVBuiltinFunctionCall(TI, BuiltinID, TheCall);
}
}
@@ -1550,6 +1554,10 @@
Diag(TheCall->getBeginLoc(), diag::warn_alloca)
<< TheCall->getDirectCallee();
break;
+ case Builtin::BI__arithmetic_fence:
+ if (SemaBuiltinArithmeticFence(TheCall))
+ return ExprError();
+ break;
case Builtin::BI__assume:
case Builtin::BI__builtin_assume:
if (SemaBuiltinAssume(TheCall))
@@ -1962,6 +1970,26 @@
case Builtin::BI__builtin_matrix_column_major_store:
return SemaBuiltinMatrixColumnMajorStore(TheCall, TheCallResult);
+
+ case Builtin::BI__builtin_get_device_side_mangled_name: {
+ auto Check = [](CallExpr *TheCall) {
+ if (TheCall->getNumArgs() != 1)
+ return false;
+ auto *DRE = dyn_cast<DeclRefExpr>(TheCall->getArg(0)->IgnoreImpCasts());
+ if (!DRE)
+ return false;
+ auto *D = DRE->getDecl();
+ if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D))
+ return false;
+ return D->hasAttr<CUDAGlobalAttr>() || D->hasAttr<CUDADeviceAttr>() ||
+ D->hasAttr<CUDAConstantAttr>() || D->hasAttr<HIPManagedAttr>();
+ };
+ if (!Check(TheCall)) {
+ Diag(TheCall->getBeginLoc(),
+ diag::err_hip_invalid_args_builtin_mangled_name);
+ return ExprError();
+ }
+ }
}
// Since the target specific builtins for each arch overlap, only check those
@@ -3231,34 +3259,81 @@
}
}
+static bool isPPC_64Builtin(unsigned BuiltinID) {
+ // These builtins only work on PPC 64bit targets.
+ switch (BuiltinID) {
+ case PPC::BI__builtin_divde:
+ case PPC::BI__builtin_divdeu:
+ case PPC::BI__builtin_bpermd:
+ case PPC::BI__builtin_ppc_ldarx:
+ case PPC::BI__builtin_ppc_stdcx:
+ case PPC::BI__builtin_ppc_tdw:
+ case PPC::BI__builtin_ppc_trapd:
+ case PPC::BI__builtin_ppc_cmpeqb:
+ case PPC::BI__builtin_ppc_setb:
+ case PPC::BI__builtin_ppc_mulhd:
+ case PPC::BI__builtin_ppc_mulhdu:
+ case PPC::BI__builtin_ppc_maddhd:
+ case PPC::BI__builtin_ppc_maddhdu:
+ case PPC::BI__builtin_ppc_maddld:
+ case PPC::BI__builtin_ppc_load8r:
+ case PPC::BI__builtin_ppc_store8r:
+ case PPC::BI__builtin_ppc_insert_exp:
+ case PPC::BI__builtin_ppc_extract_sig:
+ return true;
+ }
+ return false;
+}
+
+static bool SemaFeatureCheck(Sema &S, CallExpr *TheCall,
+ StringRef FeatureToCheck, unsigned DiagID,
+ StringRef DiagArg = "") {
+ if (S.Context.getTargetInfo().hasFeature(FeatureToCheck))
+ return false;
+
+ if (DiagArg.empty())
+ S.Diag(TheCall->getBeginLoc(), DiagID) << TheCall->getSourceRange();
+ else
+ S.Diag(TheCall->getBeginLoc(), DiagID)
+ << DiagArg << TheCall->getSourceRange();
+
+ return true;
+}
+
+/// Returns true if the argument consists of one contiguous run of 1s with any
+/// number of 0s on either side. The 1s are allowed to wrap from LSB to MSB, so
+/// 0x000FFF0, 0x0000FFFF, 0xFF0000FF, 0x0 are all runs. 0x0F0F0000 is not,
+/// since all 1s are not contiguous.
+bool Sema::SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum) {
+ llvm::APSInt Result;
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check constant-ness first.
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
+ return true;
+
+ // Check contiguous run of 1s, 0xFF0000FF is also a run of 1s.
+ if (Result.isShiftedMask() || (~Result).isShiftedMask())
+ return false;
+
+ return Diag(TheCall->getBeginLoc(),
+ diag::err_argument_not_contiguous_bit_field)
+ << ArgNum << Arg->getSourceRange();
+}
+
bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
- bool Is64BitBltin = BuiltinID == PPC::BI__builtin_divde ||
- BuiltinID == PPC::BI__builtin_divdeu ||
- BuiltinID == PPC::BI__builtin_bpermd;
bool IsTarget64Bit = TI.getTypeWidth(TI.getIntPtrType()) == 64;
- bool IsBltinExtDiv = BuiltinID == PPC::BI__builtin_divwe ||
- BuiltinID == PPC::BI__builtin_divweu ||
- BuiltinID == PPC::BI__builtin_divde ||
- BuiltinID == PPC::BI__builtin_divdeu;
+ llvm::APSInt Result;
- if (Is64BitBltin && !IsTarget64Bit)
+ if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
<< TheCall->getSourceRange();
- if ((IsBltinExtDiv && !TI.hasFeature("extdiv")) ||
- (BuiltinID == PPC::BI__builtin_bpermd && !TI.hasFeature("bpermd")))
- return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_only_on_pwr7)
- << TheCall->getSourceRange();
-
- auto SemaVSXCheck = [&](CallExpr *TheCall) -> bool {
- if (!TI.hasFeature("vsx"))
- return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_only_on_pwr7)
- << TheCall->getSourceRange();
- return false;
- };
-
switch (BuiltinID) {
default: return false;
case PPC::BI__builtin_altivec_crypto_vshasigmaw:
@@ -3284,11 +3359,22 @@
case PPC::BI__builtin_vsx_xxpermdi:
case PPC::BI__builtin_vsx_xxsldwi:
return SemaBuiltinVSX(TheCall);
+ case PPC::BI__builtin_divwe:
+ case PPC::BI__builtin_divweu:
+ case PPC::BI__builtin_divde:
+ case PPC::BI__builtin_divdeu:
+ return SemaFeatureCheck(*this, TheCall, "extdiv",
+ diag::err_ppc_builtin_only_on_arch, "7");
+ case PPC::BI__builtin_bpermd:
+ return SemaFeatureCheck(*this, TheCall, "bpermd",
+ diag::err_ppc_builtin_only_on_arch, "7");
case PPC::BI__builtin_unpack_vector_int128:
- return SemaVSXCheck(TheCall) ||
+ return SemaFeatureCheck(*this, TheCall, "vsx",
+ diag::err_ppc_builtin_only_on_arch, "7") ||
SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
case PPC::BI__builtin_pack_vector_int128:
- return SemaVSXCheck(TheCall);
+ return SemaFeatureCheck(*this, TheCall, "vsx",
+ diag::err_ppc_builtin_only_on_arch, "7");
case PPC::BI__builtin_altivec_vgnb:
return SemaBuiltinConstantArgRange(TheCall, 1, 2, 7);
case PPC::BI__builtin_altivec_vec_replace_elt:
@@ -3307,7 +3393,59 @@
return SemaBuiltinConstantArgRange(TheCall, 2, 0, 7);
case PPC::BI__builtin_vsx_xxpermx:
return SemaBuiltinConstantArgRange(TheCall, 3, 0, 7);
-#define CUSTOM_BUILTIN(Name, Types, Acc) \
+ case PPC::BI__builtin_ppc_tw:
+ case PPC::BI__builtin_ppc_tdw:
+ return SemaBuiltinConstantArgRange(TheCall, 2, 1, 31);
+ case PPC::BI__builtin_ppc_cmpeqb:
+ case PPC::BI__builtin_ppc_setb:
+ case PPC::BI__builtin_ppc_maddhd:
+ case PPC::BI__builtin_ppc_maddhdu:
+ case PPC::BI__builtin_ppc_maddld:
+ return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
+ diag::err_ppc_builtin_only_on_arch, "9");
+ case PPC::BI__builtin_ppc_cmprb:
+ return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
+ diag::err_ppc_builtin_only_on_arch, "9") ||
+ SemaBuiltinConstantArgRange(TheCall, 0, 0, 1);
+ // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must
+ // be a constant that represents a contiguous bit field.
+ case PPC::BI__builtin_ppc_rlwnm:
+ return SemaBuiltinConstantArg(TheCall, 1, Result) ||
+ SemaValueIsRunOfOnes(TheCall, 2);
+ case PPC::BI__builtin_ppc_rlwimi:
+ case PPC::BI__builtin_ppc_rldimi:
+ return SemaBuiltinConstantArg(TheCall, 2, Result) ||
+ SemaValueIsRunOfOnes(TheCall, 3);
+ case PPC::BI__builtin_ppc_extract_exp:
+ case PPC::BI__builtin_ppc_extract_sig:
+ case PPC::BI__builtin_ppc_insert_exp:
+ return SemaFeatureCheck(*this, TheCall, "power9-vector",
+ diag::err_ppc_builtin_only_on_arch, "9");
+ case PPC::BI__builtin_ppc_mtfsb0:
+ case PPC::BI__builtin_ppc_mtfsb1:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31);
+ case PPC::BI__builtin_ppc_mtfsf:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 255);
+ case PPC::BI__builtin_ppc_mtfsfi:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 7) ||
+ SemaBuiltinConstantArgRange(TheCall, 1, 0, 15);
+ case PPC::BI__builtin_ppc_alignx:
+ return SemaBuiltinConstantArgPower2(TheCall, 0);
+ case PPC::BI__builtin_ppc_rdlam:
+ return SemaValueIsRunOfOnes(TheCall, 2);
+ case PPC::BI__builtin_ppc_icbt:
+ case PPC::BI__builtin_ppc_sthcx:
+ case PPC::BI__builtin_ppc_stbcx:
+ case PPC::BI__builtin_ppc_lharx:
+ case PPC::BI__builtin_ppc_lbarx:
+ return SemaFeatureCheck(*this, TheCall, "isa-v207-instructions",
+ diag::err_ppc_builtin_only_on_arch, "8");
+ case PPC::BI__builtin_vsx_ldrmb:
+ case PPC::BI__builtin_vsx_strmb:
+ return SemaFeatureCheck(*this, TheCall, "isa-v207-instructions",
+ diag::err_ppc_builtin_only_on_arch, "8") ||
+ SemaBuiltinConstantArgRange(TheCall, 1, 1, 16);
+#define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
case PPC::BI__builtin_##Name: \
return SemaBuiltinPPCMMACall(TheCall, Types);
#include "clang/Basic/BuiltinsPPC.def"
@@ -3359,20 +3497,27 @@
if (!ArgExpr->EvaluateAsInt(ArgResult, Context))
return Diag(ArgExpr->getExprLoc(), diag::err_typecheck_expect_int)
<< ArgExpr->getType();
- int ord = ArgResult.Val.getInt().getZExtValue();
+ auto Ord = ArgResult.Val.getInt().getZExtValue();
// Check valididty of memory ordering as per C11 / C++11's memody model.
- switch (static_cast<llvm::AtomicOrderingCABI>(ord)) {
+ // Only fence needs check. Atomic dec/inc allow all memory orders.
+ if (!llvm::isValidAtomicOrderingCABI(Ord))
+ return Diag(ArgExpr->getBeginLoc(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << ArgExpr->getSourceRange();
+ switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) {
+ case llvm::AtomicOrderingCABI::relaxed:
+ case llvm::AtomicOrderingCABI::consume:
+ if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence)
+ return Diag(ArgExpr->getBeginLoc(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << ArgExpr->getSourceRange();
+ break;
case llvm::AtomicOrderingCABI::acquire:
case llvm::AtomicOrderingCABI::release:
case llvm::AtomicOrderingCABI::acq_rel:
case llvm::AtomicOrderingCABI::seq_cst:
break;
- default: {
- return Diag(ArgExpr->getBeginLoc(),
- diag::warn_atomic_op_has_invalid_memory_order)
- << ArgExpr->getSourceRange();
- }
}
Arg = TheCall->getArg(ScopeIndex);
@@ -3386,6 +3531,198 @@
return false;
}
+bool Sema::CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum) {
+ llvm::APSInt Result;
+
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check constant-ness first.
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
+ return true;
+
+ int64_t Val = Result.getSExtValue();
+ if ((Val >= 0 && Val <= 3) || (Val >= 5 && Val <= 7))
+ return false;
+
+ return Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_invalid_lmul)
+ << Arg->getSourceRange();
+}
+
+bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,
+ unsigned BuiltinID,
+ CallExpr *TheCall) {
+ // CodeGenFunction can also detect this, but this gives a better error
+ // message.
+ bool FeatureMissing = false;
+ SmallVector<StringRef> ReqFeatures;
+ StringRef Features = Context.BuiltinInfo.getRequiredFeatures(BuiltinID);
+ Features.split(ReqFeatures, ',');
+
+ // Check if each required feature is included
+ for (StringRef F : ReqFeatures) {
+ if (TI.hasFeature(F))
+ continue;
+
+ // If the feature is 64bit, alter the string so it will print better in
+ // the diagnostic.
+ if (F == "64bit")
+ F = "RV64";
+
+ // Convert features like "zbr" and "experimental-zbr" to "Zbr".
+ F.consume_front("experimental-");
+ std::string FeatureStr = F.str();
+ FeatureStr[0] = std::toupper(FeatureStr[0]);
+
+ // Error message
+ FeatureMissing = true;
+ Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension)
+ << TheCall->getSourceRange() << StringRef(FeatureStr);
+ }
+
+ if (FeatureMissing)
+ return true;
+
+ switch (BuiltinID) {
+ case RISCV::BI__builtin_rvv_vsetvli:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3) ||
+ CheckRISCVLMUL(TheCall, 2);
+ case RISCV::BI__builtin_rvv_vsetvlimax:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 3) ||
+ CheckRISCVLMUL(TheCall, 1);
+ case RISCV::BI__builtin_rvv_vget_v_i8m2_i8m1:
+ case RISCV::BI__builtin_rvv_vget_v_i16m2_i16m1:
+ case RISCV::BI__builtin_rvv_vget_v_i32m2_i32m1:
+ case RISCV::BI__builtin_rvv_vget_v_i64m2_i64m1:
+ case RISCV::BI__builtin_rvv_vget_v_f32m2_f32m1:
+ case RISCV::BI__builtin_rvv_vget_v_f64m2_f64m1:
+ case RISCV::BI__builtin_rvv_vget_v_u8m2_u8m1:
+ case RISCV::BI__builtin_rvv_vget_v_u16m2_u16m1:
+ case RISCV::BI__builtin_rvv_vget_v_u32m2_u32m1:
+ case RISCV::BI__builtin_rvv_vget_v_u64m2_u64m1:
+ case RISCV::BI__builtin_rvv_vget_v_i8m4_i8m2:
+ case RISCV::BI__builtin_rvv_vget_v_i16m4_i16m2:
+ case RISCV::BI__builtin_rvv_vget_v_i32m4_i32m2:
+ case RISCV::BI__builtin_rvv_vget_v_i64m4_i64m2:
+ case RISCV::BI__builtin_rvv_vget_v_f32m4_f32m2:
+ case RISCV::BI__builtin_rvv_vget_v_f64m4_f64m2:
+ case RISCV::BI__builtin_rvv_vget_v_u8m4_u8m2:
+ case RISCV::BI__builtin_rvv_vget_v_u16m4_u16m2:
+ case RISCV::BI__builtin_rvv_vget_v_u32m4_u32m2:
+ case RISCV::BI__builtin_rvv_vget_v_u64m4_u64m2:
+ case RISCV::BI__builtin_rvv_vget_v_i8m8_i8m4:
+ case RISCV::BI__builtin_rvv_vget_v_i16m8_i16m4:
+ case RISCV::BI__builtin_rvv_vget_v_i32m8_i32m4:
+ case RISCV::BI__builtin_rvv_vget_v_i64m8_i64m4:
+ case RISCV::BI__builtin_rvv_vget_v_f32m8_f32m4:
+ case RISCV::BI__builtin_rvv_vget_v_f64m8_f64m4:
+ case RISCV::BI__builtin_rvv_vget_v_u8m8_u8m4:
+ case RISCV::BI__builtin_rvv_vget_v_u16m8_u16m4:
+ case RISCV::BI__builtin_rvv_vget_v_u32m8_u32m4:
+ case RISCV::BI__builtin_rvv_vget_v_u64m8_u64m4:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
+ case RISCV::BI__builtin_rvv_vget_v_i8m4_i8m1:
+ case RISCV::BI__builtin_rvv_vget_v_i16m4_i16m1:
+ case RISCV::BI__builtin_rvv_vget_v_i32m4_i32m1:
+ case RISCV::BI__builtin_rvv_vget_v_i64m4_i64m1:
+ case RISCV::BI__builtin_rvv_vget_v_f32m4_f32m1:
+ case RISCV::BI__builtin_rvv_vget_v_f64m4_f64m1:
+ case RISCV::BI__builtin_rvv_vget_v_u8m4_u8m1:
+ case RISCV::BI__builtin_rvv_vget_v_u16m4_u16m1:
+ case RISCV::BI__builtin_rvv_vget_v_u32m4_u32m1:
+ case RISCV::BI__builtin_rvv_vget_v_u64m4_u64m1:
+ case RISCV::BI__builtin_rvv_vget_v_i8m8_i8m2:
+ case RISCV::BI__builtin_rvv_vget_v_i16m8_i16m2:
+ case RISCV::BI__builtin_rvv_vget_v_i32m8_i32m2:
+ case RISCV::BI__builtin_rvv_vget_v_i64m8_i64m2:
+ case RISCV::BI__builtin_rvv_vget_v_f32m8_f32m2:
+ case RISCV::BI__builtin_rvv_vget_v_f64m8_f64m2:
+ case RISCV::BI__builtin_rvv_vget_v_u8m8_u8m2:
+ case RISCV::BI__builtin_rvv_vget_v_u16m8_u16m2:
+ case RISCV::BI__builtin_rvv_vget_v_u32m8_u32m2:
+ case RISCV::BI__builtin_rvv_vget_v_u64m8_u64m2:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
+ case RISCV::BI__builtin_rvv_vget_v_i8m8_i8m1:
+ case RISCV::BI__builtin_rvv_vget_v_i16m8_i16m1:
+ case RISCV::BI__builtin_rvv_vget_v_i32m8_i32m1:
+ case RISCV::BI__builtin_rvv_vget_v_i64m8_i64m1:
+ case RISCV::BI__builtin_rvv_vget_v_f32m8_f32m1:
+ case RISCV::BI__builtin_rvv_vget_v_f64m8_f64m1:
+ case RISCV::BI__builtin_rvv_vget_v_u8m8_u8m1:
+ case RISCV::BI__builtin_rvv_vget_v_u16m8_u16m1:
+ case RISCV::BI__builtin_rvv_vget_v_u32m8_u32m1:
+ case RISCV::BI__builtin_rvv_vget_v_u64m8_u64m1:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 7);
+ case RISCV::BI__builtin_rvv_vset_v_i8m1_i8m2:
+ case RISCV::BI__builtin_rvv_vset_v_i16m1_i16m2:
+ case RISCV::BI__builtin_rvv_vset_v_i32m1_i32m2:
+ case RISCV::BI__builtin_rvv_vset_v_i64m1_i64m2:
+ case RISCV::BI__builtin_rvv_vset_v_f32m1_f32m2:
+ case RISCV::BI__builtin_rvv_vset_v_f64m1_f64m2:
+ case RISCV::BI__builtin_rvv_vset_v_u8m1_u8m2:
+ case RISCV::BI__builtin_rvv_vset_v_u16m1_u16m2:
+ case RISCV::BI__builtin_rvv_vset_v_u32m1_u32m2:
+ case RISCV::BI__builtin_rvv_vset_v_u64m1_u64m2:
+ case RISCV::BI__builtin_rvv_vset_v_i8m2_i8m4:
+ case RISCV::BI__builtin_rvv_vset_v_i16m2_i16m4:
+ case RISCV::BI__builtin_rvv_vset_v_i32m2_i32m4:
+ case RISCV::BI__builtin_rvv_vset_v_i64m2_i64m4:
+ case RISCV::BI__builtin_rvv_vset_v_f32m2_f32m4:
+ case RISCV::BI__builtin_rvv_vset_v_f64m2_f64m4:
+ case RISCV::BI__builtin_rvv_vset_v_u8m2_u8m4:
+ case RISCV::BI__builtin_rvv_vset_v_u16m2_u16m4:
+ case RISCV::BI__builtin_rvv_vset_v_u32m2_u32m4:
+ case RISCV::BI__builtin_rvv_vset_v_u64m2_u64m4:
+ case RISCV::BI__builtin_rvv_vset_v_i8m4_i8m8:
+ case RISCV::BI__builtin_rvv_vset_v_i16m4_i16m8:
+ case RISCV::BI__builtin_rvv_vset_v_i32m4_i32m8:
+ case RISCV::BI__builtin_rvv_vset_v_i64m4_i64m8:
+ case RISCV::BI__builtin_rvv_vset_v_f32m4_f32m8:
+ case RISCV::BI__builtin_rvv_vset_v_f64m4_f64m8:
+ case RISCV::BI__builtin_rvv_vset_v_u8m4_u8m8:
+ case RISCV::BI__builtin_rvv_vset_v_u16m4_u16m8:
+ case RISCV::BI__builtin_rvv_vset_v_u32m4_u32m8:
+ case RISCV::BI__builtin_rvv_vset_v_u64m4_u64m8:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
+ case RISCV::BI__builtin_rvv_vset_v_i8m1_i8m4:
+ case RISCV::BI__builtin_rvv_vset_v_i16m1_i16m4:
+ case RISCV::BI__builtin_rvv_vset_v_i32m1_i32m4:
+ case RISCV::BI__builtin_rvv_vset_v_i64m1_i64m4:
+ case RISCV::BI__builtin_rvv_vset_v_f32m1_f32m4:
+ case RISCV::BI__builtin_rvv_vset_v_f64m1_f64m4:
+ case RISCV::BI__builtin_rvv_vset_v_u8m1_u8m4:
+ case RISCV::BI__builtin_rvv_vset_v_u16m1_u16m4:
+ case RISCV::BI__builtin_rvv_vset_v_u32m1_u32m4:
+ case RISCV::BI__builtin_rvv_vset_v_u64m1_u64m4:
+ case RISCV::BI__builtin_rvv_vset_v_i8m2_i8m8:
+ case RISCV::BI__builtin_rvv_vset_v_i16m2_i16m8:
+ case RISCV::BI__builtin_rvv_vset_v_i32m2_i32m8:
+ case RISCV::BI__builtin_rvv_vset_v_i64m2_i64m8:
+ case RISCV::BI__builtin_rvv_vset_v_f32m2_f32m8:
+ case RISCV::BI__builtin_rvv_vset_v_f64m2_f64m8:
+ case RISCV::BI__builtin_rvv_vset_v_u8m2_u8m8:
+ case RISCV::BI__builtin_rvv_vset_v_u16m2_u16m8:
+ case RISCV::BI__builtin_rvv_vset_v_u32m2_u32m8:
+ case RISCV::BI__builtin_rvv_vset_v_u64m2_u64m8:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
+ case RISCV::BI__builtin_rvv_vset_v_i8m1_i8m8:
+ case RISCV::BI__builtin_rvv_vset_v_i16m1_i16m8:
+ case RISCV::BI__builtin_rvv_vset_v_i32m1_i32m8:
+ case RISCV::BI__builtin_rvv_vset_v_i64m1_i64m8:
+ case RISCV::BI__builtin_rvv_vset_v_f32m1_f32m8:
+ case RISCV::BI__builtin_rvv_vset_v_f64m1_f64m8:
+ case RISCV::BI__builtin_rvv_vset_v_u8m1_u8m8:
+ case RISCV::BI__builtin_rvv_vset_v_u16m1_u16m8:
+ case RISCV::BI__builtin_rvv_vset_v_u32m1_u32m8:
+ case RISCV::BI__builtin_rvv_vset_v_u64m1_u64m8:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 7);
+ }
+
+ return false;
+}
+
bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
if (BuiltinID == SystemZ::BI__builtin_tabort) {
@@ -3446,6 +3783,11 @@
case SystemZ::BI__builtin_s390_vfmaxdb: i = 2; l = 0; u = 15; break;
case SystemZ::BI__builtin_s390_vsld: i = 2; l = 0; u = 7; break;
case SystemZ::BI__builtin_s390_vsrd: i = 2; l = 0; u = 7; break;
+ case SystemZ::BI__builtin_s390_vclfnhs:
+ case SystemZ::BI__builtin_s390_vclfnls:
+ case SystemZ::BI__builtin_s390_vcfn:
+ case SystemZ::BI__builtin_s390_vcnf: i = 1; l = 0; u = 15; break;
+ case SystemZ::BI__builtin_s390_vcrnfs: i = 2; l = 0; u = 15; break;
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
@@ -4451,6 +4793,45 @@
}
}
+/// Warn if a pointer or reference argument passed to a function points to an
+/// object that is less aligned than the parameter. This can happen when
+/// creating a typedef with a lower alignment than the original type and then
+/// calling functions defined in terms of the original type.
+void Sema::CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
+ StringRef ParamName, QualType ArgTy,
+ QualType ParamTy) {
+
+ // If a function accepts a pointer or reference type
+ if (!ParamTy->isPointerType() && !ParamTy->isReferenceType())
+ return;
+
+ // If the parameter is a pointer type, get the pointee type for the
+ // argument too. If the parameter is a reference type, don't try to get
+ // the pointee type for the argument.
+ if (ParamTy->isPointerType())
+ ArgTy = ArgTy->getPointeeType();
+
+ // Remove reference or pointer
+ ParamTy = ParamTy->getPointeeType();
+
+ // Find expected alignment, and the actual alignment of the passed object.
+ // getTypeAlignInChars requires complete types
+ if (ArgTy.isNull() || ParamTy->isIncompleteType() ||
+ ArgTy->isIncompleteType() || ParamTy->isUndeducedType() ||
+ ArgTy->isUndeducedType())
+ return;
+
+ CharUnits ParamAlign = Context.getTypeAlignInChars(ParamTy);
+ CharUnits ArgAlign = Context.getTypeAlignInChars(ArgTy);
+
+ // If the argument is less aligned than the parameter, there is a
+ // potential alignment issue.
+ if (ArgAlign < ParamAlign)
+ Diag(Loc, diag::warn_param_mismatched_alignment)
+ << (int)ArgAlign.getQuantity() << (int)ParamAlign.getQuantity()
+ << ParamName << FDecl;
+}
+
/// Handles the checks for format strings, non-POD arguments to vararg
/// functions, NULL arguments passed to non-NULL parameters, and diagnose_if
/// attributes.
@@ -4505,6 +4886,31 @@
}
}
+ // Check that passed arguments match the alignment of original arguments.
+ // Try to get the missing prototype from the declaration.
+ if (!Proto && FDecl) {
+ const auto *FT = FDecl->getFunctionType();
+ if (isa_and_nonnull<FunctionProtoType>(FT))
+ Proto = cast<FunctionProtoType>(FDecl->getFunctionType());
+ }
+ if (Proto) {
+ // For variadic functions, we may have more args than parameters.
+ // For some K&R functions, we may have less args than parameters.
+ const auto N = std::min<unsigned>(Proto->getNumParams(), Args.size());
+ for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
+ // Args[ArgIdx] can be null in malformed code.
+ if (const Expr *Arg = Args[ArgIdx]) {
+ if (Arg->containsErrors())
+ continue;
+
+ QualType ParamTy = Proto->getParamType(ArgIdx);
+ QualType ArgTy = Arg->getType();
+ CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
+ ArgTy, ParamTy);
+ }
+ }
+ }
+
if (FDecl && FDecl->hasAttr<AllocAlignAttr>()) {
auto *AA = FDecl->getAttr<AllocAlignAttr>();
const Expr *Arg = Args[AA->getParamIndex().getASTIndex()];
@@ -4529,12 +4935,17 @@
/// CheckConstructorCall - Check a constructor call for correctness and safety
/// properties not enforced by the C type system.
-void Sema::CheckConstructorCall(FunctionDecl *FDecl,
+void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
ArrayRef<const Expr *> Args,
const FunctionProtoType *Proto,
SourceLocation Loc) {
VariadicCallType CallType =
- Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
+ Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
+
+ auto *Ctor = cast<CXXConstructorDecl>(FDecl);
+ CheckArgAlignment(Loc, FDecl, "'this'", Context.getPointerType(ThisType),
+ Context.getPointerType(Ctor->getThisObjectType()));
+
checkCall(FDecl, Proto, /*ThisArg=*/nullptr, Args, /*IsMemberFunction=*/true,
Loc, SourceRange(), CallType);
}
@@ -4564,6 +4975,22 @@
ImplicitThis =
cast<CXXMemberCallExpr>(TheCall)->getImplicitObjectArgument();
+ if (ImplicitThis) {
+ // ImplicitThis may or may not be a pointer, depending on whether . or -> is
+ // used.
+ QualType ThisType = ImplicitThis->getType();
+ if (!ThisType->isPointerType()) {
+ assert(!ThisType->isReferenceType());
+ ThisType = Context.getPointerType(ThisType);
+ }
+
+ QualType ThisTypeFromDecl =
+ Context.getPointerType(cast<CXXMethodDecl>(FDecl)->getThisObjectType());
+
+ CheckArgAlignment(TheCall->getRParenLoc(), FDecl, "'this'", ThisType,
+ ThisTypeFromDecl);
+ }
+
checkCall(FDecl, Proto, ImplicitThis, llvm::makeArrayRef(Args, NumArgs),
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -4797,7 +5224,8 @@
case AtomicExpr::AO__atomic_add_fetch:
case AtomicExpr::AO__atomic_sub_fetch:
IsAddSub = true;
- LLVM_FALLTHROUGH;
+ Form = Arithmetic;
+ break;
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__c11_atomic_fetch_xor:
@@ -4812,6 +5240,8 @@
case AtomicExpr::AO__atomic_or_fetch:
case AtomicExpr::AO__atomic_xor_fetch:
case AtomicExpr::AO__atomic_nand_fetch:
+ Form = Arithmetic;
+ break;
case AtomicExpr::AO__c11_atomic_fetch_min:
case AtomicExpr::AO__c11_atomic_fetch_max:
case AtomicExpr::AO__opencl_atomic_fetch_min:
@@ -4904,10 +5334,24 @@
// For an arithmetic operation, the implied arithmetic must be well-formed.
if (Form == Arithmetic) {
- // gcc does not enforce these rules for GNU atomics, but we do so for sanity.
- if (IsAddSub && !ValType->isIntegerType()
- && !ValType->isPointerType()) {
- Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_atomic_int_or_ptr)
+ // gcc does not enforce these rules for GNU atomics, but we do so for
+ // sanity.
+ auto IsAllowedValueType = [&](QualType ValType) {
+ if (ValType->isIntegerType())
+ return true;
+ if (ValType->isPointerType())
+ return true;
+ if (!ValType->isFloatingType())
+ return false;
+ // LLVM Parser does not allow atomicrmw with x86_fp80 type.
+ if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&
+ &Context.getTargetInfo().getLongDoubleFormat() ==
+ &llvm::APFloat::x87DoubleExtended())
+ return false;
+ return true;
+ };
+ if (IsAddSub && !IsAllowedValueType(ValType)) {
+ Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_atomic_int_ptr_or_fp)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
@@ -5034,7 +5478,9 @@
// passed by address. For the rest, GNU uses by-address and C11 uses
// by-value.
assert(Form != Load);
- if (Form == Init || (Form == Arithmetic && ValType->isIntegerType()))
+ if (Form == Arithmetic && ValType->isPointerType())
+ Ty = Context.getPointerDiffType();
+ else if (Form == Init || Form == Arithmetic)
Ty = ValType;
else if (Form == Copy || Form == Xchg) {
if (IsPassedByAddress) {
@@ -5043,9 +5489,7 @@
ExprRange.getBegin());
}
Ty = ByValType;
- } else if (Form == Arithmetic)
- Ty = Context.getPointerDiffType();
- else {
+ } else {
Expr *ValArg = APIOrderedArgs[i];
// The value pointer is always dereferenced, a nullptr is undefined.
CheckNonNullArgument(*this, ValArg, ExprRange.getBegin());
@@ -6168,7 +6612,7 @@
ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc) {
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
ExprObjectKind OK = OK_Ordinary;
QualType DstTy = TInfo->getType();
QualType SrcTy = E->getType();
@@ -6214,6 +6658,29 @@
return false;
}
+/// SemaBuiltinArithmeticFence - Handle __arithmetic_fence.
+bool Sema::SemaBuiltinArithmeticFence(CallExpr *TheCall) {
+ if (!Context.getTargetInfo().checkArithmeticFenceSupported())
+ return Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
+ << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
+ if (checkArgCount(*this, TheCall, 1))
+ return true;
+ Expr *Arg = TheCall->getArg(0);
+ if (Arg->isInstantiationDependent())
+ return false;
+
+ QualType ArgTy = Arg->getType();
+ if (!ArgTy->hasFloatingRepresentation())
+ return Diag(TheCall->getEndLoc(), diag::err_typecheck_expect_flt_or_vector)
+ << ArgTy;
+ if (Arg->isLValue()) {
+ ExprResult FirstArg = DefaultLvalueConversion(Arg);
+ TheCall->setArg(0, FirstArg.get());
+ }
+ TheCall->setType(TheCall->getArg(0)->getType());
+ return false;
+}
+
/// SemaBuiltinAssume - Handle __assume (MS Extension).
// __assume does not evaluate its arguments, and should warn if its argument
// has side effects.
@@ -6421,13 +6888,13 @@
if (Result.getSExtValue() < Low || Result.getSExtValue() > High) {
if (RangeIsError)
return Diag(TheCall->getBeginLoc(), diag::err_argument_invalid_range)
- << Result.toString(10) << Low << High << Arg->getSourceRange();
+ << toString(Result, 10) << Low << High << Arg->getSourceRange();
else
// Defer the warning until we know if the code will be emitted so that
// dead code can ignore this.
DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
PDiag(diag::warn_argument_invalid_range)
- << Result.toString(10) << Low << High
+ << toString(Result, 10) << Low << High
<< Arg->getSourceRange());
}
@@ -6762,18 +7229,18 @@
bool ValidString = true;
if (IsARMBuiltin) {
- ValidString &= Fields[0].startswith_lower("cp") ||
- Fields[0].startswith_lower("p");
+ ValidString &= Fields[0].startswith_insensitive("cp") ||
+ Fields[0].startswith_insensitive("p");
if (ValidString)
- Fields[0] =
- Fields[0].drop_front(Fields[0].startswith_lower("cp") ? 2 : 1);
+ Fields[0] = Fields[0].drop_front(
+ Fields[0].startswith_insensitive("cp") ? 2 : 1);
- ValidString &= Fields[2].startswith_lower("c");
+ ValidString &= Fields[2].startswith_insensitive("c");
if (ValidString)
Fields[2] = Fields[2].drop_front(1);
if (FiveFields) {
- ValidString &= Fields[3].startswith_lower("c");
+ ValidString &= Fields[3].startswith_insensitive("c");
if (ValidString)
Fields[3] = Fields[3].drop_front(1);
}
@@ -8633,8 +9100,11 @@
} else if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) {
// Special case for 'a', which has type 'int' in C.
// Note, however, that we do /not/ want to treat multibyte constants like
- // 'MooV' as characters! This form is deprecated but still exists.
- if (ExprTy == S.Context.IntTy)
+ // 'MooV' as characters! This form is deprecated but still exists. In
+ // addition, don't treat expressions as of type 'char' if one byte length
+ // modifier is provided.
+ if (ExprTy == S.Context.IntTy &&
+ FS.getLengthModifier().getKind() != LengthModifier::AsChar)
if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue()))
ExprTy = S.Context.CharTy;
}
@@ -10253,64 +10723,116 @@
namespace {
void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
- const UnaryOperator *UnaryExpr,
- const VarDecl *Var) {
- StorageClass Class = Var->getStorageClass();
- if (Class == StorageClass::SC_Extern ||
- Class == StorageClass::SC_PrivateExtern ||
- Var->getType()->isReferenceType())
- return;
-
- S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
- << CalleeName << Var;
-}
-
-void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
const UnaryOperator *UnaryExpr, const Decl *D) {
- if (const auto *Field = dyn_cast<FieldDecl>(D))
+ if (isa<FieldDecl, FunctionDecl, VarDecl>(D)) {
S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
- << CalleeName << Field;
+ << CalleeName << 0 /*object: */ << cast<NamedDecl>(D);
+ return;
+ }
}
void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName,
const UnaryOperator *UnaryExpr) {
- if (UnaryExpr->getOpcode() != UnaryOperator::Opcode::UO_AddrOf)
- return;
-
- if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr()))
- if (const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl()))
- return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, Var);
+ if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr())) {
+ const Decl *D = Lvalue->getDecl();
+ if (isa<DeclaratorDecl>(D))
+ if (!dyn_cast<DeclaratorDecl>(D)->getType()->isReferenceType())
+ return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
+ }
if (const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->getSubExpr()))
return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr,
Lvalue->getMemberDecl());
}
-void CheckFreeArgumentsStackArray(Sema &S, const std::string &CalleeName,
- const DeclRefExpr *Lvalue) {
- if (!Lvalue->getType()->isArrayType())
+void CheckFreeArgumentsPlus(Sema &S, const std::string &CalleeName,
+ const UnaryOperator *UnaryExpr) {
+ const auto *Lambda = dyn_cast<LambdaExpr>(
+ UnaryExpr->getSubExpr()->IgnoreImplicitAsWritten()->IgnoreParens());
+ if (!Lambda)
return;
+ S.Diag(Lambda->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << 2 /*object: lambda expression*/;
+}
+
+void CheckFreeArgumentsStackArray(Sema &S, const std::string &CalleeName,
+ const DeclRefExpr *Lvalue) {
const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl());
if (Var == nullptr)
return;
S.Diag(Lvalue->getBeginLoc(), diag::warn_free_nonheap_object)
- << CalleeName << Var;
+ << CalleeName << 0 /*object: */ << Var;
+}
+
+void CheckFreeArgumentsCast(Sema &S, const std::string &CalleeName,
+ const CastExpr *Cast) {
+ SmallString<128> SizeString;
+ llvm::raw_svector_ostream OS(SizeString);
+
+ clang::CastKind Kind = Cast->getCastKind();
+ if (Kind == clang::CK_BitCast &&
+ !Cast->getSubExpr()->getType()->isFunctionPointerType())
+ return;
+ if (Kind == clang::CK_IntegralToPointer &&
+ !isa<IntegerLiteral>(
+ Cast->getSubExpr()->IgnoreParenImpCasts()->IgnoreParens()))
+ return;
+
+ switch (Cast->getCastKind()) {
+ case clang::CK_BitCast:
+ case clang::CK_IntegralToPointer:
+ case clang::CK_FunctionToPointerDecay:
+ OS << '\'';
+ Cast->printPretty(OS, nullptr, S.getPrintingPolicy());
+ OS << '\'';
+ break;
+ default:
+ return;
+ }
+
+ S.Diag(Cast->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << 0 /*object: */ << OS.str();
}
} // namespace
/// Alerts the user that they are attempting to free a non-malloc'd object.
void Sema::CheckFreeArguments(const CallExpr *E) {
- const Expr *Arg = E->getArg(0)->IgnoreParenCasts();
const std::string CalleeName =
dyn_cast<FunctionDecl>(E->getCalleeDecl())->getQualifiedNameAsString();
- if (const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg))
- return CheckFreeArgumentsAddressof(*this, CalleeName, UnaryExpr);
+ { // Prefer something that doesn't involve a cast to make things simpler.
+ const Expr *Arg = E->getArg(0)->IgnoreParenCasts();
+ if (const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg))
+ switch (UnaryExpr->getOpcode()) {
+ case UnaryOperator::Opcode::UO_AddrOf:
+ return CheckFreeArgumentsAddressof(*this, CalleeName, UnaryExpr);
+ case UnaryOperator::Opcode::UO_Plus:
+ return CheckFreeArgumentsPlus(*this, CalleeName, UnaryExpr);
+ default:
+ break;
+ }
- if (const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg))
- return CheckFreeArgumentsStackArray(*this, CalleeName, Lvalue);
+ if (const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg))
+ if (Lvalue->getType()->isArrayType())
+ return CheckFreeArgumentsStackArray(*this, CalleeName, Lvalue);
+
+ if (const auto *Label = dyn_cast<AddrLabelExpr>(Arg)) {
+ Diag(Label->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << 0 /*object: */ << Label->getLabel()->getIdentifier();
+ return;
+ }
+
+ if (isa<BlockExpr>(Arg)) {
+ Diag(Arg->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << 1 /*object: block*/;
+ return;
+ }
+ }
+ // Maybe the cast was important, check after the other cases.
+ if (const auto *Cast = dyn_cast<CastExpr>(E->getArg(0)))
+ return CheckFreeArgumentsCast(*this, CalleeName, Cast);
}
void
@@ -11228,11 +11750,14 @@
<< OtherIsBooleanDespiteType << *Result
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
} else {
- unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
- ? (HasEnumType(OriginalOther)
- ? diag::warn_unsigned_enum_always_true_comparison
- : diag::warn_unsigned_always_true_comparison)
- : diag::warn_tautological_constant_compare;
+ bool IsCharTy = OtherT.withoutLocalFastQualifiers() == S.Context.CharTy;
+ unsigned Diag =
+ (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
+ ? (HasEnumType(OriginalOther)
+ ? diag::warn_unsigned_enum_always_true_comparison
+ : IsCharTy ? diag::warn_unsigned_char_always_true_comparison
+ : diag::warn_unsigned_always_true_comparison)
+ : diag::warn_tautological_constant_compare;
S.Diag(E->getOperatorLoc(), Diag)
<< RhsConstant << OtherT << E->getOpcodeStr() << OS.str() << *Result
@@ -11487,8 +12012,8 @@
if (FieldWidth == 1 && Value == 1)
return false;
- std::string PrettyValue = Value.toString(10);
- std::string PrettyTrunc = TruncatedValue.toString(10);
+ std::string PrettyValue = toString(Value, 10);
+ std::string PrettyTrunc = toString(TruncatedValue, 10);
S.Diag(InitLoc, diag::warn_impcast_bitfield_precision_constant)
<< PrettyValue << PrettyTrunc << OriginalInit->getType()
@@ -11724,7 +12249,7 @@
llvm::APSInt ValueInRange = Value;
ValueInRange.setIsSigned(!Range.NonNegative);
ValueInRange = ValueInRange.trunc(Range.Width);
- return ValueInRange.toString(10);
+ return toString(ValueInRange, 10);
}
static bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) {
@@ -12040,7 +12565,7 @@
adornObjCBoolConversionDiagWithTernaryFixit(
S, E,
S.Diag(CC, diag::warn_impcast_constant_value_to_objc_bool)
- << Result.Val.getInt().toString(10));
+ << toString(Result.Val.getInt(), 10));
}
return;
}
@@ -12055,6 +12580,13 @@
// Strip vector types.
if (isa<VectorType>(Source)) {
+ if (Target->isVLSTBuiltinType() &&
+ (S.Context.areCompatibleSveTypes(QualType(Target, 0),
+ QualType(Source, 0)) ||
+ S.Context.areLaxCompatibleSveTypes(QualType(Target, 0),
+ QualType(Source, 0))))
+ return;
+
if (!isa<VectorType>(Target)) {
if (S.SourceMgr.isInSystemMacro(CC))
return;
@@ -12215,7 +12747,7 @@
if (Overflowed) {
S.DiagRuntimeBehavior(E->getExprLoc(), E,
S.PDiag(diag::warn_impcast_fixed_point_range)
- << Value.toString(/*Radix=*/10) << T
+ << toString(Value, /*Radix=*/10) << T
<< E->getSourceRange()
<< clang::SourceRange(CC));
return;
@@ -12255,7 +12787,8 @@
llvm::APFloat::rmNearestTiesToEven);
if (ConversionStatus != llvm::APFloat::opOK) {
- std::string PrettySourceValue = SourceInt->toString(10);
+ SmallString<32> PrettySourceValue;
+ SourceInt->toString(PrettySourceValue, 10);
SmallString<32> PrettyTargetValue;
TargetFloatValue.toString(PrettyTargetValue, TargetPrecision);
@@ -12314,7 +12847,7 @@
if (S.SourceMgr.isInSystemMacro(CC))
return;
- std::string PrettySourceValue = Value.toString(10);
+ std::string PrettySourceValue = toString(Value, 10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
S.DiagRuntimeBehavior(
@@ -12360,7 +12893,7 @@
!S.SourceMgr.isInSystemMacro(CC)) {
llvm::APSInt Value = Result.Val.getInt();
if (isSameWidthConstantConversion(S, E, T, CC)) {
- std::string PrettySourceValue = Value.toString(10);
+ std::string PrettySourceValue = toString(Value, 10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
S.DiagRuntimeBehavior(
@@ -14046,7 +14579,8 @@
case Stmt::MemberExprClass: {
auto *ME = cast<MemberExpr>(E);
auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
- if (!FD || FD->getType()->isReferenceType())
+ if (!FD || FD->getType()->isReferenceType() ||
+ FD->getParent()->isInvalidDecl())
break;
Optional<std::pair<CharUnits, CharUnits>> P;
if (ME->isArrow())
@@ -14270,11 +14804,11 @@
const ConstantArrayType *ArrayTy =
Context.getAsConstantArrayType(BaseExpr->getType());
- if (!ArrayTy)
- return;
-
- const Type *BaseType = ArrayTy->getElementType().getTypePtr();
- if (EffectiveType->isDependentType() || BaseType->isDependentType())
+ const Type *BaseType =
+ ArrayTy == nullptr ? nullptr : ArrayTy->getElementType().getTypePtr();
+ bool IsUnboundedArray = (BaseType == nullptr);
+ if (EffectiveType->isDependentType() ||
+ (!IsUnboundedArray && BaseType->isDependentType()))
return;
Expr::EvalResult Result;
@@ -14282,8 +14816,10 @@
return;
llvm::APSInt index = Result.Val.getInt();
- if (IndexNegated)
+ if (IndexNegated) {
+ index.setIsUnsigned(false);
index = -index;
+ }
const NamedDecl *ND = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
@@ -14291,6 +14827,74 @@
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = ME->getMemberDecl();
+ if (IsUnboundedArray) {
+ if (index.isUnsigned() || !index.isNegative()) {
+ const auto &ASTC = getASTContext();
+ unsigned AddrBits =
+ ASTC.getTargetInfo().getPointerWidth(ASTC.getTargetAddressSpace(
+ EffectiveType->getCanonicalTypeInternal()));
+ if (index.getBitWidth() < AddrBits)
+ index = index.zext(AddrBits);
+ Optional<CharUnits> ElemCharUnits =
+ ASTC.getTypeSizeInCharsIfKnown(EffectiveType);
+ // PR50741 - If EffectiveType has unknown size (e.g., if it's a void
+ // pointer) bounds-checking isn't meaningful.
+ if (!ElemCharUnits)
+ return;
+ llvm::APInt ElemBytes(index.getBitWidth(), ElemCharUnits->getQuantity());
+ // If index has more active bits than address space, we already know
+ // we have a bounds violation to warn about. Otherwise, compute
+ // address of (index + 1)th element, and warn about bounds violation
+ // only if that address exceeds address space.
+ if (index.getActiveBits() <= AddrBits) {
+ bool Overflow;
+ llvm::APInt Product(index);
+ Product += 1;
+ Product = Product.umul_ov(ElemBytes, Overflow);
+ if (!Overflow && Product.getActiveBits() <= AddrBits)
+ return;
+ }
+
+ // Need to compute max possible elements in address space, since that
+ // is included in diag message.
+ llvm::APInt MaxElems = llvm::APInt::getMaxValue(AddrBits);
+ MaxElems = MaxElems.zext(std::max(AddrBits + 1, ElemBytes.getBitWidth()));
+ MaxElems += 1;
+ ElemBytes = ElemBytes.zextOrTrunc(MaxElems.getBitWidth());
+ MaxElems = MaxElems.udiv(ElemBytes);
+
+ unsigned DiagID =
+ ASE ? diag::warn_array_index_exceeds_max_addressable_bounds
+ : diag::warn_ptr_arith_exceeds_max_addressable_bounds;
+
+ // Diag message shows element size in bits and in "bytes" (platform-
+ // dependent CharUnits)
+ DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
+ PDiag(DiagID)
+ << toString(index, 10, true) << AddrBits
+ << (unsigned)ASTC.toBits(*ElemCharUnits)
+ << toString(ElemBytes, 10, false)
+ << toString(MaxElems, 10, false)
+ << (unsigned)MaxElems.getLimitedValue(~0U)
+ << IndexExpr->getSourceRange());
+
+ if (!ND) {
+ // Try harder to find a NamedDecl to point at in the note.
+ while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
+ BaseExpr = ASE->getBase()->IgnoreParenCasts();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+ ND = DRE->getDecl();
+ if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
+ ND = ME->getMemberDecl();
+ }
+
+ if (ND)
+ DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr,
+ PDiag(diag::note_array_declared_here) << ND);
+ }
+ return;
+ }
+
if (index.isUnsigned() || !index.isNegative()) {
// It is possible that the type of the base expression after
// IgnoreParenCasts is incomplete, even though the type of the base
@@ -14353,13 +14957,12 @@
}
}
- unsigned DiagID = diag::warn_ptr_arith_exceeds_bounds;
- if (ASE)
- DiagID = diag::warn_array_index_exceeds_bounds;
+ unsigned DiagID = ASE ? diag::warn_array_index_exceeds_bounds
+ : diag::warn_ptr_arith_exceeds_bounds;
DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
- PDiag(DiagID) << index.toString(10, true)
- << size.toString(10, true)
+ PDiag(DiagID) << toString(index, 10, true)
+ << toString(size, 10, true)
<< (unsigned)size.getLimitedValue(~0U)
<< IndexExpr->getSourceRange());
} else {
@@ -14370,18 +14973,17 @@
}
DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
- PDiag(DiagID) << index.toString(10, true)
+ PDiag(DiagID) << toString(index, 10, true)
<< IndexExpr->getSourceRange());
}
if (!ND) {
// Try harder to find a NamedDecl to point at in the note.
- while (const ArraySubscriptExpr *ASE =
- dyn_cast<ArraySubscriptExpr>(BaseExpr))
+ while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
BaseExpr = ASE->getBase()->IgnoreParenCasts();
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
ND = DRE->getDecl();
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
+ if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = ME->getMemberDecl();
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp b/src/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
index be04970..e03b671 100644
--- a/src/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
@@ -381,6 +381,8 @@
} // namespace
void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
+ if (!Enabled)
+ return;
if (isa<BlockDecl>(S.CurContext)) {
if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {
ComputeType = nullptr;
@@ -399,14 +401,30 @@
}
void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) {
+ if (!Enabled)
+ return;
auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
ComputeType = nullptr;
Type = VD ? VD->getType() : QualType();
ExpectedLoc = Tok;
}
+static QualType getDesignatedType(QualType BaseType, const Designation &Desig);
+
+void PreferredTypeBuilder::enterDesignatedInitializer(SourceLocation Tok,
+ QualType BaseType,
+ const Designation &D) {
+ if (!Enabled)
+ return;
+ ComputeType = nullptr;
+ Type = getDesignatedType(BaseType, D);
+ ExpectedLoc = Tok;
+}
+
void PreferredTypeBuilder::enterFunctionArgument(
SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) {
+ if (!Enabled)
+ return;
this->ComputeType = ComputeType;
Type = QualType();
ExpectedLoc = Tok;
@@ -414,6 +432,8 @@
void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok,
SourceLocation LParLoc) {
+ if (!Enabled)
+ return;
// expected type for parenthesized expression does not change.
if (ExpectedLoc == LParLoc)
ExpectedLoc = Tok;
@@ -531,6 +551,8 @@
void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS,
tok::TokenKind Op) {
+ if (!Enabled)
+ return;
ComputeType = nullptr;
Type = getPreferredTypeOfBinaryRHS(S, LHS, Op);
ExpectedLoc = Tok;
@@ -538,7 +560,7 @@
void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok,
Expr *Base) {
- if (!Base)
+ if (!Enabled || !Base)
return;
// Do we have expected type for Base?
if (ExpectedLoc != Base->getBeginLoc())
@@ -551,6 +573,8 @@
void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok,
tok::TokenKind OpKind,
SourceLocation OpLoc) {
+ if (!Enabled)
+ return;
ComputeType = nullptr;
Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind);
ExpectedLoc = Tok;
@@ -558,6 +582,8 @@
void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok,
Expr *LHS) {
+ if (!Enabled)
+ return;
ComputeType = nullptr;
Type = S.getASTContext().IntTy;
ExpectedLoc = Tok;
@@ -565,12 +591,16 @@
void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok,
QualType CastType) {
+ if (!Enabled)
+ return;
ComputeType = nullptr;
Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType();
ExpectedLoc = Tok;
}
void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) {
+ if (!Enabled)
+ return;
ComputeType = nullptr;
Type = S.getASTContext().BoolTy;
ExpectedLoc = Tok;
@@ -709,18 +739,17 @@
// Filter out names reserved for the implementation if they come from a
// system header.
static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
- const IdentifierInfo *Id = ND->getIdentifier();
- if (!Id)
- return false;
-
+ ReservedIdentifierStatus Status = ND->isReserved(SemaRef.getLangOpts());
// Ignore reserved names for compiler provided decls.
- if (Id->isReservedName() && ND->getLocation().isInvalid())
+ if ((Status != ReservedIdentifierStatus::NotReserved) &&
+ (Status != ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope) &&
+ ND->getLocation().isInvalid())
return true;
// For system headers ignore only double-underscore names.
// This allows for system headers providing private symbols with a single
// underscore.
- if (Id->isReservedName(/*doubleUnderscoreOnly=*/true) &&
+ if (Status == ReservedIdentifierStatus::StartsWithDoubleUnderscore &&
SemaRef.SourceMgr.isInSystemHeader(
SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
return true;
@@ -3886,6 +3915,9 @@
case Decl::UnresolvedUsingTypename:
return CXCursor_UsingDeclaration;
+ case Decl::UsingEnum:
+ return CXCursor_EnumDecl;
+
case Decl::ObjCPropertyImpl:
switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
case ObjCPropertyImplDecl::Dynamic:
@@ -4784,8 +4816,16 @@
// in case of specializations. Since we might not have a decl for the
// instantiation/specialization yet, e.g. dependent code.
static RecordDecl *getAsRecordDecl(const QualType BaseType) {
- if (auto *RD = BaseType->getAsRecordDecl())
+ if (auto *RD = BaseType->getAsRecordDecl()) {
+ if (const auto *CTSD =
+ llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ // Template might not be instantiated yet, fall back to primary template
+ // in such cases.
+ if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared)
+ RD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
+ }
return RD;
+ }
if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) {
if (const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(
@@ -5159,6 +5199,74 @@
llvm::DenseMap<const IdentifierInfo *, Member> Results;
};
+// Returns a type for E that yields acceptable member completions.
+// In particular, when E->getType() is DependentTy, try to guess a likely type.
+// We accept some lossiness (like dropping parameters).
+// We only try to handle common expressions on the LHS of MemberExpr.
+QualType getApproximateType(const Expr *E) {
+ QualType Unresolved = E->getType();
+ if (Unresolved.isNull() ||
+ !Unresolved->isSpecificBuiltinType(BuiltinType::Dependent))
+ return Unresolved;
+ E = E->IgnoreParens();
+ // A call: approximate-resolve callee to a function type, get its return type
+ if (const CallExpr *CE = llvm::dyn_cast<CallExpr>(E)) {
+ QualType Callee = getApproximateType(CE->getCallee());
+ if (Callee.isNull() ||
+ Callee->isSpecificPlaceholderType(BuiltinType::BoundMember))
+ Callee = Expr::findBoundMemberType(CE->getCallee());
+ if (Callee.isNull())
+ return Unresolved;
+
+ if (const auto *FnTypePtr = Callee->getAs<PointerType>()) {
+ Callee = FnTypePtr->getPointeeType();
+ } else if (const auto *BPT = Callee->getAs<BlockPointerType>()) {
+ Callee = BPT->getPointeeType();
+ }
+ if (const FunctionType *FnType = Callee->getAs<FunctionType>())
+ return FnType->getReturnType().getNonReferenceType();
+
+ // Unresolved call: try to guess the return type.
+ if (const auto *OE = llvm::dyn_cast<OverloadExpr>(CE->getCallee())) {
+ // If all candidates have the same approximate return type, use it.
+ // Discard references and const to allow more to be "the same".
+ // (In particular, if there's one candidate + ADL, resolve it).
+ const Type *Common = nullptr;
+ for (const auto *D : OE->decls()) {
+ QualType ReturnType;
+ if (const auto *FD = llvm::dyn_cast<FunctionDecl>(D))
+ ReturnType = FD->getReturnType();
+ else if (const auto *FTD = llvm::dyn_cast<FunctionTemplateDecl>(D))
+ ReturnType = FTD->getTemplatedDecl()->getReturnType();
+ if (ReturnType.isNull())
+ continue;
+ const Type *Candidate =
+ ReturnType.getNonReferenceType().getCanonicalType().getTypePtr();
+ if (Common && Common != Candidate)
+ return Unresolved; // Multiple candidates.
+ Common = Candidate;
+ }
+ if (Common != nullptr)
+ return QualType(Common, 0);
+ }
+ }
+ // A dependent member: approximate-resolve the base, then lookup.
+ if (const auto *CDSME = llvm::dyn_cast<CXXDependentScopeMemberExpr>(E)) {
+ QualType Base = CDSME->isImplicitAccess()
+ ? CDSME->getBaseType()
+ : getApproximateType(CDSME->getBase());
+ if (CDSME->isArrow() && !Base.isNull())
+ Base = Base->getPointeeType(); // could handle unique_ptr etc here?
+ RecordDecl *RD = Base.isNull() ? nullptr : getAsRecordDecl(Base);
+ if (RD && RD->isCompleteDefinition()) {
+ for (const auto *Member : RD->lookup(CDSME->getMember()))
+ if (const ValueDecl *VD = llvm::dyn_cast<ValueDecl>(Member))
+ return VD->getType().getNonReferenceType();
+ }
+ }
+ return Unresolved;
+}
+
// If \p Base is ParenListExpr, assume a chain of comma operators and pick the
// last expr. We expect other ParenListExprs to be resolved to e.g. constructor
// calls before here. (So the ParenListExpr should be nonempty, but check just
@@ -5187,7 +5295,7 @@
ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
if (ConvertedBase.isInvalid())
return;
- QualType ConvertedBaseType = ConvertedBase.get()->getType();
+ QualType ConvertedBaseType = getApproximateType(ConvertedBase.get());
enum CodeCompletionContext::Kind contextKind;
@@ -5223,7 +5331,7 @@
return false;
Base = ConvertedBase.get();
- QualType BaseType = Base->getType();
+ QualType BaseType = getApproximateType(Base);
if (BaseType.isNull())
return false;
ExprValueKind BaseKind = Base->getValueKind();
@@ -5605,8 +5713,9 @@
unsigned CurrentArg, SourceLocation OpenParLoc) {
if (Candidates.empty())
return QualType();
- SemaRef.CodeCompleter->ProcessOverloadCandidates(
- SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
+ if (SemaRef.getPreprocessor().isCodeCompletionReached())
+ SemaRef.CodeCompleter->ProcessOverloadCandidates(
+ SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
return getParamType(SemaRef, Candidates, CurrentArg);
}
@@ -5771,25 +5880,39 @@
return QualType();
}
-void Sema::CodeCompleteDesignator(const QualType BaseType,
+static QualType getDesignatedType(QualType BaseType, const Designation &Desig) {
+ for (unsigned I = 0; I < Desig.getNumDesignators(); ++I) {
+ if (BaseType.isNull())
+ break;
+ QualType NextType;
+ const auto &D = Desig.getDesignator(I);
+ if (D.isArrayDesignator() || D.isArrayRangeDesignator()) {
+ if (BaseType->isArrayType())
+ NextType = BaseType->getAsArrayTypeUnsafe()->getElementType();
+ } else {
+ assert(D.isFieldDesignator());
+ auto *RD = getAsRecordDecl(BaseType);
+ if (RD && RD->isCompleteDefinition()) {
+ for (const auto *Member : RD->lookup(D.getField()))
+ if (const FieldDecl *FD = llvm::dyn_cast<FieldDecl>(Member)) {
+ NextType = FD->getType();
+ break;
+ }
+ }
+ }
+ BaseType = NextType;
+ }
+ return BaseType;
+}
+
+void Sema::CodeCompleteDesignator(QualType BaseType,
llvm::ArrayRef<Expr *> InitExprs,
const Designation &D) {
+ BaseType = getDesignatedType(BaseType, D);
if (BaseType.isNull())
return;
- // FIXME: Handle nested designations, e.g. : .x.^
- if (!D.empty())
- return;
-
const auto *RD = getAsRecordDecl(BaseType);
- if (!RD)
- return;
- if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
- // Template might not be instantiated yet, fall back to primary template in
- // such cases.
- if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared)
- RD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
- }
- if (RD->fields().empty())
+ if (!RD || RD->fields().empty())
return;
CodeCompletionContext CCC(CodeCompletionContext::CCC_DotMemberAccess,
@@ -9078,6 +9201,18 @@
Builder.AddPlaceholderChunk("condition");
Results.AddResult(Builder.TakeString());
+ // #elifdef <macro>
+ Builder.AddTypedTextChunk("elifdef");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("macro");
+ Results.AddResult(Builder.TakeString());
+
+ // #elifndef <macro>
+ Builder.AddTypedTextChunk("elifndef");
+ Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Builder.AddPlaceholderChunk("macro");
+ Results.AddResult(Builder.TakeString());
+
// #else
Builder.AddTypedTextChunk("else");
Results.AddResult(Builder.TakeString());
@@ -9356,10 +9491,10 @@
// Only files that really look like headers. (Except in system dirs).
if (!IsSystem) {
// Header extensions from Types.def, which we can't depend on here.
- if (!(Filename.endswith_lower(".h") ||
- Filename.endswith_lower(".hh") ||
- Filename.endswith_lower(".hpp") ||
- Filename.endswith_lower(".inc")))
+ if (!(Filename.endswith_insensitive(".h") ||
+ Filename.endswith_insensitive(".hh") ||
+ Filename.endswith_insensitive(".hpp") ||
+ Filename.endswith_insensitive(".inc")))
break;
}
AddCompletion(Filename, /*IsDirectory=*/false);
diff --git a/src/llvm-project/clang/lib/Sema/SemaConcept.cpp b/src/llvm-project/clang/lib/Sema/SemaConcept.cpp
index 1ff7b1c..931c9e3 100644
--- a/src/llvm-project/clang/lib/Sema/SemaConcept.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaConcept.cpp
@@ -25,6 +25,8 @@
#include "clang/Basic/OperatorPrecedence.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringExtras.h"
+
using namespace clang;
using namespace sema;
@@ -41,9 +43,12 @@
LHS = BO->getLHS();
RHS = BO->getRHS();
} else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
- Op = OO->getOperator();
- LHS = OO->getArg(0);
- RHS = OO->getArg(1);
+ // If OO is not || or && it might not have exactly 2 arguments.
+ if (OO->getNumArgs() == 2) {
+ Op = OO->getOperator();
+ LHS = OO->getArg(0);
+ RHS = OO->getArg(1);
+ }
}
}
@@ -172,9 +177,11 @@
SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
Expr::EvalResult EvalResult;
EvalResult.Diag = &EvaluationDiags;
- if (!SubstitutedAtomicExpr.get()->EvaluateAsRValue(EvalResult, S.Context)) {
- // C++2a [temp.constr.atomic]p1
- // ...E shall be a constant expression of type bool.
+ if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
+ S.Context) ||
+ !EvaluationDiags.empty()) {
+ // C++2a [temp.constr.atomic]p1
+ // ...E shall be a constant expression of type bool.
S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
diag::err_non_constant_constraint_expression)
<< SubstitutedAtomicExpr.get()->getSourceRange();
@@ -183,6 +190,8 @@
return true;
}
+ assert(EvalResult.Val.isInt() &&
+ "evaluating bool expression didn't produce int");
Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
if (!Satisfaction.IsSatisfied)
Satisfaction.Details.emplace_back(ConstraintExpr,
@@ -214,6 +223,13 @@
Sema::SFINAETrap Trap(S);
SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
MLTAL);
+ // Substitution might have stripped off a contextual conversion to
+ // bool if this is the operand of an '&&' or '||'. For example, we
+ // might lose an lvalue-to-rvalue conversion here. If so, put it back
+ // before we try to evaluate.
+ if (!SubstitutedExpression.isInvalid())
+ SubstitutedExpression =
+ S.PerformContextuallyConvertToBool(SubstitutedExpression.get());
if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
// C++2a [temp.constr.atomic]p1
// ...If substitution results in an invalid type or expression, the
@@ -439,18 +455,19 @@
case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
ConceptSpecializationExpr *ConstraintExpr =
Req->getReturnTypeRequirementSubstitutedConstraintExpr();
- if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1)
+ if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
// A simple case - expr type is the type being constrained and the concept
// was not provided arguments.
- S.Diag(ConstraintExpr->getBeginLoc(),
+ Expr *e = Req->getExpr();
+ S.Diag(e->getBeginLoc(),
diag::note_expr_requirement_constraints_not_satisfied_simple)
- << (int)First << S.BuildDecltypeType(Req->getExpr(),
- Req->getExpr()->getBeginLoc())
+ << (int)First << S.getDecltypeForParenthesizedExpr(e)
<< ConstraintExpr->getNamedConcept();
- else
+ } else {
S.Diag(ConstraintExpr->getBeginLoc(),
diag::note_expr_requirement_constraints_not_satisfied)
<< (int)First << ConstraintExpr;
+ }
S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
break;
}
@@ -522,9 +539,9 @@
diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
/*First=*/false);
return;
- case BO_LAnd:
- bool LHSSatisfied;
- BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
+ case BO_LAnd: {
+ bool LHSSatisfied =
+ BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
if (LHSSatisfied) {
// LHS is true, so RHS must be false.
diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
@@ -534,12 +551,13 @@
diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
// RHS might also be false
- bool RHSSatisfied;
- BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
+ bool RHSSatisfied =
+ BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
if (!RHSSatisfied)
diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
/*First=*/false);
return;
+ }
case BO_GE:
case BO_LE:
case BO_GT:
@@ -550,15 +568,19 @@
BO->getRHS()->getType()->isIntegerType()) {
Expr::EvalResult SimplifiedLHS;
Expr::EvalResult SimplifiedRHS;
- BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
- BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
+ BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
+ Expr::SE_NoSideEffects,
+ /*InConstantContext=*/true);
+ BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
+ Expr::SE_NoSideEffects,
+ /*InConstantContext=*/true);
if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
S.Diag(SubstExpr->getBeginLoc(),
diag::note_atomic_constraint_evaluated_to_false_elaborated)
<< (int)First << SubstExpr
- << SimplifiedLHS.Val.getInt().toString(10)
+ << toString(SimplifiedLHS.Val.getInt(), 10)
<< BinaryOperator::getOpcodeStr(BO->getOpcode())
- << SimplifiedRHS.Val.getInt().toString(10);
+ << toString(SimplifiedRHS.Val.getInt(), 10);
return;
}
}
@@ -720,22 +742,15 @@
NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
ArrayRef<const Expr *> E) {
assert(E.size() != 0);
- auto First = fromConstraintExpr(S, D, E[0]);
- if (E.size() == 1)
- return First;
- auto Second = fromConstraintExpr(S, D, E[1]);
- if (!Second)
+ auto Conjunction = fromConstraintExpr(S, D, E[0]);
+ if (!Conjunction)
return None;
- llvm::Optional<NormalizedConstraint> Conjunction;
- Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
- CCK_Conjunction);
- for (unsigned I = 2; I < E.size(); ++I) {
+ for (unsigned I = 1; I < E.size(); ++I) {
auto Next = fromConstraintExpr(S, D, E[I]);
if (!Next)
- return llvm::Optional<NormalizedConstraint>{};
- NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
+ return None;
+ *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
std::move(*Next), CCK_Conjunction);
- *Conjunction = std::move(NewConjunction);
}
return Conjunction;
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaCoroutine.cpp b/src/llvm-project/clang/lib/Sema/SemaCoroutine.cpp
index 7a48bfa..94c7280 100644
--- a/src/llvm-project/clang/lib/Sema/SemaCoroutine.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaCoroutine.cpp
@@ -291,26 +291,6 @@
cast<UnresolvedLookupExpr>(R.get()));
}
-static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id,
- MultiExprArg CallArgs) {
- StringRef Name = S.Context.BuiltinInfo.getName(Id);
- LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName);
- S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true);
-
- auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
- assert(BuiltInDecl && "failed to find builtin declaration");
-
- ExprResult DeclRef =
- S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
- assert(DeclRef.isUsable() && "Builtin reference cannot fail");
-
- ExprResult Call =
- S.BuildCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
-
- assert(!Call.isInvalid() && "Call to builtin cannot fail!");
- return Call.get();
-}
-
static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType,
SourceLocation Loc) {
QualType CoroHandleType = lookupCoroutineHandleType(S, PromiseType, Loc);
@@ -327,7 +307,7 @@
}
Expr *FramePtr =
- buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
+ S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
CXXScopeSpec SS;
ExprResult FromAddr =
@@ -404,8 +384,8 @@
// the resume call and return instruction, which would interfere with the
// musttail call contract.
JustAddress = S.MaybeCreateExprWithCleanups(JustAddress);
- return buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_resume,
- JustAddress);
+ return S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_resume,
+ JustAddress);
}
/// Build calls to await_ready, await_suspend, and await_resume for a co_await
@@ -897,7 +877,7 @@
// If the expression is a temporary, materialize it as an lvalue so that we
// can use it multiple times.
- if (E->getValueKind() == VK_RValue)
+ if (E->isPRValue())
E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
// The location of the `co_await` token cannot be used when constructing
@@ -957,7 +937,7 @@
// If the expression is a temporary, materialize it as an lvalue so that we
// can use it multiple times.
- if (E->getValueKind() == VK_RValue)
+ if (E->isPRValue())
E = CreateMaterializeTemporaryExpr(E->getType(), E, true);
// Build the await_ready, await_suspend, await_resume calls.
@@ -994,25 +974,10 @@
E = R.get();
}
- // Move the return value if we can
- if (E) {
- auto NRVOCandidate = this->getCopyElisionCandidate(E->getType(), E, CES_AsIfByStdMove);
- if (NRVOCandidate) {
- InitializedEntity Entity =
- InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate);
- ExprResult MoveResult = this->PerformMoveOrCopyInitialization(
- Entity, NRVOCandidate, E->getType(), E);
- if (MoveResult.get())
- E = MoveResult.get();
- }
- }
-
- // FIXME: If the operand is a reference to a variable that's about to go out
- // of scope, we should treat the operand as an xvalue for this overload
- // resolution.
VarDecl *Promise = FSI->CoroutinePromise;
ExprResult PC;
if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
+ getNamedReturnInfo(E, SimplerImplicitMoveMode::ForceOn);
PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
} else {
E = MakeFullDiscardedValueExpr(E).get();
@@ -1372,10 +1337,10 @@
return false;
Expr *FramePtr =
- buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
+ S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});
Expr *FrameSize =
- buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {});
+ S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});
// Make new call.
@@ -1404,7 +1369,7 @@
return false;
Expr *CoroFree =
- buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr});
+ S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr});
SmallVector<Expr *, 2> DeleteArgs{CoroFree};
@@ -1569,7 +1534,7 @@
// Trigger a nice error message.
InitializedEntity Entity =
InitializedEntity::InitializeResult(Loc, FnRetType, false);
- S.PerformMoveOrCopyInitialization(Entity, nullptr, FnRetType, ReturnValue);
+ S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
noteMemberDeclaredHere(S, ReturnValue, Fn);
return false;
}
@@ -1585,8 +1550,8 @@
return false;
InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl);
- ExprResult Res = S.PerformMoveOrCopyInitialization(Entity, nullptr, GroType,
- this->ReturnValue);
+ ExprResult Res =
+ S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);
if (Res.isInvalid())
return false;
diff --git a/src/llvm-project/clang/lib/Sema/SemaDecl.cpp b/src/llvm-project/clang/lib/Sema/SemaDecl.cpp
index 1f7ab49..205f580 100644
--- a/src/llvm-project/clang/lib/Sema/SemaDecl.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaDecl.cpp
@@ -434,10 +434,14 @@
// Look to see if we have a type anywhere in the list of results.
for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end();
Res != ResEnd; ++Res) {
- if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res) ||
- (AllowDeducedTemplate && getAsTypeTemplateDecl(*Res))) {
- if (!IIDecl || (*Res)->getLocation() < IIDecl->getLocation())
- IIDecl = *Res;
+ NamedDecl *RealRes = (*Res)->getUnderlyingDecl();
+ if (isa<TypeDecl, ObjCInterfaceDecl, UnresolvedUsingIfExistsDecl>(
+ RealRes) ||
+ (AllowDeducedTemplate && getAsTypeTemplateDecl(RealRes))) {
+ if (!IIDecl ||
+ // Make the selection of the recovery decl deterministic.
+ RealRes->getLocation() < IIDecl->getLocation())
+ IIDecl = RealRes;
}
}
@@ -486,6 +490,10 @@
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
if (!HasTrailingDot)
T = Context.getObjCInterfaceType(IDecl);
+ } else if (auto *UD = dyn_cast<UnresolvedUsingIfExistsDecl>(IIDecl)) {
+ (void)DiagnoseUseOfDecl(UD, NameLoc);
+ // Recover with 'int'
+ T = Context.IntTy;
} else if (AllowDeducedTemplate) {
if (auto *TD = getAsTypeTemplateDecl(IIDecl))
T = Context.getDeducedTemplateSpecializationType(TemplateName(TD),
@@ -502,7 +510,7 @@
// constructor or destructor name (in such a case, the scope specifier
// will be attached to the enclosing Expr or Decl node).
if (SS && SS->isNotEmpty() && !IsCtorOrDtorName &&
- !isa<ObjCInterfaceDecl>(IIDecl)) {
+ !isa<ObjCInterfaceDecl, UnresolvedUsingIfExistsDecl>(IIDecl)) {
if (WantNontrivialTypeSourceInfo) {
// Construct a type with type-source information.
TypeLocBuilder Builder;
@@ -1161,6 +1169,11 @@
return NameClassification::Concept(
TemplateName(cast<TemplateDecl>(FirstDecl)));
+ if (auto *EmptyD = dyn_cast<UnresolvedUsingIfExistsDecl>(FirstDecl)) {
+ (void)DiagnoseUseOfDecl(EmptyD, NameLoc);
+ return NameClassification::Error();
+ }
+
// We can have a type template here if we're classifying a template argument.
if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl) &&
!isa<VarTemplateDecl>(FirstDecl))
@@ -1516,6 +1529,7 @@
} else {
IdResolver.AddDecl(D);
}
+ warnOnReservedIdentifier(D);
}
bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S,
@@ -1905,6 +1919,41 @@
Diag(D->getLocation(), DiagID) << D << Hint;
}
+void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD) {
+ // If it's not referenced, it can't be set.
+ if (!VD->isReferenced() || !VD->getDeclName() || VD->hasAttr<UnusedAttr>())
+ return;
+
+ const auto *Ty = VD->getType().getTypePtr()->getBaseElementTypeUnsafe();
+
+ if (Ty->isReferenceType() || Ty->isDependentType())
+ return;
+
+ if (const TagType *TT = Ty->getAs<TagType>()) {
+ const TagDecl *Tag = TT->getDecl();
+ if (Tag->hasAttr<UnusedAttr>())
+ return;
+ // In C++, don't warn for record types that don't have WarnUnusedAttr, to
+ // mimic gcc's behavior.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) {
+ if (!RD->hasAttr<WarnUnusedAttr>())
+ return;
+ }
+ }
+
+ auto iter = RefsMinusAssignments.find(VD);
+ if (iter == RefsMinusAssignments.end())
+ return;
+
+ assert(iter->getSecond() >= 0 &&
+ "Found a negative number of references to a VarDecl");
+ if (iter->getSecond() != 0)
+ return;
+ unsigned DiagID = isa<ParmVarDecl>(VD) ? diag::warn_unused_but_set_parameter
+ : diag::warn_unused_but_set_variable;
+ Diag(VD->getLocation(), DiagID) << VD;
+}
+
static void CheckPoppedLabel(LabelDecl *L, Sema &S) {
// Verify that we have no forward references left. If so, there was a goto
// or address of a label taken, but no definition of it. Label fwd
@@ -1937,6 +1986,10 @@
DiagnoseUnusedDecl(D);
if (const auto *RD = dyn_cast<RecordDecl>(D))
DiagnoseUnusedNestedTypedefs(RD);
+ if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ DiagnoseUnusedButSetDecl(VD);
+ RefsMinusAssignments.erase(VD);
+ }
}
if (!D->getDeclName()) continue;
@@ -2540,9 +2593,18 @@
return AnyAdded;
}
+#define WANT_DECL_MERGE_LOGIC
+#include "clang/Sema/AttrParsedAttrImpl.inc"
+#undef WANT_DECL_MERGE_LOGIC
+
static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
const InheritableAttr *Attr,
Sema::AvailabilityMergeKind AMK) {
+ // Diagnose any mutual exclusions between the attribute that we want to add
+ // and attributes that already exist on the declaration.
+ if (!DiagnoseMutualExclusions(S, D, Attr))
+ return false;
+
// This function copies an attribute Attr from a previous declaration to the
// new declaration D if the new declaration doesn't itself have that attribute
// yet or if that attribute allows duplicates.
@@ -2592,22 +2654,17 @@
NewAttr = S.mergeOptimizeNoneAttr(D, *OA);
else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
NewAttr = S.mergeInternalLinkageAttr(D, *InternalLinkageA);
- else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr))
- NewAttr = S.mergeCommonAttr(D, *CommonA);
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
NewAttr = nullptr;
else if ((isa<DeprecatedAttr>(Attr) || isa<UnavailableAttr>(Attr)) &&
(AMK == Sema::AMK_Override ||
- AMK == Sema::AMK_ProtocolImplementation))
+ AMK == Sema::AMK_ProtocolImplementation ||
+ AMK == Sema::AMK_OptionalProtocolImplementation))
NewAttr = nullptr;
else if (const auto *UA = dyn_cast<UuidAttr>(Attr))
NewAttr = S.mergeUuidAttr(D, *UA, UA->getGuid(), UA->getGuidDecl());
- else if (const auto *SLHA = dyn_cast<SpeculativeLoadHardeningAttr>(Attr))
- NewAttr = S.mergeSpeculativeLoadHardeningAttr(D, *SLHA);
- else if (const auto *SLHA = dyn_cast<NoSpeculativeLoadHardeningAttr>(Attr))
- NewAttr = S.mergeNoSpeculativeLoadHardeningAttr(D, *SLHA);
else if (const auto *IMA = dyn_cast<WebAssemblyImportModuleAttr>(Attr))
NewAttr = S.mergeImportModuleAttr(D, *IMA);
else if (const auto *INA = dyn_cast<WebAssemblyImportNameAttr>(Attr))
@@ -2831,6 +2888,11 @@
NewAttr->setInherited(true);
New->addAttr(NewAttr);
}
+ if (RetainAttr *OldAttr = Old->getMostRecentDecl()->getAttr<RetainAttr>()) {
+ RetainAttr *NewAttr = OldAttr->clone(Context);
+ NewAttr->setInherited(true);
+ New->addAttr(NewAttr);
+ }
if (!Old->hasAttrs() && !New->hasAttrs())
return;
@@ -2947,13 +3009,14 @@
case AMK_Redeclaration:
case AMK_Override:
case AMK_ProtocolImplementation:
+ case AMK_OptionalProtocolImplementation:
LocalAMK = AMK;
break;
}
}
// Already handled.
- if (isa<UsedAttr>(I))
+ if (isa<UsedAttr>(I) || isa<RetainAttr>(I))
continue;
if (mergeDeclAttribute(*this, New, I, LocalAMK))
@@ -3102,6 +3165,7 @@
template<typename T> static bool isExternC(T *D) { return D->isExternC(); }
static bool isExternC(VarTemplateDecl *) { return false; }
+static bool isExternC(FunctionTemplateDecl *) { return false; }
/// Check whether a redeclaration of an entity introduced by a
/// using-declaration is valid, given that we know it's not an overload
@@ -3136,7 +3200,7 @@
if (!Old) {
S.Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
S.Diag(OldS->getTargetDecl()->getLocation(), diag::note_using_decl_target);
- S.Diag(OldS->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ S.Diag(OldS->getIntroducer()->getLocation(), diag::note_using_decl) << 0;
return true;
}
return false;
@@ -3221,15 +3285,25 @@
Diag(New->getLocation(), diag::err_using_decl_friend);
Diag(Shadow->getTargetDecl()->getLocation(),
diag::note_using_decl_target);
- Diag(Shadow->getUsingDecl()->getLocation(),
- diag::note_using_decl) << 0;
+ Diag(Shadow->getIntroducer()->getLocation(), diag::note_using_decl)
+ << 0;
return true;
}
- // Check whether the two declarations might declare the same function.
- if (checkUsingShadowRedecl<FunctionDecl>(*this, Shadow, New))
- return true;
- OldD = Old = cast<FunctionDecl>(Shadow->getTargetDecl());
+ // Check whether the two declarations might declare the same function or
+ // function template.
+ if (FunctionTemplateDecl *NewTemplate =
+ New->getDescribedFunctionTemplate()) {
+ if (checkUsingShadowRedecl<FunctionTemplateDecl>(*this, Shadow,
+ NewTemplate))
+ return true;
+ OldD = Old = cast<FunctionTemplateDecl>(Shadow->getTargetDecl())
+ ->getAsFunction();
+ } else {
+ if (checkUsingShadowRedecl<FunctionDecl>(*this, Shadow, New))
+ return true;
+ OldD = Old = cast<FunctionDecl>(Shadow->getTargetDecl());
+ }
} else {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
@@ -3852,10 +3926,11 @@
ObjCMethodDecl *oldMethod) {
// Merge the attributes, including deprecated/unavailable
AvailabilityMergeKind MergeKind =
- isa<ObjCProtocolDecl>(oldMethod->getDeclContext())
- ? AMK_ProtocolImplementation
- : isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
- : AMK_Override;
+ isa<ObjCProtocolDecl>(oldMethod->getDeclContext())
+ ? (oldMethod->isOptional() ? AMK_OptionalProtocolImplementation
+ : AMK_ProtocolImplementation)
+ : isa<ObjCImplDecl>(newMethod->getDeclContext()) ? AMK_Redeclaration
+ : AMK_Override;
mergeDeclAttributes(newMethod, oldMethod, MergeKind);
@@ -5206,7 +5281,8 @@
// trivial in almost all cases, except if a union member has an in-class
// initializer:
// union { int n = 0; };
- ActOnUninitializedDecl(Anon);
+ if (!Invalid)
+ ActOnUninitializedDecl(Anon);
}
Anon->setImplicit();
@@ -5351,10 +5427,8 @@
case UnqualifiedIdKind::IK_OperatorFunctionId:
NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator));
- NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc =
- Name.OperatorFunctionId.SymbolLocations[0].getRawEncoding();
- NameInfo.getInfo().CXXOperatorName.EndOpNameLoc
- = Name.EndLocation.getRawEncoding();
+ NameInfo.setCXXOperatorNameRange(SourceRange(
+ Name.OperatorFunctionId.SymbolLocations[0], Name.EndLocation));
return NameInfo;
case UnqualifiedIdKind::IK_LiteralOperatorId:
@@ -5551,6 +5625,18 @@
return false;
}
+void Sema::warnOnReservedIdentifier(const NamedDecl *D) {
+ // Avoid warning twice on the same identifier, and don't warn on redeclaration
+ // of system decl.
+ if (D->getPreviousDecl() || D->isImplicit())
+ return;
+ ReservedIdentifierStatus Status = D->isReserved(getLangOpts());
+ if (Status != ReservedIdentifierStatus::NotReserved &&
+ !Context.getSourceManager().isInSystemHeader(D->getLocation()))
+ Diag(D->getLocation(), diag::warn_reserved_extern_symbol)
+ << D << static_cast<int>(Status);
+}
+
Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg());
@@ -5559,9 +5645,6 @@
Dcl && Dcl->getDeclContext()->isFileContext())
Dcl->setTopLevelDeclInObjCContainer();
- if (getLangOpts().OpenCL)
- setCurrentOpenCLExtensionForDecl(Dcl);
-
return Dcl;
}
@@ -6035,26 +6118,26 @@
/// Attempt to fold a variable-sized type to a constant-sized type, returning
/// true if we were successful.
-static bool tryToFixVariablyModifiedVarType(Sema &S, TypeSourceInfo *&TInfo,
- QualType &T, SourceLocation Loc,
- unsigned FailedFoldDiagID) {
+bool Sema::tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo,
+ QualType &T, SourceLocation Loc,
+ unsigned FailedFoldDiagID) {
bool SizeIsNegative;
llvm::APSInt Oversized;
TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(
- TInfo, S.Context, SizeIsNegative, Oversized);
+ TInfo, Context, SizeIsNegative, Oversized);
if (FixedTInfo) {
- S.Diag(Loc, diag::ext_vla_folded_to_constant);
+ Diag(Loc, diag::ext_vla_folded_to_constant);
TInfo = FixedTInfo;
T = FixedTInfo->getType();
return true;
}
if (SizeIsNegative)
- S.Diag(Loc, diag::err_typecheck_negative_array_size);
+ Diag(Loc, diag::err_typecheck_negative_array_size);
else if (Oversized.getBoolValue())
- S.Diag(Loc, diag::err_array_too_large) << Oversized.toString(10);
+ Diag(Loc, diag::err_array_too_large) << toString(Oversized, 10);
else if (FailedFoldDiagID)
- S.Diag(Loc, FailedFoldDiagID);
+ Diag(Loc, FailedFoldDiagID);
return false;
}
@@ -6172,7 +6255,7 @@
Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope);
else if (Oversized.getBoolValue())
Diag(NewTD->getLocation(), diag::err_array_too_large)
- << Oversized.toString(10);
+ << toString(Oversized, 10);
else
Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope);
NewTD->setInvalidDecl();
@@ -6341,7 +6424,11 @@
if (Type->isSamplerT() || Type->isVoidType())
return;
LangAS ImplAS = LangAS::opencl_private;
- if ((getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) &&
+ // OpenCL C v3.0 s6.7.8 - For OpenCL C 2.0 or with the
+ // __opencl_c_program_scope_global_variables feature, the address space
+ // for a variable at program scope or a static or extern variable inside
+ // a function are inferred to be __global.
+ if (getOpenCLOptions().areProgramScopeVariablesSupported(getLangOpts()) &&
Var->hasGlobalStorage())
ImplAS = LangAS::opencl_global;
// If the original type from a decayed type is an array type and that array
@@ -6434,16 +6521,6 @@
}
}
- // Virtual functions cannot be marked as 'notail'.
- if (auto *Attr = ND.getAttr<NotTailCalledAttr>())
- if (auto *MD = dyn_cast<CXXMethodDecl>(&ND))
- if (MD->isVirtual()) {
- S.Diag(ND.getLocation(),
- diag::err_invalid_attribute_on_virtual_function)
- << Attr;
- ND.dropAttr<NotTailCalledAttr>();
- }
-
// Check the attributes on the function type, if any.
if (const auto *FD = dyn_cast<FunctionDecl>(&ND)) {
// Don't declare this variable in the second operand of the for-statement;
@@ -6727,17 +6804,20 @@
llvm_unreachable("Unknown type of decl!");
}
+
/// Returns true if there hasn't been any invalid type diagnosed.
-static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
- DeclContext *DC, QualType R) {
+static bool diagnoseOpenCLTypes(Sema &Se, VarDecl *NewVD) {
+ DeclContext *DC = NewVD->getDeclContext();
+ QualType R = NewVD->getType();
+
// OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
// OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
// argument.
if (R->isImageType() || R->isPipeType()) {
- Se.Diag(D.getIdentifierLoc(),
+ Se.Diag(NewVD->getLocation(),
diag::err_opencl_type_can_only_be_used_as_function_parameter)
<< R;
- D.setInvalidType();
+ NewVD->setInvalidDecl();
return false;
}
@@ -6746,35 +6826,40 @@
// OpenCL v2.0 s6.9.q:
// The clk_event_t and reserve_id_t types cannot be declared in program
// scope.
- if (NULL == S->getParent()) {
+ if (NewVD->hasGlobalStorage() && !NewVD->isStaticLocal()) {
if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) {
- Se.Diag(D.getIdentifierLoc(),
+ Se.Diag(NewVD->getLocation(),
diag::err_invalid_type_for_program_scope_var)
<< R;
- D.setInvalidType();
+ NewVD->setInvalidDecl();
return false;
}
}
// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
- if (!Se.getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) {
- QualType NR = R;
- while (NR->isPointerType() || NR->isMemberFunctionPointerType()) {
- if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType()) {
- Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
- D.setInvalidType();
+ if (!Se.getOpenCLOptions().isAvailableOption("__cl_clang_function_pointers",
+ Se.getLangOpts())) {
+ QualType NR = R.getCanonicalType();
+ while (NR->isPointerType() || NR->isMemberFunctionPointerType() ||
+ NR->isReferenceType()) {
+ if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType() ||
+ NR->isFunctionReferenceType()) {
+ Se.Diag(NewVD->getLocation(), diag::err_opencl_function_pointer)
+ << NR->isReferenceType();
+ NewVD->setInvalidDecl();
return false;
}
NR = NR->getPointeeType();
}
}
- if (!Se.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
+ if (!Se.getOpenCLOptions().isAvailableOption("cl_khr_fp16",
+ Se.getLangOpts())) {
// OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
// half array type (unless the cl_khr_fp16 extension is enabled).
if (Se.Context.getBaseElementType(R)->isHalfType()) {
- Se.Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
- D.setInvalidType();
+ Se.Diag(NewVD->getLocation(), diag::err_opencl_half_declaration) << R;
+ NewVD->setInvalidDecl();
return false;
}
}
@@ -6784,34 +6869,20 @@
// address space qualifiers.
if (R->isEventT()) {
if (R.getAddressSpace() != LangAS::opencl_private) {
- Se.Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual);
- D.setInvalidType();
+ Se.Diag(NewVD->getBeginLoc(), diag::err_event_t_addr_space_qual);
+ NewVD->setInvalidDecl();
return false;
}
}
- // C++ for OpenCL does not allow the thread_local storage qualifier.
- // OpenCL C does not support thread_local either, and
- // also reject all other thread storage class specifiers.
- DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
- if (TSC != TSCS_unspecified) {
- bool IsCXX = Se.getLangOpts().OpenCLCPlusPlus;
- Se.Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
- diag::err_opencl_unknown_type_specifier)
- << IsCXX << Se.getLangOpts().getOpenCLVersionTuple().getAsString()
- << DeclSpec::getSpecifierName(TSC) << 1;
- D.setInvalidType();
- return false;
- }
-
if (R->isSamplerT()) {
// OpenCL v1.2 s6.9.b p4:
// The sampler type cannot be used with the __local and __global address
// space qualifiers.
if (R.getAddressSpace() == LangAS::opencl_local ||
R.getAddressSpace() == LangAS::opencl_global) {
- Se.Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
- D.setInvalidType();
+ Se.Diag(NewVD->getLocation(), diag::err_wrong_sampler_addressspace);
+ NewVD->setInvalidDecl();
}
// OpenCL v1.2 s6.12.14.1:
@@ -6820,15 +6891,26 @@
if (DC->isTranslationUnit() &&
!(R.getAddressSpace() == LangAS::opencl_constant ||
R.isConstQualified())) {
- Se.Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler);
- D.setInvalidType();
+ Se.Diag(NewVD->getLocation(), diag::err_opencl_nonconst_global_sampler);
+ NewVD->setInvalidDecl();
}
- if (D.isInvalidType())
+ if (NewVD->isInvalidDecl())
return false;
}
+
return true;
}
+template <typename AttrTy>
+static void copyAttrFromTypedefToDecl(Sema &S, Decl *D, const TypedefType *TT) {
+ const TypedefNameDecl *TND = TT->getDecl();
+ if (const auto *Attribute = TND->getAttr<AttrTy>()) {
+ AttrTy *Clone = Attribute->clone(S.Context);
+ Clone->setInherited(true);
+ D->addAttr(Clone);
+ }
+}
+
NamedDecl *Sema::ActOnVariableDeclarator(
Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
@@ -6898,10 +6980,10 @@
}
}
- // If this variable has a variable-modified type and an initializer, try to
+ // If this variable has a VLA type and an initializer, try to
// fold to a constant-sized type. This is otherwise invalid.
- if (D.hasInitializer() && R->isVariablyModifiedType())
- tryToFixVariablyModifiedVarType(*this, TInfo, R, D.getIdentifierLoc(),
+ if (D.hasInitializer() && R->isVariableArrayType())
+ tryToFixVariablyModifiedVarType(TInfo, R, D.getIdentifierLoc(),
/*DiagID=*/0);
bool IsMemberSpecialization = false;
@@ -7176,7 +7258,6 @@
case ConstexprSpecKind::Constexpr:
NewVD->setConstexpr(true);
- MaybeAddCUDAConstantAttr(NewVD);
// C++1z [dcl.spec.constexpr]p1:
// A static data member declared with the constexpr specifier is
// implicitly an inline variable.
@@ -7242,15 +7323,30 @@
}
if (getLangOpts().OpenCL) {
-
deduceOpenCLAddressSpace(NewVD);
- diagnoseOpenCLTypes(S, *this, D, DC, NewVD->getType());
+ DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
+ if (TSC != TSCS_unspecified) {
+ bool IsCXX = getLangOpts().OpenCLCPlusPlus;
+ Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+ diag::err_opencl_unknown_type_specifier)
+ << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString()
+ << DeclSpec::getSpecifierName(TSC) << 1;
+ NewVD->setInvalidDecl();
+ }
}
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewVD, D);
+ // FIXME: This is probably the wrong location to be doing this and we should
+ // probably be doing this for more attributes (especially for function
+ // pointer attributes such as format, warn_unused_result, etc.). Ideally
+ // the code to copy attributes would be generated by TableGen.
+ if (R->isFunctionPointerType())
+ if (const auto *TT = R->getAs<TypedefType>())
+ copyAttrFromTypedefToDecl<AllocSizeAttr>(*this, NewVD, TT);
+
if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
getLangOpts().SYCLIsDevice) {
if (EmitTLSUnsupportedError &&
@@ -7490,7 +7586,8 @@
SDK_StaticMember,
SDK_Field,
SDK_Typedef,
- SDK_Using
+ SDK_Using,
+ SDK_StructuredBinding
};
/// Determine what kind of declaration we're shadowing.
@@ -7500,6 +7597,8 @@
return SDK_Using;
else if (isa<TypedefDecl>(ShadowedDecl))
return SDK_Typedef;
+ else if (isa<BindingDecl>(ShadowedDecl))
+ return SDK_StructuredBinding;
else if (isa<RecordDecl>(OldDC))
return isa<FieldDecl>(ShadowedDecl) ? SDK_Field : SDK_StaticMember;
@@ -7539,9 +7638,8 @@
return nullptr;
NamedDecl *ShadowedDecl = R.getFoundDecl();
- return isa<VarDecl>(ShadowedDecl) || isa<FieldDecl>(ShadowedDecl)
- ? ShadowedDecl
- : nullptr;
+ return isa<VarDecl, FieldDecl, BindingDecl>(ShadowedDecl) ? ShadowedDecl
+ : nullptr;
}
/// Return the declaration shadowed by the given typedef \p D, or null
@@ -7559,6 +7657,18 @@
return isa<TypedefNameDecl>(ShadowedDecl) ? ShadowedDecl : nullptr;
}
+/// Return the declaration shadowed by the given variable \p D, or null
+/// if it doesn't shadow any declaration or shadowing warnings are disabled.
+NamedDecl *Sema::getShadowedDeclaration(const BindingDecl *D,
+ const LookupResult &R) {
+ if (!shouldWarnIfShadowedDecl(Diags, R))
+ return nullptr;
+
+ NamedDecl *ShadowedDecl = R.getFoundDecl();
+ return isa<VarDecl, FieldDecl, BindingDecl>(ShadowedDecl) ? ShadowedDecl
+ : nullptr;
+}
+
/// Diagnose variable or built-in function shadowing. Implements
/// -Wshadow.
///
@@ -7878,7 +7988,8 @@
// OpenCL v1.2 s6.8 - The static qualifier is valid only in program
// scope.
if (getLangOpts().OpenCLVersion == 120 &&
- !getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers") &&
+ !getOpenCLOptions().isAvailableOption("cl_clang_storage_class_specifiers",
+ getLangOpts()) &&
NewVD->isStaticLocal()) {
Diag(NewVD->getLocation(), diag::err_static_function_scope);
NewVD->setInvalidDecl();
@@ -7886,6 +7997,9 @@
}
if (getLangOpts().OpenCL) {
+ if (!diagnoseOpenCLTypes(*this, NewVD))
+ return;
+
// OpenCL v2.0 s6.12.5 - The __block storage type is not supported.
if (NewVD->hasAttr<BlocksAttr>()) {
Diag(NewVD->getLocation(), diag::err_opencl_block_storage_type);
@@ -7907,23 +8021,17 @@
return;
}
}
- // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the
- // __constant address space.
- // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static
- // variables inside a function can also be declared in the global
- // address space.
- // C++ for OpenCL inherits rule from OpenCL C v2.0.
+
// FIXME: Adding local AS in C++ for OpenCL might make sense.
if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() ||
NewVD->hasExternalStorage()) {
- if (!T->isSamplerT() &&
- !T->isDependentType() &&
+ if (!T->isSamplerT() && !T->isDependentType() &&
!(T.getAddressSpace() == LangAS::opencl_constant ||
(T.getAddressSpace() == LangAS::opencl_global &&
- (getLangOpts().OpenCLVersion == 200 ||
- getLangOpts().OpenCLCPlusPlus)))) {
+ getOpenCLOptions().areProgramScopeVariablesSupported(
+ getLangOpts())))) {
int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1;
- if (getLangOpts().OpenCLVersion == 200 || getLangOpts().OpenCLCPlusPlus)
+ if (getOpenCLOptions().areProgramScopeVariablesSupported(getLangOpts()))
Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space)
<< Scope << "global or constant";
else
@@ -8613,7 +8721,10 @@
}
static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
- if (PT->isPointerType()) {
+ if (PT->isDependentType())
+ return InvalidKernelParam;
+
+ if (PT->isPointerType() || PT->isReferenceType()) {
QualType PointeeType = PT->getPointeeType();
if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
PointeeType.getAddressSpace() == LangAS::opencl_private ||
@@ -8630,6 +8741,18 @@
return PtrPtrKernelParam;
}
+
+ // C++ for OpenCL v1.0 s2.4:
+ // Moreover the types used in parameters of the kernel functions must be:
+ // Standard layout types for pointer parameters. The same applies to
+ // reference if an implementation supports them in kernel parameters.
+ if (S.getLangOpts().OpenCLCPlusPlus &&
+ !S.getOpenCLOptions().isAvailableOption(
+ "__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
+ !PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
+ !PointeeType->isStandardLayoutType())
+ return InvalidKernelParam;
+
return PtrKernelParam;
}
@@ -8650,12 +8773,10 @@
// OpenCL extension spec v1.2 s9.5:
// This extension adds support for half scalar and vector types as built-in
// types that can be used for arithmetic operations, conversions etc.
- if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16") && PT->isHalfType())
+ if (!S.getOpenCLOptions().isAvailableOption("cl_khr_fp16", S.getLangOpts()) &&
+ PT->isHalfType())
return InvalidKernelParam;
- if (PT->isRecordType())
- return RecordKernelParam;
-
// Look into an array argument to check if it has a forbidden type.
if (PT->isArrayType()) {
const Type *UnderlyingTy = PT->getPointeeOrArrayElementType();
@@ -8665,6 +8786,19 @@
return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0));
}
+ // C++ for OpenCL v1.0 s2.4:
+ // Moreover the types used in parameters of the kernel functions must be:
+ // Trivial and standard-layout types C++17 [basic.types] (plain old data
+ // types) for parameters passed by value;
+ if (S.getLangOpts().OpenCLCPlusPlus &&
+ !S.getOpenCLOptions().isAvailableOption(
+ "__cl_clang_non_portable_kernel_param_types", S.getLangOpts()) &&
+ !PT->isOpenCLSpecificType() && !PT.isPODType(S.Context))
+ return InvalidKernelParam;
+
+ if (PT->isRecordType())
+ return RecordKernelParam;
+
return ValidKernelParam;
}
@@ -8685,7 +8819,7 @@
// OpenCL v3.0 s6.11.a:
// A kernel function argument cannot be declared as a pointer to a pointer
// type. [...] This restriction only applies to OpenCL C 1.2 or below.
- if (S.getLangOpts().OpenCLVersion < 120 &&
+ if (S.getLangOpts().OpenCLVersion <= 120 &&
!S.getLangOpts().OpenCLCPlusPlus) {
S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
D.setInvalidType();
@@ -9657,6 +9791,10 @@
(D.getCXXScopeSpec().getScopeRep()->isDependent() ||
(!Previous.empty() && CurContext->isDependentContext()))) {
// ignore these
+ } else if (NewFD->isCPUDispatchMultiVersion() ||
+ NewFD->isCPUSpecificMultiVersion()) {
+ // ignore this, we allow the redeclaration behavior here to create new
+ // versions of the function.
} else {
// The user tried to provide an out-of-line definition for a
// function that is a member of a class or namespace, but there
@@ -9793,7 +9931,7 @@
if (II && II->isStr(getCudaConfigureFuncName()) &&
!NewFD->isInvalidDecl() &&
NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
- if (!R->getAs<FunctionType>()->getReturnType()->isScalarType())
+ if (!R->castAs<FunctionType>()->getReturnType()->isScalarType())
Diag(NewFD->getLocation(), diag::err_config_scalar_return)
<< getCudaConfigureFuncName();
Context.setcudaConfigureCallDecl(NewFD);
@@ -10930,24 +11068,6 @@
if (!CurContext->isRecord())
CheckCXXDefaultArguments(NewFD);
- // If this function declares a builtin function, check the type of this
- // declaration against the expected type for the builtin.
- if (unsigned BuiltinID = NewFD->getBuiltinID()) {
- ASTContext::GetBuiltinTypeError Error;
- LookupNecessaryTypesForBuiltin(S, BuiltinID);
- QualType T = Context.GetBuiltinType(BuiltinID, Error);
- // If the type of the builtin differs only in its exception
- // specification, that's OK.
- // FIXME: If the types do differ in this way, it would be better to
- // retain the 'noexcept' form of the type.
- if (!T.isNull() &&
- !Context.hasSameFunctionTypeIgnoringExceptionSpec(T,
- NewFD->getType()))
- // The type of this function differs from the type of the builtin,
- // so forget about the builtin entirely.
- Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents);
- }
-
// If this function is declared as being extern "C", then check to see if
// the function returns a UDT (class, struct, or union type) that is not C
// compatible, and if it does, warn the user.
@@ -11159,6 +11279,25 @@
}
}
+static bool isDefaultStdCall(FunctionDecl *FD, Sema &S) {
+
+ // Default calling convention for main and wmain is __cdecl
+ if (FD->getName() == "main" || FD->getName() == "wmain")
+ return false;
+
+ // Default calling convention for MinGW is __cdecl
+ const llvm::Triple &T = S.Context.getTargetInfo().getTriple();
+ if (T.isWindowsGNUEnvironment())
+ return false;
+
+ // Default calling convention for WinMain, wWinMain and DllMain
+ // is __stdcall on 32 bit Windows
+ if (T.isOSWindows() && T.getArch() == llvm::Triple::x86)
+ return true;
+
+ return false;
+}
+
void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) {
QualType T = FD->getType();
assert(T->isFunctionType() && "function decl is not of function type");
@@ -11173,6 +11312,21 @@
if (FD->getName() != "DllMain")
FD->setHasImplicitReturnZero(true);
+ // Explicity specified calling conventions are applied to MSVC entry points
+ if (!hasExplicitCallingConv(T)) {
+ if (isDefaultStdCall(FD, *this)) {
+ if (FT->getCallConv() != CC_X86StdCall) {
+ FT = Context.adjustFunctionType(
+ FT, FT->getExtInfo().withCallingConv(CC_X86StdCall));
+ FD->setType(QualType(FT, 0));
+ }
+ } else if (FT->getCallConv() != CC_C) {
+ FT = Context.adjustFunctionType(FT,
+ FT->getExtInfo().withCallingConv(CC_C));
+ FD->setType(QualType(FT, 0));
+ }
+ }
+
if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) {
Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD;
FD->setInvalidDecl();
@@ -12074,12 +12228,12 @@
// If adding the initializer will turn this declaration into a definition,
// and we already have a definition for this variable, diagnose or otherwise
// handle the situation.
- VarDecl *Def;
- if ((Def = VDecl->getDefinition()) && Def != VDecl &&
- (!VDecl->isStaticDataMember() || VDecl->isOutOfLine()) &&
- !VDecl->isThisDeclarationADemotedDefinition() &&
- checkVarDeclRedefinition(Def, VDecl))
- return;
+ if (VarDecl *Def = VDecl->getDefinition())
+ if (Def != VDecl &&
+ (!VDecl->isStaticDataMember() || VDecl->isOutOfLine()) &&
+ !VDecl->isThisDeclarationADemotedDefinition() &&
+ checkVarDeclRedefinition(Def, VDecl))
+ return;
if (getLangOpts().CPlusPlus) {
// C++ [class.static.data]p4
@@ -12193,12 +12347,10 @@
// Variables declared within a function/method body (except for references)
// are handled by a dataflow analysis.
// This is undefined behavior in C++, but valid in C.
- if (getLangOpts().CPlusPlus) {
+ if (getLangOpts().CPlusPlus)
if (!VDecl->hasLocalStorage() || VDecl->getType()->isRecordType() ||
- VDecl->getType()->isReferenceType()) {
+ VDecl->getType()->isReferenceType())
CheckSelfReference(*this, RealDecl, Init, DirectInit);
- }
- }
// If the type changed, it means we had an incomplete type that was
// completed by the initializer. For example:
@@ -12444,7 +12596,7 @@
}
if (LangOpts.OpenMP && VDecl->isFileVarDecl())
- DeclsToCheckForDeferredDiags.push_back(VDecl);
+ DeclsToCheckForDeferredDiags.insert(VDecl);
CheckCompleteVariableDeclaration(VDecl);
}
@@ -12543,9 +12695,21 @@
if (!Var->isInvalidDecl() &&
Var->getType().getAddressSpace() == LangAS::opencl_constant &&
Var->getStorageClass() != SC_Extern && !Var->getInit()) {
- Diag(Var->getLocation(), diag::err_opencl_constant_no_init);
- Var->setInvalidDecl();
- return;
+ bool HasConstExprDefaultConstructor = false;
+ if (CXXRecordDecl *RD = Var->getType()->getAsCXXRecordDecl()) {
+ for (auto *Ctor : RD->ctors()) {
+ if (Ctor->isConstexpr() && Ctor->getNumParams() == 0 &&
+ Ctor->getMethodQualifiers().getAddressSpace() ==
+ LangAS::opencl_constant) {
+ HasConstExprDefaultConstructor = true;
+ }
+ }
+ }
+ if (!HasConstExprDefaultConstructor) {
+ Diag(Var->getLocation(), diag::err_opencl_constant_no_init);
+ Var->setInvalidDecl();
+ return;
+ }
}
if (!Var->isInvalidDecl() && RealDecl->hasAttr<LoaderUninitializedAttr>()) {
@@ -12567,6 +12731,8 @@
return;
}
}
+ // The declaration is unitialized, no need for further checks.
+ return;
}
VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition();
@@ -12611,7 +12777,7 @@
Diag(Var->getLocation(), diag::note_private_extern);
}
- if (Context.getTargetInfo().allowDebugInfoForExternalVar() &&
+ if (Context.getTargetInfo().allowDebugInfoForExternalRef() &&
!Var->isInvalidDecl() && !getLangOpts().CPlusPlus)
ExternalDeclarations.push_back(Var);
@@ -12848,6 +13014,8 @@
void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (var->isInvalidDecl()) return;
+ MaybeAddCUDAConstantAttr(var);
+
if (getLangOpts().OpenCL) {
// OpenCL v2.0 s6.12.5 - Every block variable declaration must have an
// initialiser
@@ -12938,43 +13106,6 @@
}
}
- // Apply section attributes and pragmas to global variables.
- bool GlobalStorage = var->hasGlobalStorage();
- if (GlobalStorage && var->isThisDeclarationADefinition() &&
- !inTemplateInstantiation()) {
- PragmaStack<StringLiteral *> *Stack = nullptr;
- int SectionFlags = ASTContext::PSF_Read;
- if (var->getType().isConstQualified())
- Stack = &ConstSegStack;
- else if (!var->getInit()) {
- Stack = &BSSSegStack;
- SectionFlags |= ASTContext::PSF_Write;
- } else {
- Stack = &DataSegStack;
- SectionFlags |= ASTContext::PSF_Write;
- }
- if (const SectionAttr *SA = var->getAttr<SectionAttr>()) {
- if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec)
- SectionFlags |= ASTContext::PSF_Implicit;
- UnifySection(SA->getName(), SectionFlags, var);
- } else if (Stack->CurrentValue) {
- SectionFlags |= ASTContext::PSF_Implicit;
- auto SectionName = Stack->CurrentValue->getString();
- var->addAttr(SectionAttr::CreateImplicit(
- Context, SectionName, Stack->CurrentPragmaLocation,
- AttributeCommonInfo::AS_Pragma, SectionAttr::Declspec_allocate));
- if (UnifySection(SectionName, SectionFlags, var))
- var->dropAttr<SectionAttr>();
- }
-
- // Apply the init_seg attribute if this has an initializer. If the
- // initializer turns out to not be dynamic, we'll end up ignoring this
- // attribute.
- if (CurInitSeg && var->getInit())
- var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(),
- CurInitSegLoc,
- AttributeCommonInfo::AS_Pragma));
- }
if (!var->getType()->isStructureType() && var->hasInit() &&
isa<InitListExpr>(var->getInit())) {
@@ -13024,14 +13155,6 @@
}
}
- // All the following checks are C++ only.
- if (!getLangOpts().CPlusPlus) {
- // If this variable must be emitted, add it as an initializer for the
- // current module.
- if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
- Context.addModuleInitializer(ModuleScopes.back().Module, var);
- return;
- }
QualType type = var->getType();
@@ -13039,11 +13162,14 @@
getCurFunction()->addByrefBlockVar(var);
Expr *Init = var->getInit();
+ bool GlobalStorage = var->hasGlobalStorage();
bool IsGlobal = GlobalStorage && !var->isStaticLocal();
QualType baseType = Context.getBaseElementType(type);
+ bool HasConstInit = true;
// Check whether the initializer is sufficiently constant.
- if (!type->isDependentType() && Init && !Init->isValueDependent() &&
+ if (getLangOpts().CPlusPlus && !type->isDependentType() && Init &&
+ !Init->isValueDependent() &&
(GlobalStorage || var->isConstexpr() ||
var->mightBeUsableInConstantExpressions(Context))) {
// If this variable might have a constant initializer or might be usable in
@@ -13051,7 +13177,6 @@
// do this lazily, because the result might depend on things that change
// later, such as which constexpr functions happen to be defined.
SmallVector<PartialDiagnosticAt, 8> Notes;
- bool HasConstInit;
if (!getLangOpts().CPlusPlus11) {
// Prior to C++11, in contexts where a constant initializer is required,
// the set of valid constant initializers is described by syntactic rules
@@ -13116,6 +13241,57 @@
}
}
+ // Apply section attributes and pragmas to global variables.
+ if (GlobalStorage && var->isThisDeclarationADefinition() &&
+ !inTemplateInstantiation()) {
+ PragmaStack<StringLiteral *> *Stack = nullptr;
+ int SectionFlags = ASTContext::PSF_Read;
+ if (var->getType().isConstQualified()) {
+ if (HasConstInit)
+ Stack = &ConstSegStack;
+ else {
+ Stack = &BSSSegStack;
+ SectionFlags |= ASTContext::PSF_Write;
+ }
+ } else if (var->hasInit() && HasConstInit) {
+ Stack = &DataSegStack;
+ SectionFlags |= ASTContext::PSF_Write;
+ } else {
+ Stack = &BSSSegStack;
+ SectionFlags |= ASTContext::PSF_Write;
+ }
+ if (const SectionAttr *SA = var->getAttr<SectionAttr>()) {
+ if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec)
+ SectionFlags |= ASTContext::PSF_Implicit;
+ UnifySection(SA->getName(), SectionFlags, var);
+ } else if (Stack->CurrentValue) {
+ SectionFlags |= ASTContext::PSF_Implicit;
+ auto SectionName = Stack->CurrentValue->getString();
+ var->addAttr(SectionAttr::CreateImplicit(
+ Context, SectionName, Stack->CurrentPragmaLocation,
+ AttributeCommonInfo::AS_Pragma, SectionAttr::Declspec_allocate));
+ if (UnifySection(SectionName, SectionFlags, var))
+ var->dropAttr<SectionAttr>();
+ }
+
+ // Apply the init_seg attribute if this has an initializer. If the
+ // initializer turns out to not be dynamic, we'll end up ignoring this
+ // attribute.
+ if (CurInitSeg && var->getInit())
+ var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(),
+ CurInitSegLoc,
+ AttributeCommonInfo::AS_Pragma));
+ }
+
+ // All the following checks are C++ only.
+ if (!getLangOpts().CPlusPlus) {
+ // If this variable must be emitted, add it as an initializer for the
+ // current module.
+ if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
+ Context.addModuleInitializer(ModuleScopes.back().Module, var);
+ return;
+ }
+
// Require the destructor.
if (!type->isDependentType())
if (const RecordType *recordType = baseType->getAs<RecordType>())
@@ -13131,16 +13307,6 @@
CheckCompleteDecompositionDeclaration(DD);
}
-/// Determines if a variable's alignment is dependent.
-static bool hasDependentAlignment(VarDecl *VD) {
- if (VD->getType()->isDependentType())
- return true;
- for (auto *I : VD->specific_attrs<AlignedAttr>())
- if (I->isAlignmentDependent())
- return true;
- return false;
-}
-
/// Check if VD needs to be dllexport/dllimport due to being in a
/// dllexport/import function.
void Sema::CheckStaticLocalForDllExport(VarDecl *VD) {
@@ -13229,8 +13395,7 @@
if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) {
// Protect the check so that it's not performed on dependent types and
// dependent alignments (we can't determine the alignment in that case).
- if (VD->getTLSKind() && !hasDependentAlignment(VD) &&
- !VD->isInvalidDecl()) {
+ if (VD->getTLSKind() && !VD->hasDependentAlignment()) {
CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign);
if (Context.getDeclAlign(VD) > MaxAlignChars) {
Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
@@ -13294,10 +13459,18 @@
if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
- Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr;
+ Diag(Attr->getLocation(), diag::warn_attribute_ignored_on_non_definition)
+ << Attr;
VD->dropAttr<UsedAttr>();
}
}
+ if (RetainAttr *Attr = VD->getAttr<RetainAttr>()) {
+ if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
+ Diag(Attr->getLocation(), diag::warn_attribute_ignored_on_non_definition)
+ << Attr;
+ VD->dropAttr<RetainAttr>();
+ }
+ }
const DeclContext *DC = VD->getDeclContext();
// If there's a #pragma GCC visibility in scope, and this isn't a class
@@ -13872,7 +14045,7 @@
// Don't warn about 'main'.
if (isa<TranslationUnitDecl>(FD->getDeclContext()->getRedeclContext()))
if (IdentifierInfo *II = FD->getIdentifier())
- if (II->isStr("main"))
+ if (II->isStr("main") || II->isStr("efi_main"))
return false;
// Don't warn about inline functions.
@@ -14656,7 +14829,7 @@
auto ES = getEmissionStatus(FD);
if (ES == Sema::FunctionEmissionStatus::Emitted ||
ES == Sema::FunctionEmissionStatus::Unknown)
- DeclsToCheckForDeferredDiags.push_back(FD);
+ DeclsToCheckForDeferredDiags.insert(FD);
}
return dcl;
@@ -15799,7 +15972,7 @@
Diag(KWLoc, diag::err_using_decl_conflict_reverse);
Diag(Shadow->getTargetDecl()->getLocation(),
diag::note_using_decl_target);
- Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl)
+ Diag(Shadow->getIntroducer()->getLocation(), diag::note_using_decl)
<< 0;
// Recover by ignoring the old declaration.
Previous.clear();
@@ -16331,6 +16504,7 @@
void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
SourceLocation FinalLoc,
bool IsFinalSpelledSealed,
+ bool IsAbstract,
SourceLocation LBraceLoc) {
AdjustDeclIfTemplate(TagD);
CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD);
@@ -16340,11 +16514,14 @@
if (!Record->getIdentifier())
return;
- if (FinalLoc.isValid())
+ if (IsAbstract)
+ Record->markAbstract();
+
+ if (FinalLoc.isValid()) {
Record->addAttr(FinalAttr::Create(
Context, FinalLoc, AttributeCommonInfo::AS_Keyword,
static_cast<FinalAttr::Spelling>(IsFinalSpelledSealed)));
-
+ }
// C++ [class]p2:
// [...] The class-name is also inserted into the scope of the
// class itself; this is known as the injected-class-name. For
@@ -16478,16 +16655,16 @@
if (Value.isSigned() && Value.isNegative()) {
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_has_negative_width)
- << FieldName << Value.toString(10);
+ << FieldName << toString(Value, 10);
return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width)
- << Value.toString(10);
+ << toString(Value, 10);
}
// The size of the bit-field must not exceed our maximum permitted object
// size.
if (Value.getActiveBits() > ConstantArrayType::getMaxSizeBits(Context)) {
return Diag(FieldLoc, diag::err_bitfield_too_wide)
- << !FieldName << FieldName << Value.toString(10);
+ << !FieldName << FieldName << toString(Value, 10);
}
if (!FieldTy->isDependentType()) {
@@ -16505,14 +16682,9 @@
if (CStdConstraintViolation || MSBitfieldViolation) {
unsigned DiagWidth =
CStdConstraintViolation ? TypeWidth : TypeStorageSize;
- if (FieldName)
- return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width)
- << FieldName << Value.toString(10)
- << !CStdConstraintViolation << DiagWidth;
-
- return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width)
- << Value.toString(10) << !CStdConstraintViolation
- << DiagWidth;
+ return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width)
+ << (bool)FieldName << FieldName << toString(Value, 10)
+ << !CStdConstraintViolation << DiagWidth;
}
// Warn on types where the user might conceivably expect to get all
@@ -16520,7 +16692,7 @@
// 'bool'.
if (BitfieldIsOverwide && !FieldTy->isBooleanType() && FieldName) {
Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
- << FieldName << Value.toString(10)
+ << FieldName << toString(Value, 10)
<< (unsigned)TypeWidth;
}
}
@@ -16698,8 +16870,10 @@
Record->setInvalidDecl();
InvalidDecl = true;
}
- // OpenCL v1.2 s6.9.c: bitfields are not supported.
- if (BitWidth) {
+ // OpenCL v1.2 s6.9.c: bitfields are not supported, unless Clang extension
+ // is enabled.
+ if (BitWidth && !getOpenCLOptions().isAvailableOption(
+ "__cl_clang_bitfields", LangOpts)) {
Diag(Loc, diag::err_opencl_bitfields);
InvalidDecl = true;
}
@@ -16716,7 +16890,7 @@
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
if (!tryToFixVariablyModifiedVarType(
- *this, TInfo, T, Loc, diag::err_typecheck_field_variable_size))
+ TInfo, T, Loc, diag::err_typecheck_field_variable_size))
InvalidDecl = true;
}
@@ -16944,7 +17118,7 @@
// than a variably modified type.
else if (T->isVariablyModifiedType()) {
if (!tryToFixVariablyModifiedVarType(
- *this, TInfo, T, Loc, diag::err_typecheck_ivar_variable_size))
+ TInfo, T, Loc, diag::err_typecheck_ivar_variable_size))
D.setInvalidType();
}
@@ -17630,7 +17804,7 @@
// Complain if the value is not representable in an int.
if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
Diag(IdLoc, diag::ext_enum_value_not_int)
- << EnumVal.toString(10) << Val->getSourceRange()
+ << toString(EnumVal, 10) << Val->getSourceRange()
<< (EnumVal.isUnsigned() || EnumVal.isNonNegative());
else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
// Force the type of the expression to 'int'.
@@ -17688,11 +17862,11 @@
if (Enum->isFixed())
// When the underlying type is fixed, this is ill-formed.
Diag(IdLoc, diag::err_enumerator_wrapped)
- << EnumVal.toString(10)
+ << toString(EnumVal, 10)
<< EltTy;
else
Diag(IdLoc, diag::ext_enumerator_increment_too_large)
- << EnumVal.toString(10);
+ << toString(EnumVal, 10);
} else {
EltTy = T;
}
@@ -17716,7 +17890,7 @@
!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
// Enforce C99 6.7.2.2p2 even when we compute the next value.
Diag(IdLoc, diag::ext_enum_value_not_int)
- << EnumVal.toString(10) << 1;
+ << toString(EnumVal, 10) << 1;
}
}
}
@@ -17970,14 +18144,14 @@
// Emit warning for one enum constant.
auto *FirstECD = Vec->front();
S.Diag(FirstECD->getLocation(), diag::warn_duplicate_enum_values)
- << FirstECD << FirstECD->getInitVal().toString(10)
+ << FirstECD << toString(FirstECD->getInitVal(), 10)
<< FirstECD->getSourceRange();
// Emit one note for each of the remaining enum constants with
// the same value.
for (auto *ECD : llvm::make_range(Vec->begin() + 1, Vec->end()))
S.Diag(ECD->getLocation(), diag::note_duplicate_element)
- << ECD << ECD->getInitVal().toString(10)
+ << ECD << toString(ECD->getInitVal(), 10)
<< ECD->getSourceRange();
}
}
@@ -18212,7 +18386,7 @@
!Context.hasSameType(NewTy, ECD->getInitExpr()->getType()))
ECD->setInitExpr(ImplicitCastExpr::Create(
Context, NewTy, CK_IntegralCast, ECD->getInitExpr(),
- /*base paths*/ nullptr, VK_RValue, FPOptionsOverride()));
+ /*base paths*/ nullptr, VK_PRValue, FPOptionsOverride()));
if (getLangOpts().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
@@ -18323,6 +18497,8 @@
Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD,
bool Final) {
+ assert(FD && "Expected non-null FunctionDecl");
+
// SYCL functions can be template, so we check if they have appropriate
// attribute prior to checking if it is a template.
if (LangOpts.SYCLIsDevice && FD->hasAttr<SYCLKernelAttr>())
@@ -18350,7 +18526,7 @@
OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl());
// DevTy may be changed later by
// #pragma omp declare target to(*) device_type(*).
- // Therefore DevTyhaving no value does not imply host. The emission status
+ // Therefore DevTy having no value does not imply host. The emission status
// will be checked again at the end of compilation unit with Final = true.
if (DevTy.hasValue())
if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host)
diff --git a/src/llvm-project/clang/lib/Sema/SemaDeclAttr.cpp b/src/llvm-project/clang/lib/Sema/SemaDeclAttr.cpp
index 30d08b3..bb4ce8d 100644
--- a/src/llvm-project/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaDeclAttr.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetBuiltins.h"
@@ -40,6 +41,8 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Assumptions.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -153,7 +156,8 @@
return false;
}
-static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
+static inline bool isNSStringType(QualType T, ASTContext &Ctx,
+ bool AllowNSAttributedString = false) {
const auto *PT = T->getAs<ObjCObjectPointerType>();
if (!PT)
return false;
@@ -164,6 +168,9 @@
IdentifierInfo* ClsName = Cls->getIdentifier();
+ if (AllowNSAttributedString &&
+ ClsName == &Ctx.Idents.get("NSAttributedString"))
+ return true;
// FIXME: Should we walk the chain of classes?
return ClsName == &Ctx.Idents.get("NSString") ||
ClsName == &Ctx.Idents.get("NSMutableString");
@@ -190,44 +197,6 @@
return AL.getNumArgs() + AL.hasParsedType();
}
-template <typename Compare>
-static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
- unsigned Num, unsigned Diag,
- Compare Comp) {
- if (Comp(getNumAttributeArgs(AL), Num)) {
- S.Diag(AL.getLoc(), Diag) << AL << Num;
- return false;
- }
-
- return true;
-}
-
-/// Check if the attribute has exactly as many args as Num. May
-/// output an error.
-static bool checkAttributeNumArgs(Sema &S, const ParsedAttr &AL, unsigned Num) {
- return checkAttributeNumArgsImpl(S, AL, Num,
- diag::err_attribute_wrong_number_arguments,
- std::not_equal_to<unsigned>());
-}
-
-/// Check if the attribute has at least as many args as Num. May
-/// output an error.
-static bool checkAttributeAtLeastNumArgs(Sema &S, const ParsedAttr &AL,
- unsigned Num) {
- return checkAttributeNumArgsImpl(S, AL, Num,
- diag::err_attribute_too_few_arguments,
- std::less<unsigned>());
-}
-
-/// Check if the attribute has at most as many args as Num. May
-/// output an error.
-static bool checkAttributeAtMostNumArgs(Sema &S, const ParsedAttr &AL,
- unsigned Num) {
- return checkAttributeNumArgsImpl(S, AL, Num,
- diag::err_attribute_too_many_arguments,
- std::greater<unsigned>());
-}
-
/// A helper function to provide Attribute Location for the Attr types
/// AND the ParsedAttr.
template <typename AttrInfo>
@@ -261,7 +230,7 @@
if (!I->isIntN(32)) {
S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
- << I->toString(10, false) << 32 << /* Unsigned */ 1;
+ << toString(*I, 10, false) << 32 << /* Unsigned */ 1;
return false;
}
@@ -289,7 +258,7 @@
llvm::APSInt I(32); // for toString
I = UVal;
S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
- << I.toString(10, false) << 32 << /* Unsigned */ 0;
+ << toString(I, 10, false) << 32 << /* Unsigned */ 0;
return false;
}
@@ -423,10 +392,10 @@
std::forward<DiagnosticArgs>(ExtraArgs)...);
}
-/// Add an attribute {@code AttrType} to declaration {@code D}, provided that
-/// {@code PassesCheck} is true.
-/// Otherwise, emit diagnostic {@code DiagID}, passing in all parameters
-/// specified in {@code ExtraArgs}.
+/// Add an attribute @c AttrType to declaration @c D, provided that
+/// @c PassesCheck is true.
+/// Otherwise, emit diagnostic @c DiagID, passing in all parameters
+/// specified in @c ExtraArgs.
template <typename AttrType, typename... DiagnosticArgs>
static void handleSimpleAttributeOrDiagnose(Sema &S, Decl *D,
const AttributeCommonInfo &CI,
@@ -440,24 +409,6 @@
handleSimpleAttribute<AttrType>(S, D, CI);
}
-template <typename AttrType>
-static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- handleSimpleAttribute<AttrType>(S, D, AL);
-}
-
-/// Applies the given attribute to the Decl so long as the Decl doesn't
-/// already have one of the given incompatible attributes.
-template <typename AttrType, typename IncompatibleAttrType,
- typename... IncompatibleAttrTypes>
-static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL))
- return;
- handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D,
- AL);
-}
-
/// Check if the passed-in expression is of type int or bool.
static bool isIntOrBool(Expr *Exp) {
QualType QT = Exp->getType();
@@ -546,16 +497,9 @@
// Else check if any base classes have the attribute.
if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- CXXBasePaths BPaths(false, false);
- if (CRD->lookupInBases(
- [](const CXXBaseSpecifier *BS, CXXBasePath &) {
- const auto &Ty = *BS->getType();
- // If it's type-dependent, we assume it could have the attribute.
- if (Ty.isDependentType())
- return true;
- return Ty.castAs<RecordType>()->getDecl()->hasAttr<AttrType>();
- },
- BPaths, true))
+ if (!CRD->forallBases([](const CXXRecordDecl *Base) {
+ return !Base->hasAttr<AttrType>();
+ }))
return true;
}
return false;
@@ -770,7 +714,7 @@
static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1))
return false;
// Check that this attribute only applies to lockable types.
@@ -846,32 +790,33 @@
///
/// AttrArgNo is used to actually retrieve the argument, so it's base-0.
template <typename AttrInfo>
-static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,
- const AttrInfo &AI, unsigned AttrArgNo) {
+static bool checkParamIsIntegerType(Sema &S, const Decl *D, const AttrInfo &AI,
+ unsigned AttrArgNo) {
assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument");
Expr *AttrArg = AI.getArgAsExpr(AttrArgNo);
ParamIdx Idx;
- if (!checkFunctionOrMethodParameterIndex(S, FD, AI, AttrArgNo + 1, AttrArg,
+ if (!checkFunctionOrMethodParameterIndex(S, D, AI, AttrArgNo + 1, AttrArg,
Idx))
return false;
- const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex());
- if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) {
+ QualType ParamTy = getFunctionOrMethodParamType(D, Idx.getASTIndex());
+ if (!ParamTy->isIntegerType() && !ParamTy->isCharType()) {
SourceLocation SrcLoc = AttrArg->getBeginLoc();
S.Diag(SrcLoc, diag::err_attribute_integers_only)
- << AI << Param->getSourceRange();
+ << AI << getFunctionOrMethodParamRange(D, Idx.getASTIndex());
return false;
}
return true;
}
static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
- !checkAttributeAtMostNumArgs(S, AL, 2))
+ if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
return;
- const auto *FD = cast<FunctionDecl>(D);
- if (!FD->getReturnType()->isPointerType()) {
+ assert(isFunctionOrMethod(D) && hasFunctionProto(D));
+
+ QualType RetTy = getFunctionOrMethodResultType(D);
+ if (!RetTy->isPointerType()) {
S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL;
return;
}
@@ -881,7 +826,7 @@
// Parameter indices are 1-indexed, hence Index=1
if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Idx=*/1))
return;
- if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0))
+ if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/0))
return;
ParamIdx SizeArgNo(SizeArgNoVal, D);
@@ -892,7 +837,7 @@
// Parameter indices are 1-based, hence Index=2
if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Idx=*/2))
return;
- if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1))
+ if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/1))
return;
NumberArgNo = ParamIdx(Val, D);
}
@@ -903,7 +848,7 @@
static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
SmallVectorImpl<Expr *> &Args) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1))
return false;
if (!isIntOrBool(AL.getArgAsExpr(0))) {
@@ -950,7 +895,7 @@
}
static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1))
return;
// check that all arguments are lockable objects
@@ -1192,7 +1137,7 @@
}
static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1))
return;
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
@@ -1991,6 +1936,12 @@
return;
}
+ if (S.Context.getTargetInfo().getTriple().isOSAIX() &&
+ Model != "global-dynamic") {
+ S.Diag(LiteralLoc, diag::err_aix_attr_unsupported_tls_model) << Model;
+ return;
+ }
+
D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model));
}
@@ -2015,7 +1966,7 @@
}
}
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1))
return;
SmallVector<IdentifierInfo *, 8> CPUs;
@@ -2062,8 +2013,7 @@
return;
}
- if (CommonAttr *CA = S.mergeCommonAttr(D, AL))
- D->addAttr(CA);
+ D->addAttr(::new (S.Context) CommonAttr(S.Context, AL));
}
static void handleCmseNSEntryAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
@@ -2082,9 +2032,6 @@
}
static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL))
- return;
-
if (AL.isDeclspecAttribute()) {
const auto &Triple = S.getASTContext().getTargetInfo().getTriple();
const auto &Arch = Triple.getArch();
@@ -2119,7 +2066,7 @@
}
bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) {
- if (!checkAttributeNumArgs(*this, Attrs, 0)) {
+ if (!Attrs.checkExactlyNumArgs(*this, 0)) {
Attrs.setInvalid();
return true;
}
@@ -2147,7 +2094,7 @@
ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD || (!VD->getType()->isBlockPointerType() &&
!VD->getType()->isFunctionPointerType())) {
- S.Diag(AL.getLoc(), AL.isCXX11Attribute()
+ S.Diag(AL.getLoc(), AL.isStandardAttributeSyntax()
? diag::err_attribute_wrong_decl_type
: diag::warn_attribute_wrong_decl_type)
<< AL << ExpectedFunctionMethodOrBlock;
@@ -2354,6 +2301,7 @@
case AMK_Override:
case AMK_ProtocolImplementation:
+ case AMK_OptionalProtocolImplementation:
OverrideOrImpl = true;
break;
}
@@ -2422,6 +2370,14 @@
diag::warn_mismatched_availability_override_unavail)
<< AvailabilityAttr::getPrettyPlatformName(Platform->getName())
<< (AMK == AMK_Override);
+ } else if (Which != 1 && AMK == AMK_OptionalProtocolImplementation) {
+ // Allow different 'introduced' / 'obsoleted' availability versions
+ // on a method that implements an optional protocol requirement. It
+ // makes less sense to allow this for 'deprecated' as the user can't
+ // see if the method is 'deprecated' as 'respondsToSelector' will
+ // still return true when the method is deprecated.
+ ++i;
+ continue;
} else {
Diag(OldAA->getLocation(),
diag::warn_mismatched_availability_override)
@@ -2491,7 +2447,14 @@
}
static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeNumArgs(S, AL, 1))
+ if (isa<UsingDecl, UnresolvedUsingTypenameDecl, UnresolvedUsingValueDecl>(
+ D)) {
+ S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using)
+ << AL;
+ return;
+ }
+
+ if (!AL.checkExactlyNumArgs(S, 1))
return;
IdentifierLoc *Platform = AL.getArgAsIdent(0);
@@ -2594,15 +2557,90 @@
if (NewAttr)
D->addAttr(NewAttr);
}
+ } else if (S.Context.getTargetInfo().getTriple().getOS() ==
+ llvm::Triple::IOS &&
+ S.Context.getTargetInfo().getTriple().isMacCatalystEnvironment()) {
+ auto GetSDKInfo = [&]() {
+ return S.getDarwinSDKInfoForAvailabilityChecking(AL.getRange().getBegin(),
+ "macOS");
+ };
+
+ // Transcribe "ios" to "maccatalyst" (and add a new attribute).
+ IdentifierInfo *NewII = nullptr;
+ if (II->getName() == "ios")
+ NewII = &S.Context.Idents.get("maccatalyst");
+ else if (II->getName() == "ios_app_extension")
+ NewII = &S.Context.Idents.get("maccatalyst_app_extension");
+ if (NewII) {
+ auto MinMacCatalystVersion = [](const VersionTuple &V) {
+ if (V.empty())
+ return V;
+ if (V.getMajor() < 13 ||
+ (V.getMajor() == 13 && V.getMinor() && *V.getMinor() < 1))
+ return VersionTuple(13, 1); // The min Mac Catalyst version is 13.1.
+ return V;
+ };
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
+ ND, AL.getRange(), NewII, true /*Implicit*/,
+ MinMacCatalystVersion(Introduced.Version),
+ MinMacCatalystVersion(Deprecated.Version),
+ MinMacCatalystVersion(Obsoleted.Version), IsUnavailable, Str,
+ IsStrict, Replacement, Sema::AMK_None,
+ PriorityModifier + Sema::AP_InferredFromOtherPlatform);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+ } else if (II->getName() == "macos" && GetSDKInfo() &&
+ (!Introduced.Version.empty() || !Deprecated.Version.empty() ||
+ !Obsoleted.Version.empty())) {
+ if (const auto *MacOStoMacCatalystMapping =
+ GetSDKInfo()->getVersionMapping(
+ DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
+ // Infer Mac Catalyst availability from the macOS availability attribute
+ // if it has versioned availability. Don't infer 'unavailable'. This
+ // inferred availability has lower priority than the other availability
+ // attributes that are inferred from 'ios'.
+ NewII = &S.Context.Idents.get("maccatalyst");
+ auto RemapMacOSVersion =
+ [&](const VersionTuple &V) -> Optional<VersionTuple> {
+ if (V.empty())
+ return None;
+ // API_TO_BE_DEPRECATED is 100000.
+ if (V.getMajor() == 100000)
+ return VersionTuple(100000);
+ // The minimum iosmac version is 13.1
+ return MacOStoMacCatalystMapping->map(V, VersionTuple(13, 1), None);
+ };
+ Optional<VersionTuple> NewIntroduced =
+ RemapMacOSVersion(Introduced.Version),
+ NewDeprecated =
+ RemapMacOSVersion(Deprecated.Version),
+ NewObsoleted =
+ RemapMacOSVersion(Obsoleted.Version);
+ if (NewIntroduced || NewDeprecated || NewObsoleted) {
+ auto VersionOrEmptyVersion =
+ [](const Optional<VersionTuple> &V) -> VersionTuple {
+ return V ? *V : VersionTuple();
+ };
+ AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
+ ND, AL.getRange(), NewII, true /*Implicit*/,
+ VersionOrEmptyVersion(NewIntroduced),
+ VersionOrEmptyVersion(NewDeprecated),
+ VersionOrEmptyVersion(NewObsoleted), /*IsUnavailable=*/false, Str,
+ IsStrict, Replacement, Sema::AMK_None,
+ PriorityModifier + Sema::AP_InferredFromOtherPlatform +
+ Sema::AP_InferredFromOtherPlatform);
+ if (NewAttr)
+ D->addAttr(NewAttr);
+ }
+ }
+ }
}
}
static void handleExternalSourceSymbolAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3))
return;
- assert(checkAttributeAtMostNumArgs(S, AL, 3) &&
- "Invalid number of arguments in an external_source_symbol attribute");
StringRef Language;
if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0)))
@@ -2693,11 +2731,6 @@
D->addAttr(newAttr);
}
-static void handleObjCNonRuntimeProtocolAttr(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- handleSimpleAttribute<ObjCNonRuntimeProtocolAttr>(S, D, AL);
-}
-
static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// objc_direct cannot be set on methods declared in the context of a protocol
if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
@@ -2872,8 +2905,10 @@
QualType Ty = V->getType();
if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
const FunctionType *FT = Ty->isFunctionPointerType()
- ? D->getFunctionType()
- : Ty->castAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
+ ? D->getFunctionType()
+ : Ty->castAs<BlockPointerType>()
+ ->getPointeeType()
+ ->castAs<FunctionType>();
if (!cast<FunctionProtoType>(FT)->isVariadic()) {
int m = Ty->isFunctionPointerType() ? 0 : 1;
S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
@@ -2906,7 +2941,7 @@
}
StringRef Str;
- if ((AL.isCXX11Attribute() || AL.isC2xAttribute()) && !AL.getScopeName()) {
+ if (AL.isStandardAttributeSyntax() && !AL.getScopeName()) {
// The standard attribute cannot be applied to variable declarations such
// as a function pointer.
if (isa<VarDecl>(D))
@@ -3051,11 +3086,31 @@
return ::new (Context) SectionAttr(Context, CI, Name);
}
+/// Used to implement to perform semantic checking on
+/// attribute((section("foo"))) specifiers.
+///
+/// In this case, "foo" is passed in to be checked. If the section
+/// specifier is invalid, return an Error that indicates the problem.
+///
+/// This is a simple quality of implementation feature to catch errors
+/// and give good diagnostics in cases when the assembler or code generator
+/// would otherwise reject the section specifier.
+llvm::Error Sema::isValidSectionSpecifier(StringRef SecName) {
+ if (!Context.getTargetInfo().getTriple().isOSDarwin())
+ return llvm::Error::success();
+
+ // Let MCSectionMachO validate this.
+ StringRef Segment, Section;
+ unsigned TAA, StubSize;
+ bool HasTAA;
+ return llvm::MCSectionMachO::ParseSectionSpecifier(SecName, Segment, Section,
+ TAA, HasTAA, StubSize);
+}
+
bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
- std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName);
- if (!Error.empty()) {
- Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error
- << 1 /*'section'*/;
+ if (llvm::Error E = isValidSectionSpecifier(SecName)) {
+ Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
+ << toString(std::move(E)) << 1 /*'section'*/;
return false;
}
return true;
@@ -3072,14 +3127,6 @@
if (!S.checkSectionName(LiteralLoc, Str))
return;
- // If the target wants to validate the section specifier, make it happen.
- std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);
- if (!Error.empty()) {
- S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
- << Error;
- return;
- }
-
SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str);
if (NewAttr) {
D->addAttr(NewAttr);
@@ -3095,11 +3142,9 @@
// `#pragma code_seg("segname")` uses checkSectionName() instead.
static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc,
StringRef CodeSegName) {
- std::string Error =
- S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName);
- if (!Error.empty()) {
+ if (llvm::Error E = S.isValidSectionSpecifier(CodeSegName)) {
S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
- << Error << 0 /*'code-seg'*/;
+ << toString(std::move(E)) << 0 /*'code-seg'*/;
return false;
}
@@ -3328,7 +3373,7 @@
return;
}
Ty = getFunctionOrMethodResultType(D);
- if (!isNSStringType(Ty, S.Context) &&
+ if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true) &&
!isCFStringType(Ty, S.Context) &&
(!Ty->isPointerType() ||
!Ty->castAs<PointerType>()->getPointeeType()->isCharType())) {
@@ -3504,7 +3549,7 @@
} else if (Kind == NSStringFormat) {
// FIXME: do we need to check if the type is NSString*? What are the
// semantics?
- if (!isNSStringType(Ty, S.Context)) {
+ if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true)) {
S.Diag(AL.getLoc(), diag::err_format_attribute_not)
<< "an NSString" << IdxExpr->getSourceRange()
<< getFunctionOrMethodParamRange(D, ArgIdx);
@@ -3802,11 +3847,11 @@
E = ImplicitCastExpr::Create(Context,
Context.getPointerType(E->getType()),
clang::CK_FunctionToPointerDecay, E, nullptr,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
if (E->isLValue())
E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),
clang::CK_LValueToRValue, E, nullptr,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
Expr::EvalResult Eval;
Notes.clear();
@@ -3986,6 +4031,12 @@
return;
uint64_t AlignVal = Alignment.getZExtValue();
+ // 16 byte ByVal alignment not due to a vector member is not honoured by XL
+ // on AIX. Emit a warning here that users are generating binary incompatible
+ // code to be safe.
+ if (AlignVal >= 16 && isa<FieldDecl>(D) &&
+ Context.getTargetInfo().getTriple().isOSAIX())
+ Diag(AttrLoc, diag::warn_not_xl_compatible) << E->getSourceRange();
// C++11 [dcl.align]p2:
// -- if the constant expression evaluates to zero, the alignment
@@ -4350,20 +4401,6 @@
return ::new (Context) AlwaysInlineAttr(Context, CI);
}
-CommonAttr *Sema::mergeCommonAttr(Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL))
- return nullptr;
-
- return ::new (Context) CommonAttr(Context, AL);
-}
-
-CommonAttr *Sema::mergeCommonAttr(Decl *D, const CommonAttr &AL) {
- if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL))
- return nullptr;
-
- return ::new (Context) CommonAttr(Context, AL);
-}
-
InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D,
const ParsedAttr &AL) {
if (const auto *VD = dyn_cast<VarDecl>(D)) {
@@ -4382,9 +4419,6 @@
}
}
- if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL))
- return nullptr;
-
return ::new (Context) InternalLinkageAttr(Context, AL);
}
InternalLinkageAttr *
@@ -4405,9 +4439,6 @@
}
}
- if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL))
- return nullptr;
-
return ::new (Context) InternalLinkageAttr(Context, AL);
}
@@ -4424,14 +4455,6 @@
return ::new (Context) MinSizeAttr(Context, CI);
}
-NoSpeculativeLoadHardeningAttr *Sema::mergeNoSpeculativeLoadHardeningAttr(
- Decl *D, const NoSpeculativeLoadHardeningAttr &AL) {
- if (checkAttrMutualExclusion<SpeculativeLoadHardeningAttr>(*this, D, AL))
- return nullptr;
-
- return ::new (Context) NoSpeculativeLoadHardeningAttr(Context, AL);
-}
-
SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
StringRef Name) {
if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) {
@@ -4465,18 +4488,7 @@
return ::new (Context) OptimizeNoneAttr(Context, CI);
}
-SpeculativeLoadHardeningAttr *Sema::mergeSpeculativeLoadHardeningAttr(
- Decl *D, const SpeculativeLoadHardeningAttr &AL) {
- if (checkAttrMutualExclusion<NoSpeculativeLoadHardeningAttr>(*this, D, AL))
- return nullptr;
-
- return ::new (Context) SpeculativeLoadHardeningAttr(Context, AL);
-}
-
static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL))
- return;
-
if (AlwaysInlineAttr *Inline =
S.mergeAlwaysInlineAttr(D, AL, AL.getAttrName()))
D->addAttr(Inline);
@@ -4493,21 +4505,22 @@
}
static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL) ||
- checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL))
- return;
const auto *VD = cast<VarDecl>(D);
if (VD->hasLocalStorage()) {
S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
return;
}
+ // constexpr variable may already get an implicit constant attr, which should
+ // be replaced by the explicit constant attr.
+ if (auto *A = D->getAttr<CUDAConstantAttr>()) {
+ if (!A->isImplicit())
+ return;
+ D->dropAttr<CUDAConstantAttr>();
+ }
D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL));
}
static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) ||
- checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL))
- return;
const auto *VD = cast<VarDecl>(D);
// extern __shared__ is only allowed on arrays with no length (e.g.
// "int x[]").
@@ -4524,10 +4537,6 @@
}
static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL) ||
- checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL)) {
- return;
- }
const auto *FD = cast<FunctionDecl>(D);
if (!FD->getReturnType()->isVoidType() &&
!FD->getReturnType()->getAs<AutoType>() &&
@@ -4561,10 +4570,6 @@
}
static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDAGlobalAttr>(S, D, AL)) {
- return;
- }
-
if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasLocalStorage()) {
S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
@@ -4581,11 +4586,6 @@
}
static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) ||
- checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL)) {
- return;
- }
-
if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasLocalStorage()) {
S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
@@ -4645,6 +4645,9 @@
case ParsedAttr::AT_SwiftCall:
D->addAttr(::new (S.Context) SwiftCallAttr(S.Context, AL));
return;
+ case ParsedAttr::AT_SwiftAsyncCall:
+ D->addAttr(::new (S.Context) SwiftAsyncCallAttr(S.Context, AL));
+ return;
case ParsedAttr::AT_VectorCall:
D->addAttr(::new (S.Context) VectorCallAttr(S.Context, AL));
return;
@@ -4691,7 +4694,7 @@
}
static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1))
return;
std::vector<StringRef> DiagnosticIdentifiers;
@@ -4730,7 +4733,10 @@
}
// To check if earlier decl attributes do not conflict the newly parsed ones
- // we always add (and check) the attribute to the cannonical decl.
+ // we always add (and check) the attribute to the cannonical decl. We need
+ // to repeat the check for attribute mutual exclusion because we're attaching
+ // all of the attributes to the canonical declaration rather than the current
+ // declaration.
D = D->getCanonicalDecl();
if (AL.getKind() == ParsedAttr::AT_Owner) {
if (checkAttrMutualExclusion<PointerAttr>(S, D, AL))
@@ -4781,7 +4787,7 @@
}
unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0;
- if (!checkAttributeNumArgs(*this, Attrs, ReqArgs)) {
+ if (!Attrs.checkExactlyNumArgs(*this, ReqArgs)) {
Attrs.setInvalid();
return true;
}
@@ -4806,6 +4812,9 @@
case ParsedAttr::AT_SwiftCall:
CC = CC_Swift;
break;
+ case ParsedAttr::AT_SwiftAsyncCall:
+ CC = CC_SwiftAsync;
+ break;
case ParsedAttr::AT_VectorCall:
CC = CC_X86VectorCall;
break;
@@ -4984,6 +4993,14 @@
D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
return;
+ case ParameterABI::SwiftAsyncContext:
+ if (!isValidSwiftContextType(type)) {
+ Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
+ << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
+ }
+ D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI));
+ return;
+
case ParameterABI::SwiftErrorResult:
if (!isValidSwiftErrorResultType(type)) {
Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
@@ -5009,7 +5026,7 @@
if (AL.isInvalid())
return true;
- if (!checkAttributeNumArgs(*this, AL, 1)) {
+ if (!AL.checkExactlyNumArgs(*this, 1)) {
AL.setInvalid();
return true;
}
@@ -5063,7 +5080,7 @@
// Make sure we can fit it in 32 bits.
if (!I->isIntN(32)) {
S.Diag(E->getExprLoc(), diag::err_ice_too_large)
- << I->toString(10, false) << 32 << /* Unsigned */ 1;
+ << toString(*I, 10, false) << 32 << /* Unsigned */ 1;
return nullptr;
}
if (*I < 0)
@@ -5098,8 +5115,7 @@
}
static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
- !checkAttributeAtMostNumArgs(S, AL, 2))
+ if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
return;
S.AddLaunchBoundsAttr(D, AL, AL.getArgAsExpr(0),
@@ -5146,7 +5162,7 @@
return;
}
- if (!checkAttributeNumArgs(S, AL, 1))
+ if (!AL.checkExactlyNumArgs(S, 1))
return;
if (!isa<VarDecl>(D)) {
@@ -5237,15 +5253,12 @@
return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
}
-static bool ArmSveAliasValid(unsigned BuiltinID, StringRef AliasName) {
- switch (BuiltinID) {
- default:
- return false;
-#define GET_SVE_BUILTINS
-#define BUILTIN(name, types, attr) case SVE::BI##name:
-#include "clang/Basic/arm_sve_builtins.inc"
- return true;
- }
+static bool ArmSveAliasValid(ASTContext &Context, unsigned BuiltinID,
+ StringRef AliasName) {
+ if (Context.BuiltinInfo.isAuxBuiltinID(BuiltinID))
+ BuiltinID = Context.BuiltinInfo.getAuxBuiltinID(BuiltinID);
+ return BuiltinID >= AArch64::FirstSVEBuiltin &&
+ BuiltinID <= AArch64::LastSVEBuiltin;
}
static void handleArmBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
@@ -5260,7 +5273,7 @@
StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
- if ((IsAArch64 && !ArmSveAliasValid(BuiltinID, AliasName)) ||
+ if ((IsAArch64 && !ArmSveAliasValid(S.Context, BuiltinID, AliasName)) ||
(!IsAArch64 && !ArmMveAliasValid(BuiltinID, AliasName) &&
!ArmCdeAliasValid(BuiltinID, AliasName))) {
S.Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
@@ -5270,6 +5283,38 @@
D->addAttr(::new (S.Context) ArmBuiltinAliasAttr(S.Context, AL, Ident));
}
+static bool RISCVAliasValid(unsigned BuiltinID, StringRef AliasName) {
+ return BuiltinID >= Builtin::FirstTSBuiltin &&
+ BuiltinID < RISCV::LastTSBuiltin;
+}
+
+static void handleBuiltinAliasAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL << 1 << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
+ unsigned BuiltinID = Ident->getBuiltinID();
+ StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
+
+ bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
+ bool IsARM = S.Context.getTargetInfo().getTriple().isARM();
+ bool IsRISCV = S.Context.getTargetInfo().getTriple().isRISCV();
+ if ((IsAArch64 && !ArmSveAliasValid(S.Context, BuiltinID, AliasName)) ||
+ (IsARM && !ArmMveAliasValid(BuiltinID, AliasName) &&
+ !ArmCdeAliasValid(BuiltinID, AliasName)) ||
+ (IsRISCV && !RISCVAliasValid(BuiltinID, AliasName)) ||
+ (!IsAArch64 && !IsARM && !IsRISCV)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_builtin_alias) << AL;
+ return;
+ }
+
+ D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident));
+}
+
//===----------------------------------------------------------------------===//
// Checker-specific attribute handlers.
//===----------------------------------------------------------------------===//
@@ -5751,9 +5796,11 @@
if (!S.checkStringLiteralArgumentAttr(AL, 0, BT))
return;
- // Don't duplicate annotations that are already set.
- if (D->hasAttr<SwiftBridgeAttr>()) {
- S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
+ // Warn about duplicate attributes if they have different arguments, but drop
+ // any duplicate attributes regardless.
+ if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) {
+ if (Other->getSwiftType() != BT)
+ S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
return;
}
@@ -5856,6 +5903,125 @@
D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention));
}
+static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D,
+ const SwiftAsyncErrorAttr *ErrorAttr,
+ const SwiftAsyncAttr *AsyncAttr) {
+ if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
+ if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
+ S.Diag(AsyncAttr->getLocation(),
+ diag::err_swift_async_error_without_swift_async)
+ << AsyncAttr << isa<ObjCMethodDecl>(D);
+ }
+ return;
+ }
+
+ const ParmVarDecl *HandlerParam = getFunctionOrMethodParam(
+ D, AsyncAttr->getCompletionHandlerIndex().getASTIndex());
+ // handleSwiftAsyncAttr already verified the type is correct, so no need to
+ // double-check it here.
+ const auto *FuncTy = HandlerParam->getType()
+ ->castAs<BlockPointerType>()
+ ->getPointeeType()
+ ->getAs<FunctionProtoType>();
+ ArrayRef<QualType> BlockParams;
+ if (FuncTy)
+ BlockParams = FuncTy->getParamTypes();
+
+ switch (ErrorAttr->getConvention()) {
+ case SwiftAsyncErrorAttr::ZeroArgument:
+ case SwiftAsyncErrorAttr::NonZeroArgument: {
+ uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();
+ if (ParamIdx == 0 || ParamIdx > BlockParams.size()) {
+ S.Diag(ErrorAttr->getLocation(),
+ diag::err_attribute_argument_out_of_bounds) << ErrorAttr << 2;
+ return;
+ }
+ QualType ErrorParam = BlockParams[ParamIdx - 1];
+ if (!ErrorParam->isIntegralType(S.Context)) {
+ StringRef ConvStr =
+ ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
+ ? "zero_argument"
+ : "nonzero_argument";
+ S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral)
+ << ErrorAttr << ConvStr << ParamIdx << ErrorParam;
+ return;
+ }
+ break;
+ }
+ case SwiftAsyncErrorAttr::NonNullError: {
+ bool AnyErrorParams = false;
+ for (QualType Param : BlockParams) {
+ // Check for NSError *.
+ if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) {
+ if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {
+ if (ID->getIdentifier() == S.getNSErrorIdent()) {
+ AnyErrorParams = true;
+ break;
+ }
+ }
+ }
+ // Check for CFError *.
+ if (const auto *PtrTy = Param->getAs<PointerType>()) {
+ if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {
+ if (S.isCFError(RT->getDecl())) {
+ AnyErrorParams = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!AnyErrorParams) {
+ S.Diag(ErrorAttr->getLocation(),
+ diag::err_swift_async_error_no_error_parameter)
+ << ErrorAttr << isa<ObjCMethodDecl>(D);
+ return;
+ }
+ break;
+ }
+ case SwiftAsyncErrorAttr::None:
+ break;
+ }
+}
+
+static void handleSwiftAsyncError(Sema &S, Decl *D, const ParsedAttr &AL) {
+ IdentifierLoc *IDLoc = AL.getArgAsIdent(0);
+ SwiftAsyncErrorAttr::ConventionKind ConvKind;
+ if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(),
+ ConvKind)) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+ << AL << IDLoc->Ident;
+ return;
+ }
+
+ uint32_t ParamIdx = 0;
+ switch (ConvKind) {
+ case SwiftAsyncErrorAttr::ZeroArgument:
+ case SwiftAsyncErrorAttr::NonZeroArgument: {
+ if (!AL.checkExactlyNumArgs(S, 2))
+ return;
+
+ Expr *IdxExpr = AL.getArgAsExpr(1);
+ if (!checkUInt32Argument(S, AL, IdxExpr, ParamIdx))
+ return;
+ break;
+ }
+ case SwiftAsyncErrorAttr::NonNullError:
+ case SwiftAsyncErrorAttr::None: {
+ if (!AL.checkExactlyNumArgs(S, 1))
+ return;
+ break;
+ }
+ }
+
+ auto *ErrorAttr =
+ ::new (S.Context) SwiftAsyncErrorAttr(S.Context, AL, ConvKind, ParamIdx);
+ D->addAttr(ErrorAttr);
+
+ if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>())
+ checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
+}
+
// For a function, this will validate a compound Swift name, e.g.
// <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
// the function will output the number of parameter names, and whether this is a
@@ -6168,7 +6334,7 @@
static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) {
// Make sure that there is an identifier as the annotation's single argument.
- if (!checkAttributeNumArgs(S, AL, 1))
+ if (!AL.checkExactlyNumArgs(S, 1))
return;
if (!AL.isArgIdent(0)) {
@@ -6210,11 +6376,11 @@
ParamIdx Idx;
if (Kind == SwiftAsyncAttr::None) {
// If this is 'none', then there shouldn't be any additional arguments.
- if (!checkAttributeNumArgs(S, AL, 1))
+ if (!AL.checkExactlyNumArgs(S, 1))
return;
} else {
// Non-none swift_async requires a completion handler index argument.
- if (!checkAttributeNumArgs(S, AL, 2))
+ if (!AL.checkExactlyNumArgs(S, 2))
return;
Expr *HandlerIdx = AL.getArgAsExpr(1);
@@ -6231,8 +6397,8 @@
return;
}
QualType BlockTy =
- CompletionBlockType->getAs<BlockPointerType>()->getPointeeType();
- if (!BlockTy->getAs<FunctionType>()->getReturnType()->isVoidType()) {
+ CompletionBlockType->castAs<BlockPointerType>()->getPointeeType();
+ if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) {
S.Diag(CompletionBlock->getLocation(),
diag::err_swift_async_bad_block_type)
<< CompletionBlock->getType();
@@ -6240,7 +6406,12 @@
}
}
- D->addAttr(::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx));
+ auto *AsyncAttr =
+ ::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx);
+ D->addAttr(AsyncAttr);
+
+ if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>())
+ checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
}
//===----------------------------------------------------------------------===//
@@ -6373,7 +6544,7 @@
}
if (AL.getNumArgs() == 0)
Tags.push_back(NS->getName());
- } else if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ } else if (!AL.checkAtLeastNumArgs(S, 1))
return;
// Store tags sorted and without duplicates.
@@ -6431,7 +6602,7 @@
}
// The attribute takes one integer argument.
- if (!checkAttributeNumArgs(S, AL, 1))
+ if (!AL.checkExactlyNumArgs(S, 1))
return;
if (!AL.isArgExpr(0)) {
@@ -6503,6 +6674,8 @@
return;
}
+ // We still have to do this manually because the Interrupt attributes are
+ // a bit special due to sharing their spellings across targets.
if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL))
return;
@@ -6516,6 +6689,39 @@
D->addAttr(::new (S.Context) MipsInterruptAttr(S.Context, AL, Kind));
}
+static void handleM68kInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!AL.checkExactlyNumArgs(S, 1))
+ return;
+
+ if (!AL.isArgExpr(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIntegerConstant;
+ return;
+ }
+
+ // FIXME: Check for decl - it should be void ()(void).
+
+ Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
+ auto MaybeNumParams = NumParamsExpr->getIntegerConstantExpr(S.Context);
+ if (!MaybeNumParams) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
+ << AL << AANT_ArgumentIntegerConstant
+ << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ unsigned Num = MaybeNumParams->getLimitedValue(255);
+ if ((Num & 1) || Num > 30) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL << (int)MaybeNumParams->getSExtValue()
+ << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ D->addAttr(::new (S.Context) M68kInterruptAttr(S.Context, AL, Num));
+ D->addAttr(UsedAttr::CreateImplicit(S.Context));
+}
+
static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// Semantic checks for a function with the 'interrupt' attribute.
// a) Must be a function.
@@ -6587,7 +6793,7 @@
return;
}
- if (!checkAttributeNumArgs(S, AL, 0))
+ if (!AL.checkExactlyNumArgs(S, 0))
return;
handleSimpleAttribute<AVRInterruptAttr>(S, D, AL);
@@ -6600,7 +6806,7 @@
return;
}
- if (!checkAttributeNumArgs(S, AL, 0))
+ if (!AL.checkExactlyNumArgs(S, 0))
return;
handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
@@ -6731,7 +6937,7 @@
}
// Check the attribute argument. Argument is optional.
- if (!checkAttributeAtMostNumArgs(S, AL, 1))
+ if (!AL.checkAtMostNumArgs(S, 1))
return;
StringRef Str;
@@ -6788,6 +6994,9 @@
case llvm::Triple::mips:
handleMipsInterruptAttr(S, D, AL);
break;
+ case llvm::Triple::m68k:
+ handleM68kInterruptAttr(S, D, AL);
+ break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
handleAnyX86InterruptAttr(S, D, AL);
@@ -6901,8 +7110,7 @@
}
static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1) ||
- !checkAttributeAtMostNumArgs(S, AL, 2))
+ if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
return;
Expr *MinExpr = AL.getArgAsExpr(0);
@@ -7125,7 +7333,7 @@
static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1))
return;
// check that all arguments are lockable objects
@@ -7149,6 +7357,11 @@
// namespace.
return;
}
+ } else if (isa<UsingDecl, UnresolvedUsingTypenameDecl,
+ UnresolvedUsingValueDecl>(D)) {
+ S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using)
+ << AL;
+ return;
}
// Handle the cases where the attribute has a text message.
@@ -7157,9 +7370,9 @@
!S.checkStringLiteralArgumentAttr(AL, 0, Str))
return;
- // Only support a single optional message for Declspec and CXX11.
- if (AL.isDeclspecAttribute() || AL.isCXX11Attribute())
- checkAttributeAtMostNumArgs(S, AL, 1);
+ // Support a single optional message only for Declspec and [[]] spellings.
+ if (AL.isDeclspecAttribute() || AL.isStandardAttributeSyntax())
+ AL.checkAtMostNumArgs(S, 1);
else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) &&
!S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
return;
@@ -7177,7 +7390,7 @@
}
static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (!checkAttributeAtLeastNumArgs(S, AL, 1))
+ if (!AL.checkAtLeastNumArgs(S, 1))
return;
std::vector<StringRef> Sanitizers;
@@ -7190,7 +7403,8 @@
return;
if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) ==
- SanitizerMask())
+ SanitizerMask() &&
+ SanitizerName != "coverage")
S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
else if (isGlobalVar(D) && SanitizerName != "address")
S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
@@ -7224,7 +7438,7 @@
// getSpelling() or prettyPrint() on the resulting semantic attribute object
// without failing assertions.
unsigned TranslatedSpellingIndex = 0;
- if (AL.isC2xAttribute() || AL.isCXX11Attribute())
+ if (AL.isStandardAttributeSyntax())
TranslatedSpellingIndex = 1;
AttributeCommonInfo Info = AL;
@@ -7247,49 +7461,6 @@
<< "2.0";
}
-/// Handles semantic checking for features that are common to all attributes,
-/// such as checking whether a parameter was properly specified, or the correct
-/// number of arguments were passed, etc.
-static bool handleCommonAttributeFeatures(Sema &S, Decl *D,
- const ParsedAttr &AL) {
- // Several attributes carry different semantics than the parsing requires, so
- // those are opted out of the common argument checks.
- //
- // We also bail on unknown and ignored attributes because those are handled
- // as part of the target-specific handling logic.
- if (AL.getKind() == ParsedAttr::UnknownAttribute)
- return false;
- // Check whether the attribute requires specific language extensions to be
- // enabled.
- if (!AL.diagnoseLangOpts(S))
- return true;
- // Check whether the attribute appertains to the given subject.
- if (!AL.diagnoseAppertainsTo(S, D))
- return true;
- if (AL.hasCustomParsing())
- return false;
-
- if (AL.getMinArgs() == AL.getMaxArgs()) {
- // If there are no optional arguments, then checking for the argument count
- // is trivial.
- if (!checkAttributeNumArgs(S, AL, AL.getMinArgs()))
- return true;
- } else {
- // There are optional arguments, so checking is slightly more involved.
- if (AL.getMinArgs() &&
- !checkAttributeAtLeastNumArgs(S, AL, AL.getMinArgs()))
- return true;
- else if (!AL.hasVariadicArg() && AL.getMaxArgs() &&
- !checkAttributeAtMostNumArgs(S, AL, AL.getMaxArgs()))
- return true;
- }
-
- if (S.CheckAttrTarget(AL))
- return true;
-
- return false;
-}
-
static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (D->isInvalidDecl())
return;
@@ -7308,16 +7479,24 @@
}
}
- // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an
- // image object can be read and written.
- // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe
- // object. Using the read_write (or __read_write) qualifier with the pipe
- // qualifier is a compilation error.
+ // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that
+ // an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel
+ // cannot read from and write to the same pipe object. Using the read_write
+ // (or __read_write) qualifier with the pipe qualifier is a compilation error.
+ // OpenCL v3.0 s6.8 - For OpenCL C 2.0, or with the
+ // __opencl_c_read_write_images feature, image objects specified as arguments
+ // to a kernel can additionally be declared to be read-write.
+ // C++ for OpenCL inherits rule from OpenCL C v2.0.
if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
if (AL.getAttrName()->getName().find("read_write") != StringRef::npos) {
+ bool ReadWriteImagesUnsupportedForOCLC =
+ (S.getLangOpts().OpenCLVersion < 200) ||
+ (S.getLangOpts().OpenCLVersion == 300 &&
+ !S.getOpenCLOptions().isSupported("__opencl_c_read_write_images",
+ S.getLangOpts()));
if ((!S.getLangOpts().OpenCLCPlusPlus &&
- S.getLangOpts().OpenCLVersion < 200) ||
+ ReadWriteImagesUnsupportedForOCLC) ||
DeclTy->isPipeType()) {
S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
<< AL << PDecl->getType() << DeclTy->isImageType();
@@ -7377,9 +7556,9 @@
}
if (A.getKind() == ParsedAttr::AT_AlwaysDestroy)
- handleSimpleAttributeWithExclusions<AlwaysDestroyAttr, NoDestroyAttr>(S, D, A);
+ handleSimpleAttribute<AlwaysDestroyAttr>(S, D, A);
else
- handleSimpleAttributeWithExclusions<NoDestroyAttr, AlwaysDestroyAttr>(S, D, A);
+ handleSimpleAttribute<NoDestroyAttr>(S, D, A);
}
static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
@@ -7643,7 +7822,7 @@
return;
}
- if (handleCommonAttributeFeatures(S, D, AL))
+ if (S.checkCommonAttributeFeatures(D, AL))
return;
switch (AL.getKind()) {
@@ -7655,6 +7834,9 @@
assert(AL.isTypeAttr() && "Non-type attribute not handled");
break;
}
+ // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
+ // statement attribute is not written on a declaration, but this code is
+ // needed for attributes in Attr.td that do not list any subjects.
S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
<< AL << D->getLocation();
break;
@@ -7668,21 +7850,6 @@
case ParsedAttr::AT_DLLImport:
handleDLLAttr(S, D, AL);
break;
- case ParsedAttr::AT_Mips16:
- handleSimpleAttributeWithExclusions<Mips16Attr, MicroMipsAttr,
- MipsInterruptAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_MicroMips:
- handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, AL);
- break;
- case ParsedAttr::AT_MipsLongCall:
- handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>(
- S, D, AL);
- break;
- case ParsedAttr::AT_MipsShortCall:
- handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>(
- S, D, AL);
- break;
case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL);
break;
@@ -7816,22 +7983,9 @@
case ParsedAttr::AT_CUDADevice:
handleDeviceAttr(S, D, AL);
break;
- case ParsedAttr::AT_CUDAHost:
- handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL);
- break;
case ParsedAttr::AT_HIPManaged:
handleManagedAttr(S, D, AL);
break;
- case ParsedAttr::AT_CUDADeviceBuiltinSurfaceType:
- handleSimpleAttributeWithExclusions<CUDADeviceBuiltinSurfaceTypeAttr,
- CUDADeviceBuiltinTextureTypeAttr>(S, D,
- AL);
- break;
- case ParsedAttr::AT_CUDADeviceBuiltinTextureType:
- handleSimpleAttributeWithExclusions<CUDADeviceBuiltinTextureTypeAttr,
- CUDADeviceBuiltinSurfaceTypeAttr>(S, D,
- AL);
- break;
case ParsedAttr::AT_GNUInline:
handleGNUInlineAttr(S, D, AL);
break;
@@ -7865,12 +8019,6 @@
case ParsedAttr::AT_Ownership:
handleOwnershipAttr(S, D, AL);
break;
- case ParsedAttr::AT_Cold:
- handleSimpleAttributeWithExclusions<ColdAttr, HotAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Hot:
- handleSimpleAttributeWithExclusions<HotAttr, ColdAttr>(S, D, AL);
- break;
case ParsedAttr::AT_Naked:
handleNakedAttr(S, D, AL);
break;
@@ -7880,9 +8028,6 @@
case ParsedAttr::AT_AnyX86NoCfCheck:
handleNoCfCheckAttr(S, D, AL);
break;
- case ParsedAttr::AT_Leaf:
- handleSimpleAttribute<LeafAttr>(S, D, AL);
- break;
case ParsedAttr::AT_NoThrow:
if (!AL.isUsedAsTypeAttr())
handleSimpleAttribute<NoThrowAttr>(S, D, AL);
@@ -7926,14 +8071,6 @@
case ParsedAttr::AT_NSErrorDomain:
handleNSErrorDomain(S, D, AL);
break;
- case ParsedAttr::AT_CFAuditedTransfer:
- handleSimpleAttributeWithExclusions<CFAuditedTransferAttr,
- CFUnknownTransferAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_CFUnknownTransfer:
- handleSimpleAttributeWithExclusions<CFUnknownTransferAttr,
- CFAuditedTransferAttr>(S, D, AL);
- break;
case ParsedAttr::AT_CFConsumed:
case ParsedAttr::AT_NSConsumed:
case ParsedAttr::AT_OSConsumed:
@@ -7974,10 +8111,6 @@
handleVecTypeHint(S, D, AL);
break;
case ParsedAttr::AT_InitPriority:
- if (S.Context.getTargetInfo().getTriple().isOSAIX())
- llvm::report_fatal_error(
- "'init_priority' attribute is not yet supported on AIX");
- else
handleInitPriorityAttr(S, D, AL);
break;
case ParsedAttr::AT_Packed:
@@ -7989,15 +8122,6 @@
case ParsedAttr::AT_Section:
handleSectionAttr(S, D, AL);
break;
- case ParsedAttr::AT_SpeculativeLoadHardening:
- handleSimpleAttributeWithExclusions<SpeculativeLoadHardeningAttr,
- NoSpeculativeLoadHardeningAttr>(S, D,
- AL);
- break;
- case ParsedAttr::AT_NoSpeculativeLoadHardening:
- handleSimpleAttributeWithExclusions<NoSpeculativeLoadHardeningAttr,
- SpeculativeLoadHardeningAttr>(S, D, AL);
- break;
case ParsedAttr::AT_CodeSeg:
handleCodeSegAttr(S, D, AL);
break;
@@ -8016,9 +8140,6 @@
case ParsedAttr::AT_ObjCDirect:
handleObjCDirectAttr(S, D, AL);
break;
- case ParsedAttr::AT_ObjCNonRuntimeProtocol:
- handleObjCNonRuntimeProtocolAttr(S, D, AL);
- break;
case ParsedAttr::AT_ObjCDirectMembers:
handleObjCDirectMembersAttr(S, D, AL);
handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
@@ -8029,17 +8150,6 @@
case ParsedAttr::AT_Unused:
handleUnusedAttr(S, D, AL);
break;
- case ParsedAttr::AT_NotTailCalled:
- handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>(
- S, D, AL);
- break;
- case ParsedAttr::AT_DisableTailCalls:
- handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D,
- AL);
- break;
- case ParsedAttr::AT_NoMerge:
- handleSimpleAttribute<NoMergeAttr>(S, D, AL);
- break;
case ParsedAttr::AT_Visibility:
handleVisibilityAttr(S, D, AL, false);
break;
@@ -8089,6 +8199,7 @@
case ParsedAttr::AT_Pascal:
case ParsedAttr::AT_RegCall:
case ParsedAttr::AT_SwiftCall:
+ case ParsedAttr::AT_SwiftAsyncCall:
case ParsedAttr::AT_VectorCall:
case ParsedAttr::AT_MSABI:
case ParsedAttr::AT_SysVABI:
@@ -8115,6 +8226,9 @@
case ParsedAttr::AT_SwiftContext:
S.AddParameterABIAttr(D, AL, ParameterABI::SwiftContext);
break;
+ case ParsedAttr::AT_SwiftAsyncContext:
+ S.AddParameterABIAttr(D, AL, ParameterABI::SwiftAsyncContext);
+ break;
case ParsedAttr::AT_SwiftErrorResult:
S.AddParameterABIAttr(D, AL, ParameterABI::SwiftErrorResult);
break;
@@ -8247,9 +8361,6 @@
case ParsedAttr::AT_SwiftBridge:
handleSwiftBridge(S, D, AL);
break;
- case ParsedAttr::AT_SwiftBridgedTypedef:
- handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL);
- break;
case ParsedAttr::AT_SwiftError:
handleSwiftError(S, D, AL);
break;
@@ -8259,15 +8370,12 @@
case ParsedAttr::AT_SwiftNewType:
handleSwiftNewType(S, D, AL);
break;
- case ParsedAttr::AT_SwiftObjCMembers:
- handleSimpleAttribute<SwiftObjCMembersAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_SwiftPrivate:
- handleSimpleAttribute<SwiftPrivateAttr>(S, D, AL);
- break;
case ParsedAttr::AT_SwiftAsync:
handleSwiftAsyncAttr(S, D, AL);
break;
+ case ParsedAttr::AT_SwiftAsyncError:
+ handleSwiftAsyncError(S, D, AL);
+ break;
// XRay attributes.
case ParsedAttr::AT_XRayLogArgs:
@@ -8287,10 +8395,6 @@
handleUninitializedAttr(S, D, AL);
break;
- case ParsedAttr::AT_LoaderUninitialized:
- handleSimpleAttribute<LoaderUninitializedAttr>(S, D, AL);
- break;
-
case ParsedAttr::AT_ObjCExternallyRetained:
handleObjCExternallyRetainedAttr(S, D, AL);
break;
@@ -8326,6 +8430,14 @@
case ParsedAttr::AT_EnforceTCBLeaf:
handleEnforceTCBAttr<EnforceTCBLeafAttr, EnforceTCBAttr>(S, D, AL);
break;
+
+ case ParsedAttr::AT_BuiltinAlias:
+ handleBuiltinAliasAttr(S, D, AL);
+ break;
+
+ case ParsedAttr::AT_UsingIfExists:
+ handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL);
+ break;
}
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp b/src/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp
index 8bfaa46..da4f4f8 100644
--- a/src/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp
@@ -254,8 +254,7 @@
ComputedEST = EST_None;
}
-ExprResult Sema::ConvertParamDefaultArgument(const ParmVarDecl *Param,
- Expr *Arg,
+ExprResult Sema::ConvertParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
SourceLocation EqualLoc) {
if (RequireCompleteType(Param->getLocation(), Param->getType(),
diag::err_typecheck_decl_incomplete_type))
@@ -316,7 +315,7 @@
auto Fail = [&] {
Param->setInvalidDecl();
Param->setDefaultArg(new (Context) OpaqueValueExpr(
- EqualLoc, Param->getType().getNonReferenceType(), VK_RValue));
+ EqualLoc, Param->getType().getNonReferenceType(), VK_PRValue));
};
// Default arguments are only permitted in C++
@@ -381,10 +380,8 @@
ParmVarDecl *Param = cast<ParmVarDecl>(param);
Param->setInvalidDecl();
UnparsedDefaultArgLocs.erase(Param);
- Param->setDefaultArg(new(Context)
- OpaqueValueExpr(EqualLoc,
- Param->getType().getNonReferenceType(),
- VK_RValue));
+ Param->setDefaultArg(new (Context) OpaqueValueExpr(
+ EqualLoc, Param->getType().getNonReferenceType(), VK_PRValue));
}
/// CheckExtraCXXDefaultArguments - Check for any extra default
@@ -857,17 +854,25 @@
Previous.clear();
}
+ auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name);
+
+ // Find the shadowed declaration before filtering for scope.
+ NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty()
+ ? getShadowedDeclaration(BD, Previous)
+ : nullptr;
+
bool ConsiderLinkage = DC->isFunctionOrMethod() &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern;
FilterLookupForScope(Previous, DC, S, ConsiderLinkage,
/*AllowInlineNamespace*/false);
+
if (!Previous.empty()) {
auto *Old = Previous.getRepresentativeDecl();
Diag(B.NameLoc, diag::err_redefinition) << B.Name;
Diag(Old->getLocation(), diag::note_previous_definition);
+ } else if (ShadowedDecl && !D.isRedeclaration()) {
+ CheckShadow(BD, ShadowedDecl, Previous);
}
-
- auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name);
PushOnScopeChains(BD, S, true);
Bindings.push_back(BD);
ParsingInitForAutoVars.insert(BD);
@@ -903,8 +908,8 @@
if ((int64_t)Bindings.size() != NumElems) {
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
<< DecompType << (unsigned)Bindings.size()
- << (unsigned)NumElems.getLimitedValue(UINT_MAX) << NumElems.toString(10)
- << (NumElems < Bindings.size());
+ << (unsigned)NumElems.getLimitedValue(UINT_MAX)
+ << toString(NumElems, 10) << (NumElems < Bindings.size());
return true;
}
@@ -969,15 +974,20 @@
}
static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy,
- TemplateArgumentListInfo &Args) {
+ TemplateArgumentListInfo &Args,
+ const TemplateParameterList *Params) {
SmallString<128> SS;
llvm::raw_svector_ostream OS(SS);
bool First = true;
+ unsigned I = 0;
for (auto &Arg : Args.arguments()) {
if (!First)
OS << ", ";
- Arg.getArgument().print(PrintingPolicy, OS);
+ Arg.getArgument().print(
+ PrintingPolicy, OS,
+ TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
First = false;
+ I++;
}
return std::string(OS.str());
}
@@ -989,7 +999,7 @@
auto DiagnoseMissing = [&] {
if (DiagID)
S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(),
- Args);
+ Args, /*Params*/ nullptr);
return true;
};
@@ -1027,7 +1037,8 @@
if (DiagID)
S.RequireCompleteType(
Loc, TraitTy, DiagID,
- printTemplateArgs(S.Context.getPrintingPolicy(), Args));
+ printTemplateArgs(S.Context.getPrintingPolicy(), Args,
+ TraitTD->getTemplateParameters()));
return true;
}
@@ -1082,7 +1093,8 @@
Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
SourceLocation Loc) override {
return S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
- << printTemplateArgs(S.Context.getPrintingPolicy(), Args);
+ << printTemplateArgs(S.Context.getPrintingPolicy(), Args,
+ /*Params*/ nullptr);
}
} Diagnoser(R, Args);
@@ -1118,7 +1130,8 @@
if (!TD) {
R.suppressDiagnostics();
S.Diag(Loc, diag::err_decomp_decl_std_tuple_element_not_specialized)
- << printTemplateArgs(S.Context.getPrintingPolicy(), Args);
+ << printTemplateArgs(S.Context.getPrintingPolicy(), Args,
+ /*Params*/ nullptr);
if (!R.empty())
S.Diag(R.getRepresentativeDecl()->getLocation(), diag::note_declared_at);
return QualType();
@@ -1151,7 +1164,7 @@
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
<< DecompType << (unsigned)Bindings.size()
<< (unsigned)TupleSize.getLimitedValue(UINT_MAX)
- << TupleSize.toString(10) << (TupleSize < Bindings.size());
+ << toString(TupleSize, 10) << (TupleSize < Bindings.size());
return true;
}
@@ -1820,9 +1833,11 @@
case Decl::UsingDirective:
case Decl::UnresolvedUsingTypename:
case Decl::UnresolvedUsingValue:
+ case Decl::UsingEnum:
// - static_assert-declarations
// - using-declarations,
// - using-directives,
+ // - using-enum-declaration
continue;
case Decl::Typedef:
@@ -2493,6 +2508,14 @@
}
}
+ // Make sure that we don't make an ill-formed AST where the type of the
+ // Class is non-dependent and its attached base class specifier is an
+ // dependent type, which violates invariants in many clang code paths (e.g.
+ // constexpr evaluator). If this case happens (in errory-recovery mode), we
+ // explicitly mark the Class decl invalid. The diagnostic was already
+ // emitted.
+ if (!Class->getTypeForDecl()->isDependentType())
+ Class->setInvalidDecl();
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
Access, TInfo, EllipsisLoc);
@@ -4122,13 +4145,9 @@
IdentifierInfo *MemberOrBase) {
if (SS.getScopeRep() || TemplateTypeTy)
return nullptr;
- DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
- if (Result.empty())
- return nullptr;
- ValueDecl *Member;
- if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
- (Member = dyn_cast<IndirectFieldDecl>(Result.front())))
- return Member;
+ for (auto *D : ClassDecl->lookup(MemberOrBase))
+ if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D))
+ return cast<ValueDecl>(D);
return nullptr;
}
@@ -5231,6 +5250,20 @@
return Member->getAnyMember()->getCanonicalDecl();
}
+static void AddInitializerToDiag(const Sema::SemaDiagnosticBuilder &Diag,
+ const CXXCtorInitializer *Previous,
+ const CXXCtorInitializer *Current) {
+ if (Previous->isAnyMemberInitializer())
+ Diag << 0 << Previous->getAnyMember();
+ else
+ Diag << 1 << Previous->getTypeSourceInfo()->getType();
+
+ if (Current->isAnyMemberInitializer())
+ Diag << 0 << Current->getAnyMember();
+ else
+ Diag << 1 << Current->getTypeSourceInfo()->getType();
+}
+
static void DiagnoseBaseOrMemInitializerOrder(
Sema &SemaRef, const CXXConstructorDecl *Constructor,
ArrayRef<CXXCtorInitializer *> Inits) {
@@ -5280,10 +5313,15 @@
unsigned NumIdealInits = IdealInitKeys.size();
unsigned IdealIndex = 0;
- CXXCtorInitializer *PrevInit = nullptr;
+ // Track initializers that are in an incorrect order for either a warning or
+ // note if multiple ones occur.
+ SmallVector<unsigned> WarnIndexes;
+ // Correlates the index of an initializer in the init-list to the index of
+ // the field/base in the class.
+ SmallVector<std::pair<unsigned, unsigned>, 32> CorrelatedInitOrder;
+
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
- CXXCtorInitializer *Init = Inits[InitIndex];
- const void *InitKey = GetKeyForMember(SemaRef.Context, Init);
+ const void *InitKey = GetKeyForMember(SemaRef.Context, Inits[InitIndex]);
// Scan forward to try to find this initializer in the idealized
// initializers list.
@@ -5294,20 +5332,8 @@
// If we didn't find this initializer, it must be because we
// scanned past it on a previous iteration. That can only
// happen if we're out of order; emit a warning.
- if (IdealIndex == NumIdealInits && PrevInit) {
- Sema::SemaDiagnosticBuilder D =
- SemaRef.Diag(PrevInit->getSourceLocation(),
- diag::warn_initializer_out_of_order);
-
- if (PrevInit->isAnyMemberInitializer())
- D << 0 << PrevInit->getAnyMember()->getDeclName();
- else
- D << 1 << PrevInit->getTypeSourceInfo()->getType();
-
- if (Init->isAnyMemberInitializer())
- D << 0 << Init->getAnyMember()->getDeclName();
- else
- D << 1 << Init->getTypeSourceInfo()->getType();
+ if (IdealIndex == NumIdealInits && InitIndex) {
+ WarnIndexes.push_back(InitIndex);
// Move back to the initializer's location in the ideal list.
for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex)
@@ -5317,8 +5343,54 @@
assert(IdealIndex < NumIdealInits &&
"initializer not found in initializer list");
}
+ CorrelatedInitOrder.emplace_back(IdealIndex, InitIndex);
+ }
- PrevInit = Init;
+ if (WarnIndexes.empty())
+ return;
+
+ // Sort based on the ideal order, first in the pair.
+ llvm::sort(CorrelatedInitOrder,
+ [](auto &LHS, auto &RHS) { return LHS.first < RHS.first; });
+
+ // Introduce a new scope as SemaDiagnosticBuilder needs to be destroyed to
+ // emit the diagnostic before we can try adding notes.
+ {
+ Sema::SemaDiagnosticBuilder D = SemaRef.Diag(
+ Inits[WarnIndexes.front() - 1]->getSourceLocation(),
+ WarnIndexes.size() == 1 ? diag::warn_initializer_out_of_order
+ : diag::warn_some_initializers_out_of_order);
+
+ for (unsigned I = 0; I < CorrelatedInitOrder.size(); ++I) {
+ if (CorrelatedInitOrder[I].second == I)
+ continue;
+ // Ideally we would be using InsertFromRange here, but clang doesn't
+ // appear to handle InsertFromRange correctly when the source range is
+ // modified by another fix-it.
+ D << FixItHint::CreateReplacement(
+ Inits[I]->getSourceRange(),
+ Lexer::getSourceText(
+ CharSourceRange::getTokenRange(
+ Inits[CorrelatedInitOrder[I].second]->getSourceRange()),
+ SemaRef.getSourceManager(), SemaRef.getLangOpts()));
+ }
+
+ // If there is only 1 item out of order, the warning expects the name and
+ // type of each being added to it.
+ if (WarnIndexes.size() == 1) {
+ AddInitializerToDiag(D, Inits[WarnIndexes.front() - 1],
+ Inits[WarnIndexes.front()]);
+ return;
+ }
+ }
+ // More than 1 item to warn, create notes letting the user know which ones
+ // are bad.
+ for (unsigned WarnIndex : WarnIndexes) {
+ const clang::CXXCtorInitializer *PrevInit = Inits[WarnIndex - 1];
+ auto D = SemaRef.Diag(PrevInit->getSourceLocation(),
+ diag::note_initializer_out_of_order);
+ AddInitializerToDiag(D, PrevInit, Inits[WarnIndex]);
+ D << PrevInit->getSourceRange();
}
}
@@ -5386,7 +5458,7 @@
return false;
}
-}
+} // namespace
/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
@@ -6928,7 +7000,7 @@
: S(S), UseLoc(UseLoc) {
bool DiagnosedMultipleConstructedBases = false;
CXXRecordDecl *ConstructedBase = nullptr;
- UsingDecl *ConstructedBaseUsing = nullptr;
+ BaseUsingDecl *ConstructedBaseIntroducer = nullptr;
// Find the set of such base class subobjects and check that there's a
// unique constructed subobject.
@@ -6952,18 +7024,18 @@
// of type B, the program is ill-formed.
if (!ConstructedBase) {
ConstructedBase = DConstructedBase;
- ConstructedBaseUsing = D->getUsingDecl();
+ ConstructedBaseIntroducer = D->getIntroducer();
} else if (ConstructedBase != DConstructedBase &&
!Shadow->isInvalidDecl()) {
if (!DiagnosedMultipleConstructedBases) {
S.Diag(UseLoc, diag::err_ambiguous_inherited_constructor)
<< Shadow->getTargetDecl();
- S.Diag(ConstructedBaseUsing->getLocation(),
- diag::note_ambiguous_inherited_constructor_using)
+ S.Diag(ConstructedBaseIntroducer->getLocation(),
+ diag::note_ambiguous_inherited_constructor_using)
<< ConstructedBase;
DiagnosedMultipleConstructedBases = true;
}
- S.Diag(D->getUsingDecl()->getLocation(),
+ S.Diag(D->getIntroducer()->getLocation(),
diag::note_ambiguous_inherited_constructor_using)
<< DConstructedBase;
}
@@ -7220,6 +7292,9 @@
return;
}
+ if (DefKind.isComparison())
+ UnusedPrivateFields.clear();
+
if (DefKind.isSpecialMember()
? CheckExplicitlyDefaultedSpecialMember(cast<CXXMethodDecl>(FD),
DefKind.asSpecialMember())
@@ -7624,7 +7699,7 @@
private:
Subobject getCompleteObject() {
- return Subobject{Subobject::CompleteObject, nullptr, FD->getLocation()};
+ return Subobject{Subobject::CompleteObject, RD, FD->getLocation()};
}
Subobject getBase(CXXBaseSpecifier *Base) {
@@ -7677,12 +7752,11 @@
if (Args[0]->getType()->isOverloadableType())
S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args);
- else {
+ else
// FIXME: We determine whether this is a valid expression by checking to
// see if there's a viable builtin operator candidate for it. That isn't
// really what the rules ask us to do, but should give the right results.
S.AddBuiltinOperatorCandidates(OO, FD->getLocation(), Args, CandidateSet);
- }
Result R;
@@ -7726,11 +7800,14 @@
return Result::deleted();
}
- // C++2a [class.compare.default]p3 [P2002R0]:
- // A defaulted comparison function is constexpr-compatible if [...]
- // no overlod resolution performed [...] results in a non-constexpr
- // function.
+ bool NeedsDeducing =
+ OO == OO_Spaceship && FD->getReturnType()->isUndeducedAutoType();
+
if (FunctionDecl *BestFD = Best->Function) {
+ // C++2a [class.compare.default]p3 [P2002R0]:
+ // A defaulted comparison function is constexpr-compatible if
+ // [...] no overlod resolution performed [...] results in a
+ // non-constexpr function.
assert(!BestFD->isDeleted() && "wrong overload resolution result");
// If it's not constexpr, explain why not.
if (Diagnose == ExplainConstexpr && !BestFD->isConstexpr()) {
@@ -7743,10 +7820,8 @@
return Result::deleted();
}
R.Constexpr &= BestFD->isConstexpr();
- }
- if (OO == OO_Spaceship && FD->getReturnType()->isUndeducedAutoType()) {
- if (auto *BestFD = Best->Function) {
+ if (NeedsDeducing) {
// If any callee has an undeduced return type, deduce it now.
// FIXME: It's not clear how a failure here should be handled. For
// now, we produce an eager diagnostic, because that is forward
@@ -7772,10 +7847,9 @@
}
return Result::deleted();
}
- if (auto *Info = S.Context.CompCategories.lookupInfoForType(
- BestFD->getCallResultType())) {
- R.Category = Info->Kind;
- } else {
+ auto *Info = S.Context.CompCategories.lookupInfoForType(
+ BestFD->getCallResultType());
+ if (!Info) {
if (Diagnose == ExplainDeleted) {
S.Diag(Subobj.Loc, diag::note_defaulted_comparison_cannot_deduce)
<< Subobj.Kind << Subobj.Decl
@@ -7786,9 +7860,18 @@
}
return Result::deleted();
}
- } else {
+ R.Category = Info->Kind;
+ }
+ } else {
+ QualType T = Best->BuiltinParamTypes[0];
+ assert(T == Best->BuiltinParamTypes[1] &&
+ "builtin comparison for different types?");
+ assert(Best->BuiltinParamTypes[2].isNull() &&
+ "invalid builtin comparison");
+
+ if (NeedsDeducing) {
Optional<ComparisonCategoryType> Cat =
- getComparisonCategoryForBuiltinCmp(Args[0]->getType());
+ getComparisonCategoryForBuiltinCmp(T);
assert(Cat && "no category for builtin comparison?");
R.Category = *Cat;
}
@@ -8249,7 +8332,7 @@
assert(!R->isUndeducedType() && "type should have been deduced already");
// Don't bother forming a no-op cast in the common case.
- if (E->isRValue() && S.Context.hasSameType(E->getType(), R))
+ if (E->isPRValue() && S.Context.hasSameType(E->getType(), R))
return E;
return S.BuildCXXNamedCast(Loc, tok::kw_static_cast,
S.Context.getTrivialTypeSourceInfo(R, Loc), E,
@@ -9660,9 +9743,9 @@
bool foundSameNameMethod = false;
SmallVector<CXXMethodDecl *, 8> overloadedMethods;
- for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- NamedDecl *D = Path.Decls.front();
+ for (Path.Decls = BaseRecord->lookup(Name).begin();
+ Path.Decls != DeclContext::lookup_iterator(); ++Path.Decls) {
+ NamedDecl *D = *Path.Decls;
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
MD = MD->getCanonicalDecl();
foundSameNameMethod = true;
@@ -10814,26 +10897,6 @@
NamespaceDecl *PrevNS) {
assert(*IsInline != PrevNS->isInline());
- // HACK: Work around a bug in libstdc++4.6's <atomic>, where
- // std::__atomic[0,1,2] are defined as non-inline namespaces, then reopened as
- // inline namespaces, with the intention of bringing names into namespace std.
- //
- // We support this just well enough to get that case working; this is not
- // sufficient to support reopening namespaces as inline in general.
- if (*IsInline && II && II->getName().startswith("__atomic") &&
- S.getSourceManager().isInSystemHeader(Loc)) {
- // Mark all prior declarations of the namespace as inline.
- for (NamespaceDecl *NS = PrevNS->getMostRecentDecl(); NS;
- NS = NS->getPreviousDecl())
- NS->setInline(*IsInline);
- // Patch up the lookup table for the containing namespace. This isn't really
- // correct, but it's good enough for this particular case.
- for (auto *I : PrevNS->decls())
- if (auto *ND = dyn_cast<NamedDecl>(I))
- PrevNS->getParent()->makeDeclVisibleInContext(ND);
- return;
- }
-
if (PrevNS->isInline())
// The user probably just forgot the 'inline', so suggest that it
// be added back.
@@ -11551,7 +11614,41 @@
NamedDecl *UD =
BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc,
SS, TargetNameInfo, EllipsisLoc, AttrList,
- /*IsInstantiation*/false);
+ /*IsInstantiation*/ false,
+ AttrList.hasAttribute(ParsedAttr::AT_UsingIfExists));
+ if (UD)
+ PushOnScopeChains(UD, S, /*AddToContext*/ false);
+
+ return UD;
+}
+
+Decl *Sema::ActOnUsingEnumDeclaration(Scope *S, AccessSpecifier AS,
+ SourceLocation UsingLoc,
+ SourceLocation EnumLoc,
+ const DeclSpec &DS) {
+ switch (DS.getTypeSpecType()) {
+ case DeclSpec::TST_error:
+ // This will already have been diagnosed
+ return nullptr;
+
+ case DeclSpec::TST_enum:
+ break;
+
+ case DeclSpec::TST_typename:
+ Diag(DS.getTypeSpecTypeLoc(), diag::err_using_enum_is_dependent);
+ return nullptr;
+
+ default:
+ llvm_unreachable("unexpected DeclSpec type");
+ }
+
+ // As with enum-decls, we ignore attributes for now.
+ auto *Enum = cast<EnumDecl>(DS.getRepAsDecl());
+ if (auto *Def = Enum->getDefinition())
+ Enum = Def;
+
+ auto *UD = BuildUsingEnumDeclaration(S, AS, UsingLoc, EnumLoc,
+ DS.getTypeSpecTypeNameLoc(), Enum);
if (UD)
PushOnScopeChains(UD, S, /*AddToContext*/ false);
@@ -11571,13 +11668,19 @@
return Context.hasSameType(TD1->getUnderlyingType(),
TD2->getUnderlyingType());
+ // Two using_if_exists using-declarations are equivalent if both are
+ // unresolved.
+ if (isa<UnresolvedUsingIfExistsDecl>(D1) &&
+ isa<UnresolvedUsingIfExistsDecl>(D2))
+ return true;
+
return false;
}
/// Determines whether to create a using shadow decl for a particular
/// decl, given the set of decls existing prior to this using lookup.
-bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
+bool Sema::CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Orig,
const LookupResult &Previous,
UsingShadowDecl *&PrevShadow) {
// Diagnose finding a decl which is not from a base class of the
@@ -11596,38 +11699,39 @@
// This is invalid (during instantiation) in C++03 because B::foo
// resolves to the using decl in B, which is not a base class of D<T>.
// We can't diagnose it immediately because C<T> is an unknown
- // specialization. The UsingShadowDecl in D<T> then points directly
+ // specialization. The UsingShadowDecl in D<T> then points directly
// to A::foo, which will look well-formed when we instantiate.
// The right solution is to not collapse the shadow-decl chain.
- if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) {
- DeclContext *OrigDC = Orig->getDeclContext();
+ if (!getLangOpts().CPlusPlus11 && CurContext->isRecord())
+ if (auto *Using = dyn_cast<UsingDecl>(BUD)) {
+ DeclContext *OrigDC = Orig->getDeclContext();
- // Handle enums and anonymous structs.
- if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
- CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
- while (OrigRec->isAnonymousStructOrUnion())
- OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+ // Handle enums and anonymous structs.
+ if (isa<EnumDecl>(OrigDC))
+ OrigDC = OrigDC->getParent();
+ CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
+ while (OrigRec->isAnonymousStructOrUnion())
+ OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
- if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
- if (OrigDC == CurContext) {
- Diag(Using->getLocation(),
- diag::err_using_decl_nested_name_specifier_is_current_class)
- << Using->getQualifierLoc().getSourceRange();
+ if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
+ if (OrigDC == CurContext) {
+ Diag(Using->getLocation(),
+ diag::err_using_decl_nested_name_specifier_is_current_class)
+ << Using->getQualifierLoc().getSourceRange();
+ Diag(Orig->getLocation(), diag::note_using_decl_target);
+ Using->setInvalidDecl();
+ return true;
+ }
+
+ Diag(Using->getQualifierLoc().getBeginLoc(),
+ diag::err_using_decl_nested_name_specifier_is_not_base_class)
+ << Using->getQualifier() << cast<CXXRecordDecl>(CurContext)
+ << Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
Using->setInvalidDecl();
return true;
}
-
- Diag(Using->getQualifierLoc().getBeginLoc(),
- diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << Using->getQualifier()
- << cast<CXXRecordDecl>(CurContext)
- << Using->getQualifierLoc().getSourceRange();
- Diag(Orig->getLocation(), diag::note_using_decl_target);
- Using->setInvalidDecl();
- return true;
}
- }
if (Previous.empty()) return false;
@@ -11648,7 +11752,7 @@
// We can have UsingDecls in our Previous results because we use the same
// LookupResult for checking whether the UsingDecl itself is a valid
// redeclaration.
- if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D))
+ if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D) || isa<UsingEnumDecl>(D))
continue;
if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
@@ -11660,7 +11764,7 @@
!isa<UnresolvedUsingValueDecl>(Target) &&
DiagnoseClassNameShadow(
CurContext,
- DeclarationNameInfo(Using->getDeclName(), Using->getLocation())))
+ DeclarationNameInfo(BUD->getDeclName(), BUD->getLocation())))
return true;
}
@@ -11681,6 +11785,20 @@
if (FoundEquivalentDecl)
return false;
+ // Always emit a diagnostic for a mismatch between an unresolved
+ // using_if_exists and a resolved using declaration in either direction.
+ if (isa<UnresolvedUsingIfExistsDecl>(Target) !=
+ (isa_and_nonnull<UnresolvedUsingIfExistsDecl>(NonTag))) {
+ if (!NonTag && !Tag)
+ return false;
+ Diag(BUD->getLocation(), diag::err_using_decl_conflict);
+ Diag(Target->getLocation(), diag::note_using_decl_target);
+ Diag((NonTag ? NonTag : Tag)->getLocation(),
+ diag::note_using_decl_conflict);
+ BUD->setInvalidDecl();
+ return true;
+ }
+
if (FunctionDecl *FD = Target->getAsFunction()) {
NamedDecl *OldDecl = nullptr;
switch (CheckOverload(nullptr, FD, Previous, OldDecl,
@@ -11689,7 +11807,7 @@
return false;
case Ovl_NonFunction:
- Diag(Using->getLocation(), diag::err_using_decl_conflict);
+ Diag(BUD->getLocation(), diag::err_using_decl_conflict);
break;
// We found a decl with the exact signature.
@@ -11701,13 +11819,13 @@
return true;
// If we're not in a record, this is an error.
- Diag(Using->getLocation(), diag::err_using_decl_conflict);
+ Diag(BUD->getLocation(), diag::err_using_decl_conflict);
break;
}
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
- Using->setInvalidDecl();
+ BUD->setInvalidDecl();
return true;
}
@@ -11717,20 +11835,20 @@
// No conflict between a tag and a non-tag.
if (!Tag) return false;
- Diag(Using->getLocation(), diag::err_using_decl_conflict);
+ Diag(BUD->getLocation(), diag::err_using_decl_conflict);
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(Tag->getLocation(), diag::note_using_decl_conflict);
- Using->setInvalidDecl();
+ BUD->setInvalidDecl();
return true;
}
// No conflict between a tag and a non-tag.
if (!NonTag) return false;
- Diag(Using->getLocation(), diag::err_using_decl_conflict);
+ Diag(BUD->getLocation(), diag::err_using_decl_conflict);
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
- Using->setInvalidDecl();
+ BUD->setInvalidDecl();
return true;
}
@@ -11745,8 +11863,7 @@
}
/// Builds a shadow declaration corresponding to a 'using' declaration.
-UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
- UsingDecl *UD,
+UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD,
NamedDecl *Orig,
UsingShadowDecl *PrevDecl) {
// If we resolved to another shadow declaration, just coalesce them.
@@ -11762,19 +11879,20 @@
UsingShadowDecl *Shadow;
if (NonTemplateTarget && isa<CXXConstructorDecl>(NonTemplateTarget)) {
+ UsingDecl *Using = cast<UsingDecl>(BUD);
bool IsVirtualBase =
isVirtualDirectBase(cast<CXXRecordDecl>(CurContext),
- UD->getQualifier()->getAsRecordDecl());
+ Using->getQualifier()->getAsRecordDecl());
Shadow = ConstructorUsingShadowDecl::Create(
- Context, CurContext, UD->getLocation(), UD, Orig, IsVirtualBase);
+ Context, CurContext, Using->getLocation(), Using, Orig, IsVirtualBase);
} else {
- Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD,
- Target);
+ Shadow = UsingShadowDecl::Create(Context, CurContext, BUD->getLocation(),
+ Target->getDeclName(), BUD, Target);
}
- UD->addShadowDecl(Shadow);
+ BUD->addShadowDecl(Shadow);
- Shadow->setAccess(UD->getAccess());
- if (Orig->isInvalidDecl() || UD->isInvalidDecl())
+ Shadow->setAccess(BUD->getAccess());
+ if (Orig->isInvalidDecl() || BUD->isInvalidDecl())
Shadow->setInvalidDecl();
Shadow->setPreviousDecl(PrevDecl);
@@ -11830,7 +11948,7 @@
}
// ...and the using decl.
- Shadow->getUsingDecl()->removeShadowDecl(Shadow);
+ Shadow->getIntroducer()->removeShadowDecl(Shadow);
// TODO: complain somehow if Shadow was used. It shouldn't
// be possible for this to happen, because...?
@@ -11936,6 +12054,29 @@
};
} // end anonymous namespace
+/// Remove decls we can't actually see from a lookup being used to declare
+/// shadow using decls.
+///
+/// \param S - The scope of the potential shadow decl
+/// \param Previous - The lookup of a potential shadow decl's name.
+void Sema::FilterUsingLookup(Scope *S, LookupResult &Previous) {
+ // It is really dumb that we have to do this.
+ LookupResult::Filter F = Previous.makeFilter();
+ while (F.hasNext()) {
+ NamedDecl *D = F.next();
+ if (!isDeclInScope(D, CurContext, S))
+ F.erase();
+ // If we found a local extern declaration that's not ordinarily visible,
+ // and this declaration is being added to a non-block scope, ignore it.
+ // We're only checking for scope conflicts here, not also for violations
+ // of the linkage rules.
+ else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() &&
+ !(D->getIdentifierNamespace() & Decl::IDNS_Ordinary))
+ F.erase();
+ }
+ F.done();
+}
+
/// Builds a using declaration.
///
/// \param IsInstantiation - Whether this call arises from an
@@ -11945,7 +12086,8 @@
Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
- const ParsedAttributesView &AttrList, bool IsInstantiation) {
+ const ParsedAttributesView &AttrList, bool IsInstantiation,
+ bool IsUsingIfExists) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
assert(IdentLoc.isValid() && "Invalid TargetName location.");
@@ -11968,21 +12110,7 @@
if (S) {
LookupName(Previous, S);
- // It is really dumb that we have to do this.
- LookupResult::Filter F = Previous.makeFilter();
- while (F.hasNext()) {
- NamedDecl *D = F.next();
- if (!isDeclInScope(D, CurContext, S))
- F.erase();
- // If we found a local extern declaration that's not ordinarily visible,
- // and this declaration is being added to a non-block scope, ignore it.
- // We're only checking for scope conflicts here, not also for violations
- // of the linkage rules.
- else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() &&
- !(D->getIdentifierNamespace() & Decl::IDNS_Ordinary))
- F.erase();
- }
- F.done();
+ FilterUsingLookup(S, Previous);
} else {
assert(IsInstantiation && "no scope in non-instantiation");
if (CurContext->isRecord())
@@ -12009,15 +12137,22 @@
SS, IdentLoc, Previous))
return nullptr;
- // Check for bad qualifiers.
- if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo,
- IdentLoc))
+ // 'using_if_exists' doesn't make sense on an inherited constructor.
+ if (IsUsingIfExists && UsingName.getName().getNameKind() ==
+ DeclarationName::CXXConstructorName) {
+ Diag(UsingLoc, diag::err_using_if_exists_on_ctor);
return nullptr;
+ }
DeclContext *LookupContext = computeDeclContext(SS);
- NamedDecl *D;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
if (!LookupContext || EllipsisLoc.isValid()) {
+ NamedDecl *D;
+ // Dependent scope, or an unexpanded pack
+ if (!LookupContext && CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword,
+ SS, NameInfo, IdentLoc))
+ return nullptr;
+
if (HasTypenameKeyword) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
@@ -12031,6 +12166,7 @@
}
D->setAccess(AS);
CurContext->addDecl(D);
+ ProcessDeclAttributeList(S, D, AttrList);
return D;
}
@@ -12040,6 +12176,7 @@
UsingName, HasTypenameKeyword);
UD->setAccess(AS);
CurContext->addDecl(UD);
+ ProcessDeclAttributeList(S, UD, AttrList);
UD->setInvalidDecl(Invalid);
return UD;
};
@@ -12068,16 +12205,25 @@
LookupQualifiedName(R, LookupContext);
+ // Validate the context, now we have a lookup
+ if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo,
+ IdentLoc, &R))
+ return nullptr;
+
+ if (R.empty() && IsUsingIfExists)
+ R.addDecl(UnresolvedUsingIfExistsDecl::Create(Context, CurContext, UsingLoc,
+ UsingName.getName()),
+ AS_public);
+
// Try to correct typos if possible. If constructor name lookup finds no
// results, that means the named class has no explicit constructors, and we
// suppressed declaring implicit ones (probably because it's dependent or
// invalid).
if (R.empty() &&
NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) {
- // HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes
- // it will believe that glibc provides a ::gets in cases where it does not,
- // and will try to pull it into namespace std with a using-declaration.
- // Just ignore the using-declaration in that case.
+ // HACK 2017-01-08: Work around an issue with libstdc++'s detection of
+ // ::gets. Sometimes it believes that glibc provides a ::gets in cases where
+ // it does not. The issue was fixed in libstdc++ 6.3 (2016-12-21) and later.
auto *II = NameInfo.getName().getAsIdentifierInfo();
if (getLangOpts().CPlusPlus14 && II && II->isStr("gets") &&
CurContext->isStdNamespace() &&
@@ -12142,7 +12288,8 @@
if (HasTypenameKeyword) {
// If we asked for a typename and got a non-type decl, error out.
- if (!R.getAsSingle<TypeDecl>()) {
+ if (!R.getAsSingle<TypeDecl>() &&
+ !R.getAsSingle<UnresolvedUsingIfExistsDecl>()) {
Diag(IdentLoc, diag::err_using_typename_non_type);
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
Diag((*I)->getUnderlyingDecl()->getLocation(),
@@ -12168,16 +12315,6 @@
return BuildInvalid();
}
- // C++14 [namespace.udecl]p7:
- // A using-declaration shall not name a scoped enumerator.
- if (auto *ED = R.getAsSingle<EnumConstantDecl>()) {
- if (cast<EnumDecl>(ED->getDeclContext())->isScoped()) {
- Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_scoped_enum)
- << SS.getRange();
- return BuildInvalid();
- }
- }
-
UsingDecl *UD = BuildValid();
// Some additional rules apply to inheriting constructors.
@@ -12199,6 +12336,61 @@
return UD;
}
+NamedDecl *Sema::BuildUsingEnumDeclaration(Scope *S, AccessSpecifier AS,
+ SourceLocation UsingLoc,
+ SourceLocation EnumLoc,
+ SourceLocation NameLoc,
+ EnumDecl *ED) {
+ bool Invalid = false;
+
+ if (CurContext->getRedeclContext()->isRecord()) {
+ /// In class scope, check if this is a duplicate, for better a diagnostic.
+ DeclarationNameInfo UsingEnumName(ED->getDeclName(), NameLoc);
+ LookupResult Previous(*this, UsingEnumName, LookupUsingDeclName,
+ ForVisibleRedeclaration);
+
+ LookupName(Previous, S);
+
+ for (NamedDecl *D : Previous)
+ if (UsingEnumDecl *UED = dyn_cast<UsingEnumDecl>(D))
+ if (UED->getEnumDecl() == ED) {
+ Diag(UsingLoc, diag::err_using_enum_decl_redeclaration)
+ << SourceRange(EnumLoc, NameLoc);
+ Diag(D->getLocation(), diag::note_using_enum_decl) << 1;
+ Invalid = true;
+ break;
+ }
+ }
+
+ if (RequireCompleteEnumDecl(ED, NameLoc))
+ Invalid = true;
+
+ UsingEnumDecl *UD = UsingEnumDecl::Create(Context, CurContext, UsingLoc,
+ EnumLoc, NameLoc, ED);
+ UD->setAccess(AS);
+ CurContext->addDecl(UD);
+
+ if (Invalid) {
+ UD->setInvalidDecl();
+ return UD;
+ }
+
+ // Create the shadow decls for each enumerator
+ for (EnumConstantDecl *EC : ED->enumerators()) {
+ UsingShadowDecl *PrevDecl = nullptr;
+ DeclarationNameInfo DNI(EC->getDeclName(), EC->getLocation());
+ LookupResult Previous(*this, DNI, LookupOrdinaryName,
+ ForVisibleRedeclaration);
+ LookupName(Previous, S);
+ FilterUsingLookup(S, Previous);
+
+ if (!CheckUsingShadowDecl(UD, EC, Previous, PrevDecl))
+ BuildUsingShadowDecl(S, UD, EC, PrevDecl);
+ }
+
+ return UD;
+}
+
NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
ArrayRef<NamedDecl *> Expansions) {
assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) ||
@@ -12280,6 +12472,8 @@
return false;
}
+ const NestedNameSpecifier *CNNS =
+ Context.getCanonicalNestedNameSpecifier(Qual);
for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
NamedDecl *D = *I;
@@ -12305,8 +12499,7 @@
// using decls differ if they name different scopes (but note that
// template instantiation can cause this check to trigger when it
// didn't before instantiation).
- if (Context.getCanonicalNestedNameSpecifier(Qual) !=
- Context.getCanonicalNestedNameSpecifier(DQual))
+ if (CNNS != Context.getCanonicalNestedNameSpecifier(DQual))
continue;
Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
@@ -12317,48 +12510,83 @@
return false;
}
-
/// Checks that the given nested-name qualifier used in a using decl
/// in the current context is appropriately related to the current
/// scope. If an error is found, diagnoses it and returns true.
-bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
- bool HasTypename,
+/// R is nullptr, if the caller has not (yet) done a lookup, otherwise it's the
+/// result of that lookup. UD is likewise nullptr, except when we have an
+/// already-populated UsingDecl whose shadow decls contain the same information
+/// (i.e. we're instantiating a UsingDecl with non-dependent scope).
+bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename,
const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
- SourceLocation NameLoc) {
+ SourceLocation NameLoc,
+ const LookupResult *R, const UsingDecl *UD) {
DeclContext *NamedContext = computeDeclContext(SS);
+ assert(bool(NamedContext) == (R || UD) && !(R && UD) &&
+ "resolvable context must have exactly one set of decls");
+
+ // C++ 20 permits using an enumerator that does not have a class-hierarchy
+ // relationship.
+ bool Cxx20Enumerator = false;
+ if (NamedContext) {
+ EnumConstantDecl *EC = nullptr;
+ if (R)
+ EC = R->getAsSingle<EnumConstantDecl>();
+ else if (UD && UD->shadow_size() == 1)
+ EC = dyn_cast<EnumConstantDecl>(UD->shadow_begin()->getTargetDecl());
+ if (EC)
+ Cxx20Enumerator = getLangOpts().CPlusPlus20;
+
+ if (auto *ED = dyn_cast<EnumDecl>(NamedContext)) {
+ // C++14 [namespace.udecl]p7:
+ // A using-declaration shall not name a scoped enumerator.
+ // C++20 p1099 permits enumerators.
+ if (EC && R && ED->isScoped())
+ Diag(SS.getBeginLoc(),
+ getLangOpts().CPlusPlus20
+ ? diag::warn_cxx17_compat_using_decl_scoped_enumerator
+ : diag::ext_using_decl_scoped_enumerator)
+ << SS.getRange();
+
+ // We want to consider the scope of the enumerator
+ NamedContext = ED->getDeclContext();
+ }
+ }
if (!CurContext->isRecord()) {
// C++03 [namespace.udecl]p3:
// C++0x [namespace.udecl]p8:
// A using-declaration for a class member shall be a member-declaration.
+ // C++20 [namespace.udecl]p7
+ // ... other than an enumerator ...
// If we weren't able to compute a valid scope, it might validly be a
- // dependent class scope or a dependent enumeration unscoped scope. If
- // we have a 'typename' keyword, the scope must resolve to a class type.
- if ((HasTypename && !NamedContext) ||
- (NamedContext && NamedContext->getRedeclContext()->isRecord())) {
- auto *RD = NamedContext
- ? cast<CXXRecordDecl>(NamedContext->getRedeclContext())
- : nullptr;
- if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD))
- RD = nullptr;
+ // dependent class or enumeration scope. If we have a 'typename' keyword,
+ // the scope must resolve to a class type.
+ if (NamedContext ? !NamedContext->getRedeclContext()->isRecord()
+ : !HasTypename)
+ return false; // OK
- Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
+ Diag(NameLoc,
+ Cxx20Enumerator
+ ? diag::warn_cxx17_compat_using_decl_class_member_enumerator
+ : diag::err_using_decl_can_not_refer_to_class_member)
<< SS.getRange();
- // If we have a complete, non-dependent source type, try to suggest a
- // way to get the same effect.
- if (!RD)
- return true;
+ if (Cxx20Enumerator)
+ return false; // OK
- // Find what this using-declaration was referring to.
- LookupResult R(*this, NameInfo, LookupOrdinaryName);
- R.setHideTags(false);
- R.suppressDiagnostics();
- LookupQualifiedName(R, RD);
+ auto *RD = NamedContext
+ ? cast<CXXRecordDecl>(NamedContext->getRedeclContext())
+ : nullptr;
+ if (RD && !RequireCompleteDeclContext(const_cast<CXXScopeSpec &>(SS), RD)) {
+ // See if there's a helpful fixit
- if (R.getAsSingle<TypeDecl>()) {
+ if (!R) {
+ // We will have already diagnosed the problem on the template
+ // definition, Maybe we should do so again?
+ } else if (R->getAsSingle<TypeDecl>()) {
if (getLangOpts().CPlusPlus11) {
// Convert 'using X::Y;' to 'using Y = X::Y;'.
Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround)
@@ -12375,7 +12603,7 @@
<< FixItHint::CreateInsertion(
InsertLoc, " " + NameInfo.getName().getAsString());
}
- } else if (R.getAsSingle<VarDecl>()) {
+ } else if (R->getAsSingle<VarDecl>()) {
// Don't provide a fixit outside C++11 mode; we don't want to suggest
// repeating the type of the static data member here.
FixItHint FixIt;
@@ -12388,7 +12616,7 @@
Diag(UsingLoc, diag::note_using_decl_class_member_workaround)
<< 2 // reference declaration
<< FixIt;
- } else if (R.getAsSingle<EnumConstantDecl>()) {
+ } else if (R->getAsSingle<EnumConstantDecl>()) {
// Don't provide a fixit outside C++11 mode; we don't want to suggest
// repeating the type of the enumeration here, and we can't do so if
// the type is anonymous.
@@ -12404,15 +12632,11 @@
<< (getLangOpts().CPlusPlus11 ? 4 : 3) // const[expr] variable
<< FixIt;
}
- return true;
}
- // Otherwise, this might be valid.
- return false;
+ return true; // Fail
}
- // The current scope is a record.
-
// If the named context is dependent, we can't decide much.
if (!NamedContext) {
// FIXME: in C++0x, we can diagnose if we can prove that the
@@ -12424,12 +12648,19 @@
return false;
}
+ // The current scope is a record.
if (!NamedContext->isRecord()) {
// Ideally this would point at the last name in the specifier,
// but we don't have that level of source info.
- Diag(SS.getRange().getBegin(),
- diag::err_using_decl_nested_name_specifier_is_not_class)
- << SS.getScopeRep() << SS.getRange();
+ Diag(SS.getBeginLoc(),
+ Cxx20Enumerator
+ ? diag::warn_cxx17_compat_using_decl_non_member_enumerator
+ : diag::err_using_decl_nested_name_specifier_is_not_class)
+ << SS.getScopeRep() << SS.getRange();
+
+ if (Cxx20Enumerator)
+ return false; // OK
+
return true;
}
@@ -12445,19 +12676,25 @@
if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(
cast<CXXRecordDecl>(NamedContext))) {
+
+ if (Cxx20Enumerator) {
+ Diag(NameLoc, diag::warn_cxx17_compat_using_decl_non_member_enumerator)
+ << SS.getRange();
+ return false;
+ }
+
if (CurContext == NamedContext) {
- Diag(NameLoc,
+ Diag(SS.getBeginLoc(),
diag::err_using_decl_nested_name_specifier_is_current_class)
- << SS.getRange();
- return true;
+ << SS.getRange();
+ return !getLangOpts().CPlusPlus20;
}
if (!cast<CXXRecordDecl>(NamedContext)->isInvalidDecl()) {
- Diag(SS.getRange().getBegin(),
+ Diag(SS.getBeginLoc(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << SS.getScopeRep()
- << cast<CXXRecordDecl>(CurContext)
- << SS.getRange();
+ << SS.getScopeRep() << cast<CXXRecordDecl>(CurContext)
+ << SS.getRange();
}
return true;
}
@@ -12957,6 +13194,16 @@
auto QT = Context.getFunctionType(ResultTy, Args, EPI);
SpecialMem->setType(QT);
+
+ // During template instantiation of implicit special member functions we need
+ // a reliable TypeSourceInfo for the function prototype in order to allow
+ // functions to be substituted.
+ if (inTemplateInstantiation() &&
+ cast<CXXRecordDecl>(SpecialMem->getParent())->isLambda()) {
+ TypeSourceInfo *TSI =
+ Context.getTrivialTypeSourceInfo(SpecialMem->getType());
+ SpecialMem->setTypeSourceInfo(TSI);
+ }
}
CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
@@ -13592,11 +13839,11 @@
Expr *From = FromB.build(S, Loc);
From = UnaryOperator::Create(
S.Context, From, UO_AddrOf, S.Context.getPointerType(From->getType()),
- VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
+ VK_PRValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
Expr *To = ToB.build(S, Loc);
To = UnaryOperator::Create(
S.Context, To, UO_AddrOf, S.Context.getPointerType(To->getType()),
- VK_RValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
+ VK_PRValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides());
const Type *E = T->getBaseElementTypeUnsafe();
bool NeedsCollectableMemCpy =
@@ -13618,7 +13865,7 @@
return StmtError();
ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
- VK_RValue, Loc, nullptr);
+ VK_PRValue, Loc, nullptr);
assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");
Expr *CallArgs[] = {
@@ -13833,7 +14080,8 @@
Expr *Comparison = BinaryOperator::Create(
S.Context, IterationVarRefRVal.build(S, Loc),
IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE,
- S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, S.CurFPFeatureOverrides());
+ S.Context.BoolTy, VK_PRValue, OK_Ordinary, Loc,
+ S.CurFPFeatureOverrides());
// Create the pre-increment of the iteration variable. We can determine
// whether the increment will overflow based on the value of the array
@@ -13988,12 +14236,20 @@
assert(UserDeclaredOperation);
}
- if (UserDeclaredOperation && UserDeclaredOperation->isUserProvided()) {
- S.Diag(UserDeclaredOperation->getLocation(),
- isa<CXXDestructorDecl>(UserDeclaredOperation)
- ? diag::warn_deprecated_copy_dtor_operation
- : diag::warn_deprecated_copy_operation)
- << RD << /*copy assignment*/ !isa<CXXConstructorDecl>(CopyOp);
+ if (UserDeclaredOperation) {
+ bool UDOIsUserProvided = UserDeclaredOperation->isUserProvided();
+ bool UDOIsDestructor = isa<CXXDestructorDecl>(UserDeclaredOperation);
+ bool IsCopyAssignment = !isa<CXXConstructorDecl>(CopyOp);
+ unsigned DiagID =
+ (UDOIsUserProvided && UDOIsDestructor)
+ ? diag::warn_deprecated_copy_with_user_provided_dtor
+ : (UDOIsUserProvided && !UDOIsDestructor)
+ ? diag::warn_deprecated_copy_with_user_provided_copy
+ : (!UDOIsUserProvided && UDOIsDestructor)
+ ? diag::warn_deprecated_copy_with_dtor
+ : diag::warn_deprecated_copy;
+ S.Diag(UserDeclaredOperation->getLocation(), DiagID)
+ << RD << IsCopyAssignment;
}
}
@@ -14244,10 +14500,7 @@
/* Diagnose */ false);
}
- // Build an exception specification pointing back at this member.
- FunctionProtoType::ExtProtoInfo EPI =
- getImplicitMethodEPI(*this, MoveAssignment);
- MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
+ setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType);
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
@@ -14629,12 +14882,18 @@
setupImplicitSpecialMemberType(CopyConstructor, Context.VoidTy, ArgType);
+ // During template instantiation of special member functions we need a
+ // reliable TypeSourceInfo for the parameter types in order to allow functions
+ // to be substituted.
+ TypeSourceInfo *TSI = nullptr;
+ if (inTemplateInstantiation() && ClassDecl->isLambda())
+ TSI = Context.getTrivialTypeSourceInfo(ArgType);
+
// Add the parameter to the constructor.
- ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
- ClassLoc, ClassLoc,
- /*IdentifierInfo=*/nullptr,
- ArgType, /*TInfo=*/nullptr,
- SC_None, nullptr);
+ ParmVarDecl *FromParam =
+ ParmVarDecl::Create(Context, CopyConstructor, ClassLoc, ClassLoc,
+ /*IdentifierInfo=*/nullptr, ArgType,
+ /*TInfo=*/TSI, SC_None, nullptr);
CopyConstructor->setParams(FromParam);
CopyConstructor->setTrivial(
@@ -14852,9 +15111,9 @@
SynthesizedFunctionScope Scope(*this, Conv);
assert(!Conv->getReturnType()->isUndeducedType());
- QualType ConvRT = Conv->getType()->getAs<FunctionType>()->getReturnType();
+ QualType ConvRT = Conv->getType()->castAs<FunctionType>()->getReturnType();
CallingConv CC =
- ConvRT->getPointeeType()->getAs<FunctionType>()->getCallConv();
+ ConvRT->getPointeeType()->castAs<FunctionType>()->getCallConv();
CXXRecordDecl *Lambda = Conv->getParent();
FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
@@ -14931,7 +15190,7 @@
if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount)
BuildBlock = ImplicitCastExpr::Create(
Context, BuildBlock.get()->getType(), CK_CopyAndAutoreleaseBlockObject,
- BuildBlock.get(), nullptr, VK_RValue, FPOptionsOverride());
+ BuildBlock.get(), nullptr, VK_PRValue, FPOptionsOverride());
if (BuildBlock.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
@@ -15201,13 +15460,12 @@
/// to form a proper call to this constructor.
///
/// \returns true if an error occurred, false otherwise.
-bool
-Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
- MultiExprArg ArgsPtr,
- SourceLocation Loc,
- SmallVectorImpl<Expr*> &ConvertedArgs,
- bool AllowExplicit,
- bool IsListInitialization) {
+bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
+ QualType DeclInitType, MultiExprArg ArgsPtr,
+ SourceLocation Loc,
+ SmallVectorImpl<Expr *> &ConvertedArgs,
+ bool AllowExplicit,
+ bool IsListInitialization) {
// FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
unsigned NumArgs = ArgsPtr.size();
Expr **Args = ArgsPtr.data();
@@ -15234,7 +15492,7 @@
DiagnoseSentinelCalls(Constructor, Loc, AllArgs);
- CheckConstructorCall(Constructor,
+ CheckConstructorCall(Constructor, DeclInitType,
llvm::makeArrayRef(AllArgs.data(), AllArgs.size()),
Proto, Loc);
@@ -15261,11 +15519,13 @@
return false;
}
-static QualType
-RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) {
- QualType QTy = PtrTy->getPointeeType();
- QTy = SemaRef.Context.removeAddrSpaceQualType(QTy);
- return SemaRef.Context.getPointerType(QTy);
+static CanQualType RemoveAddressSpaceFromPtr(Sema &SemaRef,
+ const PointerType *PtrTy) {
+ auto &Ctx = SemaRef.Context;
+ Qualifiers PtrQuals = PtrTy->getPointeeType().getQualifiers();
+ PtrQuals.removeAddressSpace();
+ return Ctx.getPointerType(Ctx.getCanonicalType(Ctx.getQualifiedType(
+ PtrTy->getPointeeType().getUnqualifiedType(), PtrQuals)));
}
static inline bool
@@ -15277,11 +15537,14 @@
QualType ResultType =
FnDecl->getType()->castAs<FunctionType>()->getReturnType();
- // The operator is valid on any address space for OpenCL.
if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
- if (auto *PtrTy = ResultType->getAs<PointerType>()) {
+ // The operator is valid on any address space for OpenCL.
+ // Drop address space from actual and expected result types.
+ if (const auto *PtrTy = ResultType->getAs<PointerType>())
ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
- }
+
+ if (auto ExpectedPtrTy = ExpectedResultType->getAs<PointerType>())
+ ExpectedResultType = RemoveAddressSpaceFromPtr(SemaRef, ExpectedPtrTy);
}
// Check that the result type is what we expect.
@@ -15311,10 +15574,14 @@
QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
// The operator is valid on any address space for OpenCL.
- if (auto *PtrTy =
- FnDecl->getParamDecl(0)->getType()->getAs<PointerType>()) {
+ // Drop address space from actual and expected first parameter types.
+ if (const auto *PtrTy =
+ FnDecl->getParamDecl(0)->getType()->getAs<PointerType>())
FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
- }
+
+ if (auto ExpectedPtrTy = ExpectedFirstParamType->getAs<PointerType>())
+ ExpectedFirstParamType =
+ RemoveAddressSpaceFromPtr(SemaRef, ExpectedPtrTy);
}
// Check that the first parameter type is what we expect.
@@ -16723,6 +16990,8 @@
}
}
+ warnOnReservedIdentifier(ND);
+
return ND;
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaDeclObjC.cpp b/src/llvm-project/clang/lib/Sema/SemaDeclObjC.cpp
index 60253a8..e0f8c6e 100644
--- a/src/llvm-project/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaDeclObjC.cpp
@@ -4407,10 +4407,12 @@
void Sema::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
ObjCMethodDecl *overridden) {
- if (const auto *attr = overridden->getAttr<ObjCDirectAttr>()) {
+ if (overridden->isDirectMethod()) {
+ const auto *attr = overridden->getAttr<ObjCDirectAttr>();
Diag(method->getLocation(), diag::err_objc_override_direct_method);
Diag(attr->getLocation(), diag::note_previous_declaration);
- } else if (const auto *attr = method->getAttr<ObjCDirectAttr>()) {
+ } else if (method->isDirectMethod()) {
+ const auto *attr = method->getAttr<ObjCDirectAttr>();
Diag(attr->getLocation(), diag::err_objc_direct_on_override)
<< isa<ObjCProtocolDecl>(overridden->getDeclContext());
Diag(overridden->getLocation(), diag::note_previous_declaration);
@@ -4856,7 +4858,8 @@
// the canonical declaration.
if (!ObjCMethod->isDirectMethod()) {
const ObjCMethodDecl *CanonicalMD = ObjCMethod->getCanonicalDecl();
- if (const auto *attr = CanonicalMD->getAttr<ObjCDirectAttr>()) {
+ if (CanonicalMD->isDirectMethod()) {
+ const auto *attr = CanonicalMD->getAttr<ObjCDirectAttr>();
ObjCMethod->addAttr(
ObjCDirectAttr::CreateImplicit(Context, attr->getLocation()));
}
@@ -4901,14 +4904,16 @@
Diag(IMD->getLocation(), diag::note_previous_declaration);
};
- if (const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>()) {
+ if (ObjCMethod->isDirectMethod()) {
+ const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>();
if (ObjCMethod->getCanonicalDecl() != IMD) {
diagContainerMismatch();
} else if (!IMD->isDirectMethod()) {
Diag(attr->getLocation(), diag::err_objc_direct_missing_on_decl);
Diag(IMD->getLocation(), diag::note_previous_declaration);
}
- } else if (const auto *attr = IMD->getAttr<ObjCDirectAttr>()) {
+ } else if (IMD->isDirectMethod()) {
+ const auto *attr = IMD->getAttr<ObjCDirectAttr>();
if (ObjCMethod->getCanonicalDecl() != IMD) {
diagContainerMismatch();
} else {
diff --git a/src/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp b/src/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp
index 851e287..8816c9c 100644
--- a/src/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -35,10 +35,12 @@
return T->getAs<FunctionProtoType>();
}
-/// HACK: libstdc++ has a bug where it shadows std::swap with a member
-/// swap function then tries to call std::swap unqualified from the exception
-/// specification of that function. This function detects whether we're in
-/// such a case and turns off delay-parsing of exception specifications.
+/// HACK: 2014-11-14 libstdc++ had a bug where it shadows std::swap with a
+/// member swap function then tries to call std::swap unqualified from the
+/// exception specification of that function. This function detects whether
+/// we're in such a case and turns off delay-parsing of exception
+/// specifications. Libstdc++ 6.1 (released 2016-04-27) appears to have
+/// resolved it as side-effect of commit ddb63209a8d (2015-06-05).
bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
auto *RD = dyn_cast<CXXRecordDecl>(CurContext);
@@ -1448,6 +1450,7 @@
case Stmt::OMPMasterTaskLoopDirectiveClass:
case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
case Stmt::OMPOrderedDirectiveClass:
+ case Stmt::OMPCanonicalLoopClass:
case Stmt::OMPParallelDirectiveClass:
case Stmt::OMPParallelForDirectiveClass:
case Stmt::OMPParallelForSimdDirectiveClass:
@@ -1458,6 +1461,8 @@
case Stmt::OMPSectionDirectiveClass:
case Stmt::OMPSectionsDirectiveClass:
case Stmt::OMPSimdDirectiveClass:
+ case Stmt::OMPTileDirectiveClass:
+ case Stmt::OMPUnrollDirectiveClass:
case Stmt::OMPSingleDirectiveClass:
case Stmt::OMPTargetDataDirectiveClass:
case Stmt::OMPTargetDirectiveClass:
@@ -1484,6 +1489,9 @@
case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ case Stmt::OMPInteropDirectiveClass:
+ case Stmt::OMPDispatchDirectiveClass:
+ case Stmt::OMPMaskedDirectiveClass:
case Stmt::ReturnStmtClass:
case Stmt::SEHExceptStmtClass:
case Stmt::SEHFinallyStmtClass:
@@ -1568,6 +1576,8 @@
return mergeCanThrow(CT, canThrow(TS->getTryBody()));
}
+ case Stmt::SYCLUniqueStableNameExprClass:
+ return CT_Cannot;
case Stmt::NoStmtClass:
llvm_unreachable("Invalid class for statement");
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaExpr.cpp b/src/llvm-project/clang/lib/Sema/SemaExpr.cpp
index ae8508d..0e6c933 100644
--- a/src/llvm-project/clang/lib/Sema/SemaExpr.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaExpr.cpp
@@ -46,8 +46,11 @@
#include "clang/Sema/SemaFixItUtils.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/SaveAndRestore.h"
+
using namespace clang;
using namespace sema;
using llvm::RoundingMode;
@@ -82,6 +85,9 @@
cast<Decl>(CurContext)->getAvailability() != AR_Unavailable)
return false;
+ if (isa<UnresolvedUsingIfExistsDecl>(D))
+ return false;
+
return true;
}
@@ -347,6 +353,12 @@
return true;
}
+ if (const auto *EmptyD = dyn_cast<UnresolvedUsingIfExistsDecl>(D)) {
+ Diag(Loc, diag::err_use_of_empty_using_if_exists);
+ Diag(EmptyD->getLocation(), diag::note_empty_using_if_exists_here);
+ return true;
+ }
+
DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess,
AvoidPartialAvailabilityChecks, ClassReceiver);
@@ -354,24 +366,6 @@
diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc);
- // CUDA/HIP: Diagnose invalid references of host global variables in device
- // functions. Reference of device global variables in host functions is
- // allowed through shadow variables therefore it is not diagnosed.
- if (LangOpts.CUDAIsDevice) {
- auto *FD = dyn_cast_or_null<FunctionDecl>(CurContext);
- auto Target = IdentifyCUDATarget(FD);
- if (FD && Target != CFT_Host) {
- const auto *VD = dyn_cast<VarDecl>(D);
- if (VD && VD->hasGlobalStorage() && !VD->hasAttr<CUDADeviceAttr>() &&
- !VD->hasAttr<CUDAConstantAttr>() && !VD->hasAttr<CUDASharedAttr>() &&
- !VD->getType()->isCUDADeviceBuiltinSurfaceType() &&
- !VD->getType()->isCUDADeviceBuiltinTextureType() &&
- !VD->isConstexpr() && !VD->getType().isConstQualified())
- targetDiag(*Locs.begin(), diag::err_ref_bad_target)
- << /*host*/ 2 << /*variable*/ 1 << VD << Target;
- }
- }
-
if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) {
if (auto *VD = dyn_cast<ValueDecl>(D))
checkDeviceDecl(VD, Loc);
@@ -531,9 +525,13 @@
// An lvalue or rvalue of type "array of N T" or "array of unknown bound of
// T" can be converted to an rvalue of type "pointer to T".
//
- if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue())
- E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
- CK_ArrayToPointerDecay).get();
+ if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue()) {
+ ExprResult Res = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
+ CK_ArrayToPointerDecay);
+ if (Res.isInvalid())
+ return ExprError();
+ E = Res.get();
+ }
}
return E;
}
@@ -657,7 +655,8 @@
return E;
// OpenCL usually rejects direct accesses to values of 'half' type.
- if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
+ if (getLangOpts().OpenCL &&
+ !getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()) &&
T->isHalfType()) {
Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
<< 0 << T;
@@ -714,7 +713,7 @@
// C++ [conv.lval]p3:
// If T is cv std::nullptr_t, the result is a null pointer constant.
CastKind CK = T->isNullPtrType() ? CK_NullToPointer : CK_LValueToRValue;
- Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue,
+ Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_PRValue,
CurFPFeatureOverrides());
// C11 6.3.2.1p2:
@@ -723,7 +722,7 @@
if (const AtomicType *Atomic = T->getAs<AtomicType>()) {
T = Atomic->getValueType().getUnqualifiedType();
Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(),
- nullptr, VK_RValue, FPOptionsOverride());
+ nullptr, VK_PRValue, FPOptionsOverride());
}
return Res;
@@ -829,14 +828,27 @@
if (BTy && (BTy->getKind() == BuiltinType::Half ||
BTy->getKind() == BuiltinType::Float)) {
if (getLangOpts().OpenCL &&
- !getOpenCLOptions().isEnabled("cl_khr_fp64")) {
- if (BTy->getKind() == BuiltinType::Half) {
- E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
- }
+ !getOpenCLOptions().isAvailableOption("cl_khr_fp64", getLangOpts())) {
+ if (BTy->getKind() == BuiltinType::Half) {
+ E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
+ }
} else {
E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
}
}
+ if (BTy &&
+ getLangOpts().getExtendIntArgs() ==
+ LangOptions::ExtendArgsKind::ExtendTo64 &&
+ Context.getTargetInfo().supportsExtendIntArgs() && Ty->isIntegerType() &&
+ Context.getTypeSizeInChars(BTy) <
+ Context.getTypeSizeInChars(Context.LongLongTy)) {
+ E = (Ty->isUnsignedIntegerType())
+ ? ImpCastExprToType(E, Context.UnsignedLongLongTy, CK_IntegralCast)
+ .get()
+ : ImpCastExprToType(E, Context.LongLongTy, CK_IntegralCast).get();
+ assert(8 == Context.getTypeSizeInChars(Context.LongLongTy).getQuantity() &&
+ "Unexpected typesize for LongLongTy");
+ }
// C++ performs lvalue-to-rvalue conversion as a default argument
// promotion, even on class types, but note:
@@ -1533,11 +1545,6 @@
if (LHSType == RHSType)
return LHSType;
- // ExtInt types aren't subject to conversions between them or normal integers,
- // so this fails.
- if(LHSType->isExtIntType() || RHSType->isExtIntType())
- return QualType();
-
// At this point, we have two different arithmetic types.
// Diagnose attempts to convert between __float128 and long double where
@@ -3211,8 +3218,7 @@
}
// Make sure that we're referring to a value.
- ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (!VD) {
+ if (!isa<ValueDecl, UnresolvedUsingIfExistsDecl>(D)) {
Diag(Loc, diag::err_ref_non_value)
<< D << SS.getRange();
Diag(D->getLocation(), diag::note_declared_at);
@@ -3223,9 +3229,11 @@
// this check when we're going to perform argument-dependent lookup
// on this function name, because this might not be the function
// that overload resolution actually selects.
- if (DiagnoseUseOfDecl(VD, Loc))
+ if (DiagnoseUseOfDecl(D, Loc))
return ExprError();
+ auto *VD = cast<ValueDecl>(D);
+
// Only create DeclRefExpr's for valid Decl's.
if (VD->isInvalidDecl() && !AcceptInvalidDecl)
return ExprError();
@@ -3242,7 +3250,7 @@
QualType type = VD->getType();
if (type.isNull())
return ExprError();
- ExprValueKind valueKind = VK_RValue;
+ ExprValueKind valueKind = VK_PRValue;
// In 'T ...V;', the type of the declaration 'V' is 'T...', but the type of
// a reference to 'V' is simply (unexpanded) 'T'. The type, like the value,
@@ -3268,7 +3276,7 @@
case Decl::UnresolvedUsingValue:
case Decl::OMPDeclareReduction:
case Decl::OMPDeclareMapper:
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
break;
// Fields and indirect fields that got here must be for
@@ -3309,7 +3317,7 @@
// For non-references, we need to strip qualifiers just in case
// the template parameter was declared as 'const int' or whatever.
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
type = type.getUnqualifiedType();
break;
}
@@ -3323,7 +3331,7 @@
if (!getLangOpts().CPlusPlus &&
!type.hasQualifiers() &&
type->isVoidType()) {
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
break;
}
LLVM_FALLTHROUGH;
@@ -3365,7 +3373,7 @@
if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) {
if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
type = Context.BuiltinFnTy;
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
break;
}
}
@@ -3376,7 +3384,7 @@
// result type, make the entire expression __unknown_anytype.
if (fty->getReturnType() == Context.UnknownAnyTy) {
type = Context.UnknownAnyTy;
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
break;
}
@@ -3397,7 +3405,7 @@
fty->getExtInfo());
// Functions are r-values in C.
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
break;
}
@@ -3420,7 +3428,7 @@
= dyn_cast<FunctionProtoType>(VD->getType()))
if (proto->getReturnType() == Context.UnknownAnyTy) {
type = Context.UnknownAnyTy;
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
break;
}
@@ -3434,7 +3442,7 @@
case Decl::CXXConversion:
case Decl::CXXDestructor:
case Decl::CXXConstructor:
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
break;
}
@@ -3509,6 +3517,28 @@
return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL);
}
+ExprResult Sema::BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+ SourceLocation LParen,
+ SourceLocation RParen,
+ TypeSourceInfo *TSI) {
+ return SYCLUniqueStableNameExpr::Create(Context, OpLoc, LParen, RParen, TSI);
+}
+
+ExprResult Sema::ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+ SourceLocation LParen,
+ SourceLocation RParen,
+ ParsedType ParsedTy) {
+ TypeSourceInfo *TSI = nullptr;
+ QualType Ty = GetTypeFromParser(ParsedTy, &TSI);
+
+ if (Ty.isNull())
+ return ExprError();
+ if (!TSI)
+ TSI = Context.getTrivialTypeSourceInfo(Ty, LParen);
+
+ return BuildSYCLUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
+}
+
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
PredefinedExpr::IdentKind IK;
@@ -3642,7 +3672,7 @@
bool ValueIsPositive = ValueAPS.isStrictlyPositive();
if (!ValueIsPositive || ValueAPS.getActiveBits() > 31) {
Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_value)
- << ValueAPS.toString(10) << ValueIsPositive;
+ << toString(ValueAPS, 10) << ValueIsPositive;
return true;
}
@@ -3819,7 +3849,7 @@
} else if (Literal.isFloatingLiteral()) {
QualType Ty;
if (Literal.isHalf){
- if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
+ if (getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()))
Ty = Context.HalfTy;
else {
Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
@@ -3843,10 +3873,11 @@
if (Ty->castAs<BuiltinType>()->getKind() != BuiltinType::Float) {
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
- } else if (getLangOpts().OpenCL &&
- !getOpenCLOptions().isEnabled("cl_khr_fp64")) {
+ } else if (getLangOpts().OpenCL && !getOpenCLOptions().isAvailableOption(
+ "cl_khr_fp64", getLangOpts())) {
// Impose single-precision float type when cl_khr_fp64 is not enabled.
- Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
+ Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64)
+ << (getLangOpts().OpenCLVersion >= 300);
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
}
@@ -3865,6 +3896,14 @@
Diag(Tok.getLocation(), diag::ext_c99_longlong);
}
+ // 'z/uz' literals are a C++2b feature.
+ if (Literal.isSizeT)
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus
+ ? getLangOpts().CPlusPlus2b
+ ? diag::warn_cxx20_compat_size_t_suffix
+ : diag::ext_cxx2b_size_t_suffix
+ : diag::err_cxx2b_size_t_suffix);
+
// Get the value in the widest-possible width.
unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth();
llvm::APInt ResultVal(MaxWidth, 0);
@@ -3899,7 +3938,26 @@
}
}
- if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong) {
+ // Check C++2b size_t literals.
+ if (Literal.isSizeT) {
+ assert(!Literal.MicrosoftInteger &&
+ "size_t literals can't be Microsoft literals");
+ unsigned SizeTSize = Context.getTargetInfo().getTypeWidth(
+ Context.getTargetInfo().getSizeType());
+
+ // Does it fit in size_t?
+ if (ResultVal.isIntN(SizeTSize)) {
+ // Does it fit in ssize_t?
+ if (!Literal.isUnsigned && ResultVal[SizeTSize - 1] == 0)
+ Ty = Context.getSignedSizeType();
+ else if (AllowUnsigned)
+ Ty = Context.getSizeType();
+ Width = SizeTSize;
+ }
+ }
+
+ if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong &&
+ !Literal.isSizeT) {
// Are int/unsigned possibilities?
unsigned IntSize = Context.getTargetInfo().getIntWidth();
@@ -3915,7 +3973,7 @@
}
// Are long/unsigned long possibilities?
- if (Ty.isNull() && !Literal.isLongLong) {
+ if (Ty.isNull() && !Literal.isLongLong && !Literal.isSizeT) {
unsigned LongSize = Context.getTargetInfo().getLongWidth();
// Does it fit in a unsigned long?
@@ -3946,7 +4004,7 @@
}
// Check long long if needed.
- if (Ty.isNull()) {
+ if (Ty.isNull() && !Literal.isSizeT) {
unsigned LongLongSize = Context.getTargetInfo().getLongLongWidth();
// Does it fit in a unsigned long long?
@@ -3963,10 +4021,16 @@
}
}
- // If we still couldn't decide a type, we probably have something that
- // does not fit in a signed long long, but has no U suffix.
+ // If we still couldn't decide a type, we either have 'size_t' literal
+ // that is out of range, or a decimal literal that does not fit in a
+ // signed long long and has no U suffix.
if (Ty.isNull()) {
- Diag(Tok.getLocation(), diag::ext_integer_literal_too_large_for_signed);
+ if (Literal.isSizeT)
+ Diag(Tok.getLocation(), diag::err_size_t_literal_too_large)
+ << Literal.isUnsigned;
+ else
+ Diag(Tok.getLocation(),
+ diag::ext_integer_literal_too_large_for_signed);
Ty = Context.UnsignedLongLongTy;
Width = Context.getTargetInfo().getLongLongWidth();
}
@@ -3989,6 +4053,10 @@
ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E) {
assert(E && "ActOnParenExpr() missing expr");
+ QualType ExprTy = E->getType();
+ if (getLangOpts().ProtectParens && CurFPFeatures.getAllowFPReassociate() &&
+ !E->isLValue() && ExprTy->hasFloatingRepresentation())
+ return BuildBuiltinCallExpr(R, Builtin::BI__arithmetic_fence, E);
return new (Context) ParenExpr(L, R, E);
}
@@ -4995,7 +5063,7 @@
llvm::APSInt LengthValue = Result.Val.getInt();
if (LengthValue.isNegative()) {
Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
- << LengthValue.toString(/*Radix=*/10, /*Signed=*/true)
+ << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
<< Length->getSourceRange();
return ExprError();
}
@@ -5019,7 +5087,7 @@
llvm::APSInt StrideValue = Result.Val.getInt();
if (!StrideValue.isStrictlyPositive()) {
Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
- << StrideValue.toString(/*Radix=*/10, /*Signed=*/true)
+ << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
<< Stride->getSourceRange();
return ExprError();
}
@@ -5098,7 +5166,7 @@
llvm::APSInt Value = EvResult.Val.getInt();
if (!Value.isStrictlyPositive()) {
Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
- << Value.toString(/*Radix=*/10, /*Signed=*/true)
+ << toString(Value, /*Radix=*/10, /*Signed=*/true)
<< Dim->getSourceRange();
ErrorFound = true;
continue;
@@ -5478,14 +5546,14 @@
BaseExpr = LHSExp; // vectors: V[123]
IndexExpr = RHSExp;
// We apply C++ DR1213 to vector subscripting too.
- if (getLangOpts().CPlusPlus11 && LHSExp->getValueKind() == VK_RValue) {
+ if (getLangOpts().CPlusPlus11 && LHSExp->isPRValue()) {
ExprResult Materialized = TemporaryMaterializationConversion(LHSExp);
if (Materialized.isInvalid())
return ExprError();
LHSExp = Materialized.get();
}
VK = LHSExp->getValueKind();
- if (VK != VK_RValue)
+ if (VK != VK_PRValue)
OK = OK_VectorComponent;
ResultType = VTy->getElementType();
@@ -5509,7 +5577,7 @@
BaseExpr = LHSExp;
IndexExpr = RHSExp;
- ResultType = LHSTy->getAs<PointerType>()->getPointeeType();
+ ResultType = LHSTy->castAs<PointerType>()->getPointeeType();
} else if (RHSTy->isArrayType()) {
// Same as previous, except for 123[f().a] case
Diag(RHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue)
@@ -5520,7 +5588,7 @@
BaseExpr = RHSExp;
IndexExpr = LHSExp;
- ResultType = RHSTy->getAs<PointerType>()->getPointeeType();
+ ResultType = RHSTy->castAs<PointerType>()->getPointeeType();
} else {
return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value)
<< LHSExp->getSourceRange() << RHSExp->getSourceRange());
@@ -5552,14 +5620,15 @@
// C forbids expressions of unqualified void type from being l-values.
// See IsCForbiddenLValueType.
- if (!ResultType.hasQualifiers()) VK = VK_RValue;
+ if (!ResultType.hasQualifiers())
+ VK = VK_PRValue;
} else if (!ResultType->isDependentType() &&
RequireCompleteSizedType(
LLoc, ResultType,
diag::err_subscript_incomplete_or_sizeless_type, BaseExpr))
return ExprError();
- assert(VK == VK_RValue || LangOpts.CPlusPlus ||
+ assert(VK == VK_PRValue || LangOpts.CPlusPlus ||
!ResultType.isCForbiddenLValueType());
if (LHSExp->IgnoreParenImpCasts()->getType()->isVariablyModifiedType() &&
@@ -5858,6 +5927,7 @@
for (unsigned i = 0; i < TotalNumArgs; ++i)
Call->setArg(i, AllArgs[i]);
+ Call->computeDependence();
return false;
}
@@ -5894,7 +5964,8 @@
(!Param || !Param->hasAttr<CFConsumedAttr>()))
CFAudited = true;
- if (Proto->getExtParameterInfo(i).isNoEscape())
+ if (Proto->getExtParameterInfo(i).isNoEscape() &&
+ ProtoArgType->isBlockPointerType())
if (auto *BE = dyn_cast<BlockExpr>(Arg->IgnoreParenNoopCasts(Context)))
BE->getBlockDecl()->setDoesNotEscape();
@@ -6061,6 +6132,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
#define PLACEHOLDER_TYPE(ID, SINGLETON_ID)
#define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID:
#include "clang/AST/BuiltinTypes.def"
@@ -6363,7 +6436,7 @@
}
return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy,
- VK_RValue, RParenLoc, CurFPFeatureOverrides());
+ VK_PRValue, RParenLoc, CurFPFeatureOverrides());
}
if (Fn->getType() == Context.PseudoObjectTy) {
ExprResult result = CheckPlaceholderExpr(Fn);
@@ -6375,9 +6448,10 @@
// in which case we won't do any semantic analysis now.
if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs)) {
if (ExecConfig) {
- return CUDAKernelCallExpr::Create(
- Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs,
- Context.DependentTy, VK_RValue, RParenLoc, CurFPFeatureOverrides());
+ return CUDAKernelCallExpr::Create(Context, Fn,
+ cast<CallExpr>(ExecConfig), ArgExprs,
+ Context.DependentTy, VK_PRValue,
+ RParenLoc, CurFPFeatureOverrides());
} else {
tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
@@ -6385,7 +6459,7 @@
Fn->getBeginLoc());
return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
- VK_RValue, RParenLoc, CurFPFeatureOverrides());
+ VK_PRValue, RParenLoc, CurFPFeatureOverrides());
}
}
@@ -6414,7 +6488,7 @@
if (!find.HasFormOfMemberPointer) {
if (Expr::hasAnyTypeDependentArguments(ArgExprs))
return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
- VK_RValue, RParenLoc, CurFPFeatureOverrides());
+ VK_PRValue, RParenLoc, CurFPFeatureOverrides());
OverloadExpr *ovl = find.Expression;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))
return BuildOverloadedCallExpr(
@@ -6468,9 +6542,6 @@
FD, /*Complain=*/true, Fn->getBeginLoc()))
return ExprError();
- if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn))
- return ExprError();
-
checkDirectCallValidity(*this, Fn, FD, ArgExprs);
}
@@ -6493,24 +6564,53 @@
ExecConfig, IsExecConfig);
}
-/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments.
+/// BuildBuiltinCallExpr - Create a call to a builtin function specified by Id
+// with the specified CallArgs
+Expr *Sema::BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id,
+ MultiExprArg CallArgs) {
+ StringRef Name = Context.BuiltinInfo.getName(Id);
+ LookupResult R(*this, &Context.Idents.get(Name), Loc,
+ Sema::LookupOrdinaryName);
+ LookupName(R, TUScope, /*AllowBuiltinCreation=*/true);
+
+ auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
+ assert(BuiltInDecl && "failed to find builtin declaration");
+
+ ExprResult DeclRef =
+ BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
+ assert(DeclRef.isUsable() && "Builtin reference cannot fail");
+
+ ExprResult Call =
+ BuildCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
+
+ assert(!Call.isInvalid() && "Call to builtin cannot fail!");
+ return Call.get();
+}
+
+/// Parse a __builtin_astype expression.
///
/// __builtin_astype( value, dst type )
///
ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc) {
- ExprValueKind VK = VK_RValue;
- ExprObjectKind OK = OK_Ordinary;
QualType DstTy = GetTypeFromParser(ParsedDestTy);
+ return BuildAsTypeExpr(E, DstTy, BuiltinLoc, RParenLoc);
+}
+
+/// Create a new AsTypeExpr node (bitcast) from the arguments.
+ExprResult Sema::BuildAsTypeExpr(Expr *E, QualType DestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc) {
+ ExprValueKind VK = VK_PRValue;
+ ExprObjectKind OK = OK_Ordinary;
QualType SrcTy = E->getType();
- if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy))
- return ExprError(Diag(BuiltinLoc,
- diag::err_invalid_astype_of_different_size)
- << DstTy
- << SrcTy
- << E->getSourceRange());
- return new (Context) AsTypeExpr(E, DstTy, VK, OK, BuiltinLoc, RParenLoc);
+ if (!SrcTy->isDependentType() &&
+ Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
+ return ExprError(
+ Diag(BuiltinLoc, diag::err_invalid_astype_of_different_size)
+ << DestTy << SrcTy << E->getSourceRange());
+ return new (Context) AsTypeExpr(E, DestTy, VK, OK, BuiltinLoc, RParenLoc);
}
/// ActOnConvertVectorExpr - create a new convert-vector expression from the
@@ -6550,12 +6650,25 @@
// so there's some risk when calling out to non-interrupt handler functions
// that the callee might not preserve them. This is easy to diagnose here,
// but can be very challenging to debug.
- if (auto *Caller = getCurFunctionDecl())
+ // Likewise, X86 interrupt handlers may only call routines with attribute
+ // no_caller_saved_registers since there is no efficient way to
+ // save and restore the non-GPR state.
+ if (auto *Caller = getCurFunctionDecl()) {
if (Caller->hasAttr<ARMInterruptAttr>()) {
bool VFP = Context.getTargetInfo().hasFeature("vfp");
- if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>()))
+ if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>())) {
Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention);
+ if (FDecl)
+ Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl;
+ }
}
+ if (Caller->hasAttr<AnyX86InterruptAttr>() &&
+ ((!FDecl || !FDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>()))) {
+ Diag(Fn->getExprLoc(), diag::warn_anyx86_interrupt_regsave);
+ if (FDecl)
+ Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl;
+ }
+ }
// Promote the function operand.
// We special-case function promotion here because we only allow promoting
@@ -6621,11 +6734,11 @@
assert(UsesADL == ADLCallKind::NotADL &&
"CUDAKernelCallExpr should not use ADL");
TheCall = CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config),
- Args, ResultTy, VK_RValue, RParenLoc,
+ Args, ResultTy, VK_PRValue, RParenLoc,
CurFPFeatureOverrides(), NumParams);
} else {
TheCall =
- CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc,
+ CallExpr::Create(Context, Fn, Args, ResultTy, VK_PRValue, RParenLoc,
CurFPFeatureOverrides(), NumParams, UsesADL);
}
@@ -6652,11 +6765,11 @@
if (CorrectedTypos && Args.size() < NumParams) {
if (Config)
TheCall = CUDAKernelCallExpr::Create(
- Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_RValue,
+ Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_PRValue,
RParenLoc, CurFPFeatureOverrides(), NumParams);
else
TheCall =
- CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc,
+ CallExpr::Create(Context, Fn, Args, ResultTy, VK_PRValue, RParenLoc,
CurFPFeatureOverrides(), NumParams, UsesADL);
}
// We can now handle the nulled arguments for the default arguments.
@@ -6750,6 +6863,7 @@
TheCall->setArg(i, Arg);
}
+ TheCall->computeDependence();
}
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
@@ -6818,9 +6932,12 @@
diag::err_array_incomplete_or_sizeless_type,
SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())))
return ExprError();
- if (literalType->isVariableArrayType())
- return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init)
- << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd()));
+ if (literalType->isVariableArrayType()) {
+ if (!tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc,
+ diag::err_variable_object_no_init)) {
+ return ExprError();
+ }
+ }
} else if (!literalType->isDependentType() &&
RequireCompleteType(LParenLoc, literalType,
diag::err_typecheck_decl_incomplete_type,
@@ -6862,7 +6979,7 @@
// obviously have a value kind derived from the kind of reference involved.
ExprValueKind VK =
(getLangOpts().CPlusPlus && !(isFileScope && literalType->isArrayType()))
- ? VK_RValue
+ ? VK_PRValue
: VK_LValue;
if (isFileScope)
@@ -7013,14 +7130,14 @@
/// Do an explicit extend of the given block pointer if we're in ARC.
void Sema::maybeExtendBlockObject(ExprResult &E) {
assert(E.get()->getType()->isBlockPointerType());
- assert(E.get()->isRValue());
+ assert(E.get()->isPRValue());
// Only do this in an r-value context.
if (!getLangOpts().ObjCAutoRefCount) return;
E = ImplicitCastExpr::Create(
Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(),
- /*base path*/ nullptr, VK_RValue, FPOptionsOverride());
+ /*base path*/ nullptr, VK_PRValue, FPOptionsOverride());
Cleanup.setExprNeedsCleanups(true);
}
@@ -7289,6 +7406,38 @@
ValidScalableConversion(destTy, srcTy);
}
+/// Are the two types matrix types and do they have the same dimensions i.e.
+/// do they have the same number of rows and the same number of columns?
+bool Sema::areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy) {
+ if (!destTy->isMatrixType() || !srcTy->isMatrixType())
+ return false;
+
+ const ConstantMatrixType *matSrcType = srcTy->getAs<ConstantMatrixType>();
+ const ConstantMatrixType *matDestType = destTy->getAs<ConstantMatrixType>();
+
+ return matSrcType->getNumRows() == matDestType->getNumRows() &&
+ matSrcType->getNumColumns() == matDestType->getNumColumns();
+}
+
+bool Sema::areVectorTypesSameSize(QualType SrcTy, QualType DestTy) {
+ assert(DestTy->isVectorType() || SrcTy->isVectorType());
+
+ uint64_t SrcLen, DestLen;
+ QualType SrcEltTy, DestEltTy;
+ if (!breakDownVectorType(SrcTy, SrcLen, SrcEltTy))
+ return false;
+ if (!breakDownVectorType(DestTy, DestLen, DestEltTy))
+ return false;
+
+ // ASTContext::getTypeSize will return the size rounded up to a
+ // power of 2, so instead of using that, we need to use the raw
+ // element size multiplied by the element count.
+ uint64_t SrcEltSize = Context.getTypeSize(SrcEltTy);
+ uint64_t DestEltSize = Context.getTypeSize(DestEltTy);
+
+ return (SrcLen * SrcEltSize == DestLen * DestEltSize);
+}
+
/// Are the two types lax-compatible vector types? That is, given
/// that one of them is a vector, do they have equal storage sizes,
/// where the storage size is the number of elements times the element
@@ -7307,18 +7456,7 @@
if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
- uint64_t srcLen, destLen;
- QualType srcEltTy, destEltTy;
- if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
- if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
- // ASTContext::getTypeSize will return the size rounded up to a
- // power of 2, so instead of using that, we need to use the raw
- // element size multiplied by the element count.
- uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
- uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
- return (srcLen * srcEltSize == destLen * destEltSize);
+ return areVectorTypesSameSize(srcTy, destTy);
}
/// Is this a legal conversion between two types, one of which is
@@ -7351,6 +7489,27 @@
return areLaxCompatibleVectorTypes(srcTy, destTy);
}
+bool Sema::CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy,
+ CastKind &Kind) {
+ if (SrcTy->isMatrixType() && DestTy->isMatrixType()) {
+ if (!areMatrixTypesOfTheSameDimension(SrcTy, DestTy)) {
+ return Diag(R.getBegin(), diag::err_invalid_conversion_between_matrixes)
+ << DestTy << SrcTy << R;
+ }
+ } else if (SrcTy->isMatrixType()) {
+ return Diag(R.getBegin(),
+ diag::err_invalid_conversion_between_matrix_and_type)
+ << SrcTy << DestTy << R;
+ } else if (DestTy->isMatrixType()) {
+ return Diag(R.getBegin(),
+ diag::err_invalid_conversion_between_matrix_and_type)
+ << DestTy << SrcTy << R;
+ }
+
+ Kind = CK_MatrixCast;
+ return false;
+}
+
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
@@ -7547,7 +7706,7 @@
// initializers must be one or must match the size of the vector.
// If a single value is specified in the initializer then it will be
// replicated to all the components of the vector
- if (VTy->getVectorKind() == VectorType::AltiVecVector) {
+ if (ShouldSplatAltivecScalarInCast(VTy)) {
// The number of initializers must be one or must match the size of the
// vector. If a single value is specified in the initializer then it will
// be replicated to all the components of the vector
@@ -8134,7 +8293,7 @@
if (getLangOpts().CPlusPlus)
return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc);
- VK = VK_RValue;
+ VK = VK_PRValue;
OK = OK_Ordinary;
if (Context.isDependenceAllowed() &&
@@ -8266,7 +8425,7 @@
// Allow ?: operations in which both operands have the same
// built-in sizeless type.
- if (LHSTy->isSizelessBuiltinType() && LHSTy == RHSTy)
+ if (LHSTy->isSizelessBuiltinType() && Context.hasSameType(LHSTy, RHSTy))
return LHSTy;
// Emit a better diagnostic if one of the expressions is a null pointer
@@ -8672,8 +8831,8 @@
// If the common expression is a class or array prvalue, materialize it
// so that we can safely refer to it multiple times.
- if (commonExpr->isRValue() && (commonExpr->getType()->isRecordType() ||
- commonExpr->getType()->isArrayType())) {
+ if (commonExpr->isPRValue() && (commonExpr->getType()->isRecordType() ||
+ commonExpr->getType()->isArrayType())) {
ExprResult MatExpr = TemporaryMaterializationConversion(commonExpr);
if (MatExpr.isInvalid())
return ExprError();
@@ -8689,7 +8848,7 @@
}
QualType LHSTy = LHSExpr->getType(), RHSTy = RHSExpr->getType();
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
ExprObjectKind OK = OK_Ordinary;
ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr;
QualType result = CheckConditionalOperands(Cond, LHS, RHS,
@@ -8973,7 +9132,7 @@
// cast operations are required, so if CheckAssignmentConstraints
// adds casts to this they'll be wasted, but fortunately that doesn't
// usually happen on valid code.
- OpaqueValueExpr RHSExpr(Loc, RHSType, VK_RValue);
+ OpaqueValueExpr RHSExpr(Loc, RHSType, VK_PRValue);
ExprResult RHSPtr = &RHSExpr;
CastKind K;
@@ -9342,7 +9501,7 @@
// union type from this initializer list.
TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
EResult = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
- VK_RValue, Initializer, false);
+ VK_PRValue, Initializer, false);
}
Sema::AssignConvertType
@@ -9481,7 +9640,7 @@
CheckPointerConversion(RHS.get(), LHSType, Kind, Path,
/*IgnoreBaseAccess=*/false, Diagnose);
if (ConvertRHS)
- RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path);
+ RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_PRValue, &Path);
}
return Compatible;
}
@@ -10000,7 +10159,7 @@
RHSType, DiagID))
return RHSType;
} else {
- if (LHS.get()->getValueKind() == VK_LValue ||
+ if (LHS.get()->isLValue() ||
!tryGCCVectorConvertAndSplat(*this, &LHS, &RHS))
return RHSType;
}
@@ -10184,14 +10343,19 @@
bool IsCompAssign, bool IsDiv) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false);
- if (LHS.get()->getType()->isVectorType() ||
- RHS.get()->getType()->isVectorType())
+ QualType LHSTy = LHS.get()->getType();
+ QualType RHSTy = RHS.get()->getType();
+ if (LHSTy->isVectorType() || RHSTy->isVectorType())
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
/*AllowBothBool*/getLangOpts().AltiVec,
/*AllowBoolConversions*/false);
- if (!IsDiv && (LHS.get()->getType()->isConstantMatrixType() ||
- RHS.get()->getType()->isConstantMatrixType()))
+ if (!IsDiv &&
+ (LHSTy->isConstantMatrixType() || RHSTy->isConstantMatrixType()))
return CheckMatrixMultiplyOperands(LHS, RHS, Loc, IsCompAssign);
+ // For division, only matrix-by-scalar is supported. Other combinations with
+ // matrix types are invalid.
+ if (IsDiv && LHSTy->isConstantMatrixType() && RHSTy->isArithmeticType())
+ return CheckMatrixElementwiseOperands(LHS, RHS, Loc, IsCompAssign);
QualType compType = UsualArithmeticConversions(
LHS, RHS, Loc, IsCompAssign ? ACK_CompAssign : ACK_Arithmetic);
@@ -10267,6 +10431,22 @@
<< S.getLangOpts().CPlusPlus << Pointer->getSourceRange();
}
+/// Diagnose invalid subraction on a null pointer.
+///
+static void diagnoseSubtractionOnNullPointer(Sema &S, SourceLocation Loc,
+ Expr *Pointer, bool BothNull) {
+ // Null - null is valid in C++ [expr.add]p7
+ if (BothNull && S.getLangOpts().CPlusPlus)
+ return;
+
+ // Is this s a macro from a system header?
+ if (S.Diags.getSuppressSystemWarnings() && S.SourceMgr.isInSystemMacro(Loc))
+ return;
+
+ S.Diag(Loc, diag::warn_pointer_sub_null_ptr)
+ << S.getLangOpts().CPlusPlus << Pointer->getSourceRange();
+}
+
/// Diagnose invalid arithmetic on two function pointers.
static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
Expr *LHS, Expr *RHS) {
@@ -10513,7 +10693,11 @@
if (LHS.get()->getType()->isConstantMatrixType() ||
RHS.get()->getType()->isConstantMatrixType()) {
- return CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy);
+ QualType compType =
+ CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy);
+ if (CompLHSTy)
+ *CompLHSTy = compType;
+ return compType;
}
QualType compType = UsualArithmeticConversions(
@@ -10613,7 +10797,11 @@
if (LHS.get()->getType()->isConstantMatrixType() ||
RHS.get()->getType()->isConstantMatrixType()) {
- return CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy);
+ QualType compType =
+ CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy);
+ if (CompLHSTy)
+ *CompLHSTy = compType;
+ return compType;
}
QualType compType = UsualArithmeticConversions(
@@ -10690,7 +10878,16 @@
LHS.get(), RHS.get()))
return QualType();
- // FIXME: Add warnings for nullptr - ptr.
+ bool LHSIsNullPtr = LHS.get()->IgnoreParenCasts()->isNullPointerConstant(
+ Context, Expr::NPC_ValueDependentIsNotNull);
+ bool RHSIsNullPtr = RHS.get()->IgnoreParenCasts()->isNullPointerConstant(
+ Context, Expr::NPC_ValueDependentIsNotNull);
+
+ // Subtracting nullptr or from nullptr is suspect
+ if (LHSIsNullPtr)
+ diagnoseSubtractionOnNullPointer(*this, Loc, LHS.get(), RHSIsNullPtr);
+ if (RHSIsNullPtr)
+ diagnoseSubtractionOnNullPointer(*this, Loc, RHS.get(), LHSIsNullPtr);
// The pointee type may have zero size. As an extension, a structure or
// union may have zero size or an array may have zero length. In this
@@ -11658,6 +11855,21 @@
LHS.get()->getSourceRange());
}
+ if (IsOrdered && LHSType->isFunctionPointerType() &&
+ RHSType->isFunctionPointerType()) {
+ // Valid unless a relational comparison of function pointers
+ bool IsError = Opc == BO_Cmp;
+ auto DiagID =
+ IsError ? diag::err_typecheck_ordered_comparison_of_function_pointers
+ : getLangOpts().CPlusPlus
+ ? diag::warn_typecheck_ordered_comparison_of_function_pointers
+ : diag::ext_typecheck_ordered_comparison_of_function_pointers;
+ Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
+ if (IsError)
+ return QualType();
+ }
+
if ((LHSType->isIntegerType() && !LHSIsNull) ||
(RHSType->isIntegerType() && !RHSIsNull)) {
// Skip normal pointer conversion checks in this case; we have better
@@ -11725,12 +11937,6 @@
<< LHSType << RHSType << LCanPointeeTy->isIncompleteType()
<< RCanPointeeTy->isIncompleteType();
}
- if (LCanPointeeTy->isFunctionType()) {
- // Valid unless a relational comparison of function pointers
- Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers)
- << LHSType << RHSType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
- }
}
} else if (!IsRelational &&
(LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
@@ -12071,11 +12277,30 @@
QualType LHSType = LHS.get()->getType();
- // If AltiVec, the comparison results in a numeric type, i.e.
- // bool for C++, int for C
- if (getLangOpts().AltiVec &&
- vType->castAs<VectorType>()->getVectorKind() == VectorType::AltiVecVector)
- return Context.getLogicalOperationType();
+ // Determine the return type of a vector compare. By default clang will return
+ // a scalar for all vector compares except vector bool and vector pixel.
+ // With the gcc compiler we will always return a vector type and with the xl
+ // compiler we will always return a scalar type. This switch allows choosing
+ // which behavior is prefered.
+ if (getLangOpts().AltiVec) {
+ switch (getLangOpts().getAltivecSrcCompat()) {
+ case LangOptions::AltivecSrcCompatKind::Mixed:
+ // If AltiVec, the comparison results in a numeric type, i.e.
+ // bool for C++, int for C
+ if (vType->castAs<VectorType>()->getVectorKind() ==
+ VectorType::AltiVecVector)
+ return Context.getLogicalOperationType();
+ else
+ Diag(Loc, diag::warn_deprecated_altivec_src_compat);
+ break;
+ case LangOptions::AltivecSrcCompatKind::GCC:
+ // For GCC we always return the vector type.
+ break;
+ case LangOptions::AltivecSrcCompatKind::XL:
+ return Context.getLogicalOperationType();
+ break;
+ }
+ }
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
@@ -12100,6 +12325,11 @@
if (Loc.isMacroID())
return;
+ // Do not diagnose if both LHS and RHS are macros.
+ if (XorLHS.get()->getExprLoc().isMacroID() &&
+ XorRHS.get()->getExprLoc().isMacroID())
+ return;
+
bool Negative = false;
bool ExplicitPlus = false;
const auto *LHSInt = dyn_cast<IntegerLiteral>(XorLHS.get());
@@ -12172,7 +12402,8 @@
RHSStrRef.find('\'') != StringRef::npos)
return;
- bool SuggestXor = S.getLangOpts().CPlusPlus || S.getPreprocessor().isMacroDefined("xor");
+ bool SuggestXor =
+ S.getLangOpts().CPlusPlus || S.getPreprocessor().isMacroDefined("xor");
const llvm::APInt XorValue = LeftSideValue ^ RightSideValue;
int64_t RightSideIntValue = RightSideValue.getSExtValue();
if (LeftSideValue == 2 && RightSideIntValue >= 0) {
@@ -12183,27 +12414,30 @@
if (Overflow) {
if (RightSideIntValue < 64)
S.Diag(Loc, diag::warn_xor_used_as_pow_base)
- << ExprStr << XorValue.toString(10, true) << ("1LL << " + RHSStr)
+ << ExprStr << toString(XorValue, 10, true) << ("1LL << " + RHSStr)
<< FixItHint::CreateReplacement(ExprRange, "1LL << " + RHSStr);
else if (RightSideIntValue == 64)
- S.Diag(Loc, diag::warn_xor_used_as_pow) << ExprStr << XorValue.toString(10, true);
+ S.Diag(Loc, diag::warn_xor_used_as_pow)
+ << ExprStr << toString(XorValue, 10, true);
else
return;
} else {
S.Diag(Loc, diag::warn_xor_used_as_pow_base_extra)
- << ExprStr << XorValue.toString(10, true) << SuggestedExpr
- << PowValue.toString(10, true)
+ << ExprStr << toString(XorValue, 10, true) << SuggestedExpr
+ << toString(PowValue, 10, true)
<< FixItHint::CreateReplacement(
ExprRange, (RightSideIntValue == 0) ? "1" : SuggestedExpr);
}
- S.Diag(Loc, diag::note_xor_used_as_pow_silence) << ("0x2 ^ " + RHSStr) << SuggestXor;
+ S.Diag(Loc, diag::note_xor_used_as_pow_silence)
+ << ("0x2 ^ " + RHSStr) << SuggestXor;
} else if (LeftSideValue == 10) {
std::string SuggestedValue = "1e" + std::to_string(RightSideIntValue);
S.Diag(Loc, diag::warn_xor_used_as_pow_base)
- << ExprStr << XorValue.toString(10, true) << SuggestedValue
+ << ExprStr << toString(XorValue, 10, true) << SuggestedValue
<< FixItHint::CreateReplacement(ExprRange, SuggestedValue);
- S.Diag(Loc, diag::note_xor_used_as_pow_silence) << ("0xA ^ " + RHSStr) << SuggestXor;
+ S.Diag(Loc, diag::note_xor_used_as_pow_silence)
+ << ("0xA ^ " + RHSStr) << SuggestXor;
}
}
@@ -12900,8 +13134,9 @@
// OpenCL v1.2 s6.1.1.1 p2:
// The half data type can only be used to declare a pointer to a buffer that
// contains half values
- if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
- LHSType->isHalfType()) {
+ if (getLangOpts().OpenCL &&
+ !getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()) &&
+ LHSType->isHalfType()) {
Diag(Loc, diag::err_opencl_half_load_store) << 1
<< LHSType.getUnqualifiedType();
return QualType();
@@ -13208,7 +13443,7 @@
OK = Op->getObjectKind();
return ResType;
} else {
- VK = VK_RValue;
+ VK = VK_PRValue;
return ResType.getUnqualifiedType();
}
}
@@ -13595,7 +13830,7 @@
// ...except that certain expressions are never l-values in C.
if (!S.getLangOpts().CPlusPlus && Result.isCForbiddenLValueType())
- VK = VK_RValue;
+ VK = VK_PRValue;
return Result;
}
@@ -13864,7 +14099,7 @@
// The following two variables are used for compound assignment operators
QualType CompLHSTy; // Type of LHS after promotions for computation
QualType CompResultTy; // Type of computation result
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
ExprObjectKind OK = OK_Ordinary;
bool ConvertHalfVec = false;
@@ -14483,7 +14718,7 @@
// assignment, but is not an lvalue.
return CompoundAssignOperator::Create(
Context, LHSExpr, RHSExpr, Opc,
- LHSExpr->getType().getUnqualifiedType(), VK_RValue, OK_Ordinary,
+ LHSExpr->getType().getUnqualifiedType(), VK_PRValue, OK_Ordinary,
OpLoc, CurFPFeatureOverrides());
QualType ResultType;
switch (Opc) {
@@ -14509,7 +14744,7 @@
break;
}
return BinaryOperator::Create(Context, LHSExpr, RHSExpr, Opc, ResultType,
- VK_RValue, OK_Ordinary, OpLoc,
+ VK_PRValue, OK_Ordinary, OpLoc,
CurFPFeatureOverrides());
}
@@ -14531,7 +14766,7 @@
UnaryOperatorKind Opc,
Expr *InputExpr) {
ExprResult Input = InputExpr;
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
bool CanOverflow = false;
@@ -14704,7 +14939,7 @@
// complex l-values to ordinary l-values and all other values to r-values.
if (Input.isInvalid()) return ExprError();
if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) {
- if (Input.get()->getValueKind() != VK_RValue &&
+ if (Input.get()->isGLValue() &&
Input.get()->getObjectKind() == OK_Ordinary)
VK = Input.get()->getValueKind();
} else if (!getLangOpts().CPlusPlus) {
@@ -15123,7 +15358,7 @@
SourceLocation RPLoc) {
assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
ExprObjectKind OK = OK_Ordinary;
QualType resType;
bool CondIsTrue = false;
@@ -15604,8 +15839,46 @@
QualType PromoteType;
if (TInfo->getType()->isPromotableIntegerType()) {
PromoteType = Context.getPromotedIntegerType(TInfo->getType());
- if (Context.typesAreCompatible(PromoteType, TInfo->getType()))
+ // [cstdarg.syn]p1 defers the C++ behavior to what the C standard says,
+ // and C2x 7.16.1.1p2 says, in part:
+ // If type is not compatible with the type of the actual next argument
+ // (as promoted according to the default argument promotions), the
+ // behavior is undefined, except for the following cases:
+ // - both types are pointers to qualified or unqualified versions of
+ // compatible types;
+ // - one type is a signed integer type, the other type is the
+ // corresponding unsigned integer type, and the value is
+ // representable in both types;
+ // - one type is pointer to qualified or unqualified void and the
+ // other is a pointer to a qualified or unqualified character type.
+ // Given that type compatibility is the primary requirement (ignoring
+ // qualifications), you would think we could call typesAreCompatible()
+ // directly to test this. However, in C++, that checks for *same type*,
+ // which causes false positives when passing an enumeration type to
+ // va_arg. Instead, get the underlying type of the enumeration and pass
+ // that.
+ QualType UnderlyingType = TInfo->getType();
+ if (const auto *ET = UnderlyingType->getAs<EnumType>())
+ UnderlyingType = ET->getDecl()->getIntegerType();
+ if (Context.typesAreCompatible(PromoteType, UnderlyingType,
+ /*CompareUnqualified*/ true))
PromoteType = QualType();
+
+ // If the types are still not compatible, we need to test whether the
+ // promoted type and the underlying type are the same except for
+ // signedness. Ask the AST for the correctly corresponding type and see
+ // if that's compatible.
+ if (!PromoteType.isNull() &&
+ PromoteType->isUnsignedIntegerType() !=
+ UnderlyingType->isUnsignedIntegerType()) {
+ UnderlyingType =
+ UnderlyingType->isUnsignedIntegerType()
+ ? Context.getCorrespondingSignedType(UnderlyingType)
+ : Context.getCorrespondingUnsignedType(UnderlyingType);
+ if (Context.typesAreCompatible(PromoteType, UnderlyingType,
+ /*CompareUnqualified*/ true))
+ PromoteType = QualType();
+ }
}
if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float))
PromoteType = Context.DoubleTy;
@@ -16138,7 +16411,8 @@
if (Result)
*Result = E->EvaluateKnownConstIntCheckOverflow(Context);
if (!isa<ConstantExpr>(E))
- E = ConstantExpr::Create(Context, E);
+ E = Result ? ConstantExpr::Create(Context, E, APValue(*Result))
+ : ConstantExpr::Create(Context, E);
return E;
}
@@ -16520,8 +16794,10 @@
if (!Rec.Lambdas.empty()) {
using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
- if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || Rec.isUnevaluated() ||
- (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) {
+ if (!getLangOpts().CPlusPlus20 &&
+ (Rec.ExprContext == ExpressionKind::EK_TemplateArgument ||
+ Rec.isUnevaluated() ||
+ (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17))) {
unsigned D;
if (Rec.isUnevaluated()) {
// C++11 [expr.prim.lambda]p2:
@@ -17030,6 +17306,42 @@
CaptureType, DeclRefType,
FunctionScopeIndexToStopAt);
+ if (SemaRef.LangOpts.CUDA && Var && Var->hasGlobalStorage()) {
+ auto *FD = dyn_cast_or_null<FunctionDecl>(SemaRef.CurContext);
+ auto VarTarget = SemaRef.IdentifyCUDATarget(Var);
+ auto UserTarget = SemaRef.IdentifyCUDATarget(FD);
+ if (VarTarget == Sema::CVT_Host &&
+ (UserTarget == Sema::CFT_Device || UserTarget == Sema::CFT_HostDevice ||
+ UserTarget == Sema::CFT_Global)) {
+ // Diagnose ODR-use of host global variables in device functions.
+ // Reference of device global variables in host functions is allowed
+ // through shadow variables therefore it is not diagnosed.
+ if (SemaRef.LangOpts.CUDAIsDevice) {
+ SemaRef.targetDiag(Loc, diag::err_ref_bad_target)
+ << /*host*/ 2 << /*variable*/ 1 << Var << UserTarget;
+ SemaRef.targetDiag(Var->getLocation(),
+ Var->getType().isConstQualified()
+ ? diag::note_cuda_const_var_unpromoted
+ : diag::note_cuda_host_var);
+ }
+ } else if (VarTarget == Sema::CVT_Device &&
+ (UserTarget == Sema::CFT_Host ||
+ UserTarget == Sema::CFT_HostDevice) &&
+ !Var->hasExternalStorage()) {
+ // Record a CUDA/HIP device side variable if it is ODR-used
+ // by host code. This is done conservatively, when the variable is
+ // referenced in any of the following contexts:
+ // - a non-function context
+ // - a host function
+ // - a host device function
+ // This makes the ODR-use of the device side variable by host code to
+ // be visible in the device compilation for the compiler to be able to
+ // emit template variables instantiated by host code only and to
+ // externalize the static device side variable ODR-used by host code.
+ SemaRef.getASTContext().CUDADeviceVarODRUsedByHost.insert(Var);
+ }
+ }
+
Var->markUsed(SemaRef.Context);
}
@@ -17263,18 +17575,17 @@
/// Capture the given variable in the captured region.
-static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
- VarDecl *Var,
- SourceLocation Loc,
- const bool BuildAndDiagnose,
- QualType &CaptureType,
- QualType &DeclRefType,
- const bool RefersToCapturedVariable,
- Sema &S, bool Invalid) {
+static bool captureInCapturedRegion(
+ CapturedRegionScopeInfo *RSI, VarDecl *Var, SourceLocation Loc,
+ const bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType,
+ const bool RefersToCapturedVariable, Sema::TryCaptureKind Kind,
+ bool IsTopScope, Sema &S, bool Invalid) {
// By default, capture variables by reference.
bool ByRef = true;
- // Using an LValue reference type is consistent with Lambdas (see below).
- if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) {
+ if (IsTopScope && Kind != Sema::TryCapture_Implicit) {
+ ByRef = (Kind == Sema::TryCapture_ExplicitByRef);
+ } else if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) {
+ // Using an LValue reference type is consistent with Lambdas (see below).
if (S.isOpenMPCapturedDecl(Var)) {
bool HasConst = DeclRefType.isConstQualified();
DeclRefType = DeclRefType.getUnqualifiedType();
@@ -17403,6 +17714,107 @@
return !Invalid;
}
+static bool canCaptureVariableByCopy(VarDecl *Var, const ASTContext &Context) {
+ // Offer a Copy fix even if the type is dependent.
+ if (Var->getType()->isDependentType())
+ return true;
+ QualType T = Var->getType().getNonReferenceType();
+ if (T.isTriviallyCopyableType(Context))
+ return true;
+ if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
+
+ if (!(RD = RD->getDefinition()))
+ return false;
+ if (RD->hasSimpleCopyConstructor())
+ return true;
+ if (RD->hasUserDeclaredCopyConstructor())
+ for (CXXConstructorDecl *Ctor : RD->ctors())
+ if (Ctor->isCopyConstructor())
+ return !Ctor->isDeleted();
+ }
+ return false;
+}
+
+/// Create up to 4 fix-its for explicit reference and value capture of \p Var or
+/// default capture. Fixes may be omitted if they aren't allowed by the
+/// standard, for example we can't emit a default copy capture fix-it if we
+/// already explicitly copy capture capture another variable.
+static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI,
+ VarDecl *Var) {
+ assert(LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None);
+ // Don't offer Capture by copy of default capture by copy fixes if Var is
+ // known not to be copy constructible.
+ bool ShouldOfferCopyFix = canCaptureVariableByCopy(Var, Sema.getASTContext());
+
+ SmallString<32> FixBuffer;
+ StringRef Separator = LSI->NumExplicitCaptures > 0 ? ", " : "";
+ if (Var->getDeclName().isIdentifier() && !Var->getName().empty()) {
+ SourceLocation VarInsertLoc = LSI->IntroducerRange.getEnd();
+ if (ShouldOfferCopyFix) {
+ // Offer fixes to insert an explicit capture for the variable.
+ // [] -> [VarName]
+ // [OtherCapture] -> [OtherCapture, VarName]
+ FixBuffer.assign({Separator, Var->getName()});
+ Sema.Diag(VarInsertLoc, diag::note_lambda_variable_capture_fixit)
+ << Var << /*value*/ 0
+ << FixItHint::CreateInsertion(VarInsertLoc, FixBuffer);
+ }
+ // As above but capture by reference.
+ FixBuffer.assign({Separator, "&", Var->getName()});
+ Sema.Diag(VarInsertLoc, diag::note_lambda_variable_capture_fixit)
+ << Var << /*reference*/ 1
+ << FixItHint::CreateInsertion(VarInsertLoc, FixBuffer);
+ }
+
+ // Only try to offer default capture if there are no captures excluding this
+ // and init captures.
+ // [this]: OK.
+ // [X = Y]: OK.
+ // [&A, &B]: Don't offer.
+ // [A, B]: Don't offer.
+ if (llvm::any_of(LSI->Captures, [](Capture &C) {
+ return !C.isThisCapture() && !C.isInitCapture();
+ }))
+ return;
+
+ // The default capture specifiers, '=' or '&', must appear first in the
+ // capture body.
+ SourceLocation DefaultInsertLoc =
+ LSI->IntroducerRange.getBegin().getLocWithOffset(1);
+
+ if (ShouldOfferCopyFix) {
+ bool CanDefaultCopyCapture = true;
+ // [=, *this] OK since c++17
+ // [=, this] OK since c++20
+ if (LSI->isCXXThisCaptured() && !Sema.getLangOpts().CPlusPlus20)
+ CanDefaultCopyCapture = Sema.getLangOpts().CPlusPlus17
+ ? LSI->getCXXThisCapture().isCopyCapture()
+ : false;
+ // We can't use default capture by copy if any captures already specified
+ // capture by copy.
+ if (CanDefaultCopyCapture && llvm::none_of(LSI->Captures, [](Capture &C) {
+ return !C.isThisCapture() && !C.isInitCapture() && C.isCopyCapture();
+ })) {
+ FixBuffer.assign({"=", Separator});
+ Sema.Diag(DefaultInsertLoc, diag::note_lambda_default_capture_fixit)
+ << /*value*/ 0
+ << FixItHint::CreateInsertion(DefaultInsertLoc, FixBuffer);
+ }
+ }
+
+ // We can't use default capture by reference if any captures already specified
+ // capture by reference.
+ if (llvm::none_of(LSI->Captures, [](Capture &C) {
+ return !C.isInitCapture() && C.isReferenceCapture() &&
+ !C.isThisCapture();
+ })) {
+ FixBuffer.assign({"&", Separator});
+ Sema.Diag(DefaultInsertLoc, diag::note_lambda_default_capture_fixit)
+ << /*reference*/ 1
+ << FixItHint::CreateInsertion(DefaultInsertLoc, FixBuffer);
+ }
+}
+
bool Sema::tryCaptureVariable(
VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
@@ -17492,6 +17904,7 @@
Diag(ExprLoc, diag::err_lambda_impcap) << Var;
Diag(Var->getLocation(), diag::note_previous_decl) << Var;
Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl);
+ buildLambdaCaptureFixit(*this, LSI, Var);
} else
diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC);
}
@@ -17570,9 +17983,11 @@
if (BuildAndDiagnose) {
Diag(ExprLoc, diag::err_lambda_impcap) << Var;
Diag(Var->getLocation(), diag::note_previous_decl) << Var;
- if (cast<LambdaScopeInfo>(CSI)->Lambda)
- Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getBeginLoc(),
- diag::note_lambda_decl);
+ auto *LSI = cast<LambdaScopeInfo>(CSI);
+ if (LSI->Lambda) {
+ Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl);
+ buildLambdaCaptureFixit(*this, LSI, Var);
+ }
// FIXME: If we error out because an outer lambda can not implicitly
// capture a variable that an inner lambda explicitly captures, we
// should have the inner lambda do the explicit capture - because
@@ -17620,9 +18035,9 @@
DeclRefType, Nested, *this, Invalid);
Nested = true;
} else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
- Invalid = !captureInCapturedRegion(RSI, Var, ExprLoc, BuildAndDiagnose,
- CaptureType, DeclRefType, Nested,
- *this, Invalid);
+ Invalid = !captureInCapturedRegion(
+ RSI, Var, ExprLoc, BuildAndDiagnose, CaptureType, DeclRefType, Nested,
+ Kind, /*IsTopScope*/ I == N - 1, *this, Invalid);
Nested = true;
} else {
LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
@@ -18079,8 +18494,9 @@
"MarkVarDeclODRUsed failed to cleanup MaybeODRUseExprs?");
}
-static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
- VarDecl *Var, Expr *E) {
+static void DoMarkVarDeclReferenced(
+ Sema &SemaRef, SourceLocation Loc, VarDecl *Var, Expr *E,
+ llvm::DenseMap<const VarDecl *, int> &RefsMinusAssignments) {
assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E) ||
isa<FunctionParmPackExpr>(E)) &&
"Invalid Expr argument to DoMarkVarDeclReferenced");
@@ -18089,24 +18505,6 @@
if (Var->isInvalidDecl())
return;
- // Record a CUDA/HIP static device/constant variable if it is referenced
- // by host code. This is done conservatively, when the variable is referenced
- // in any of the following contexts:
- // - a non-function context
- // - a host function
- // - a host device function
- // This also requires the reference of the static device/constant variable by
- // host code to be visible in the device compilation for the compiler to be
- // able to externalize the static device/constant variable.
- if (SemaRef.getASTContext().mayExternalizeStaticVar(Var)) {
- auto *CurContext = SemaRef.CurContext;
- if (!CurContext || !isa<FunctionDecl>(CurContext) ||
- cast<FunctionDecl>(CurContext)->hasAttr<CUDAHostAttr>() ||
- (!cast<FunctionDecl>(CurContext)->hasAttr<CUDADeviceAttr>() &&
- !cast<FunctionDecl>(CurContext)->hasAttr<CUDAGlobalAttr>()))
- SemaRef.getASTContext().CUDAStaticDeviceVarReferencedByHost.insert(Var);
- }
-
auto *MSI = Var->getMemberSpecializationInfo();
TemplateSpecializationKind TSK = MSI ? MSI->getTemplateSpecializationKind()
: Var->getTemplateSpecializationKind();
@@ -18115,6 +18513,10 @@
bool UsableInConstantExpr =
Var->mightBeUsableInConstantExpressions(SemaRef.Context);
+ if (Var->isLocalVarDeclOrParm() && !Var->hasExternalStorage()) {
+ RefsMinusAssignments.insert({Var, 0}).first->getSecond()++;
+ }
+
// C++20 [expr.const]p12:
// A variable [...] is needed for constant evaluation if it is [...] a
// variable whose name appears as a potentially constant evaluated
@@ -18270,16 +18672,18 @@
/// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be
/// used directly for normal expressions referring to VarDecl.
void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
- DoMarkVarDeclReferenced(*this, Loc, Var, nullptr);
+ DoMarkVarDeclReferenced(*this, Loc, Var, nullptr, RefsMinusAssignments);
}
-static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
- Decl *D, Expr *E, bool MightBeOdrUse) {
+static void
+MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E,
+ bool MightBeOdrUse,
+ llvm::DenseMap<const VarDecl *, int> &RefsMinusAssignments) {
if (SemaRef.isInOpenMPDeclareTargetContext())
SemaRef.checkDeclIsAllowedInOpenMPTarget(E, D);
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
- DoMarkVarDeclReferenced(SemaRef, Loc, Var, E);
+ DoMarkVarDeclReferenced(SemaRef, Loc, Var, E, RefsMinusAssignments);
return;
}
@@ -18325,7 +18729,8 @@
if (!isConstantEvaluated() && FD->isConsteval() &&
!RebuildingImmediateInvocation)
ExprEvalContexts.back().ReferenceToConsteval.insert(E);
- MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse);
+ MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse,
+ RefsMinusAssignments);
}
/// Perform reference-marking and odr-use handling for a MemberExpr.
@@ -18344,13 +18749,15 @@
}
SourceLocation Loc =
E->getMemberLoc().isValid() ? E->getMemberLoc() : E->getBeginLoc();
- MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse);
+ MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse,
+ RefsMinusAssignments);
}
/// Perform reference-marking and odr-use handling for a FunctionParmPackExpr.
void Sema::MarkFunctionParmPackReferenced(FunctionParmPackExpr *E) {
for (VarDecl *VD : *E)
- MarkExprReferenced(*this, E->getParameterPackLocation(), VD, E, true);
+ MarkExprReferenced(*this, E->getParameterPackLocation(), VD, E, true,
+ RefsMinusAssignments);
}
/// Perform marking for a reference to an arbitrary declaration. It
@@ -18769,7 +19176,7 @@
Expr *SubExpr = SubResult.get();
E->setSubExpr(SubExpr);
E->setType(S.Context.getPointerType(SubExpr->getType()));
- assert(E->getValueKind() == VK_RValue);
+ assert(E->isPRValue());
assert(E->getObjectKind() == OK_Ordinary);
return E;
}
@@ -18779,7 +19186,7 @@
E->setType(VD->getType());
- assert(E->getValueKind() == VK_RValue);
+ assert(E->isPRValue());
if (S.getLangOpts().CPlusPlus &&
!(isa<CXXMethodDecl>(VD) &&
cast<CXXMethodDecl>(VD)->isInstance()))
@@ -18870,7 +19277,7 @@
return ExprError();
}
- assert(E->getValueKind() == VK_RValue);
+ assert(E->isPRValue());
assert(E->getObjectKind() == OK_Ordinary);
E->setType(DestType);
@@ -19030,7 +19437,7 @@
ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) {
// The only case we should ever see here is a function-to-pointer decay.
if (E->getCastKind() == CK_FunctionToPointerDecay) {
- assert(E->getValueKind() == VK_RValue);
+ assert(E->isPRValue());
assert(E->getObjectKind() == OK_Ordinary);
E->setType(DestType);
@@ -19044,7 +19451,7 @@
E->setSubExpr(Result.get());
return E;
} else if (E->getCastKind() == CK_LValueToRValue) {
- assert(E->getValueKind() == VK_RValue);
+ assert(E->isPRValue());
assert(E->getObjectKind() == OK_Ordinary);
assert(isa<BlockPointerType>(E->getType()));
@@ -19076,8 +19483,8 @@
DestType = Ptr->getPointeeType();
ExprResult Result = resolveDecl(E, VD);
if (Result.isInvalid()) return ExprError();
- return S.ImpCastExprToType(Result.get(), Type,
- CK_FunctionToPointerDecay, VK_RValue);
+ return S.ImpCastExprToType(Result.get(), Type, CK_FunctionToPointerDecay,
+ VK_PRValue);
}
if (!Type->isFunctionType()) {
@@ -19119,13 +19526,13 @@
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
if (MD->isInstance()) {
- ValueKind = VK_RValue;
+ ValueKind = VK_PRValue;
Type = S.Context.BoundMemberTy;
}
// Function references aren't l-values in C.
if (!S.getLangOpts().CPlusPlus)
- ValueKind = VK_RValue;
+ ValueKind = VK_PRValue;
// - variables
} else if (isa<VarDecl>(VD)) {
@@ -19324,7 +19731,7 @@
CK_BuiltinFnToFnPtr)
.get();
return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy,
- VK_RValue, SourceLocation(),
+ VK_PRValue, SourceLocation(),
FPOptionsOverride());
}
}
@@ -19365,6 +19772,8 @@
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id:
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
#define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id:
#define PLACEHOLDER_TYPE(Id, SingletonId)
#include "clang/AST/BuiltinTypes.def"
@@ -19406,23 +19815,31 @@
ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
llvm::ArrayRef<AvailabilitySpec> AvailSpecs, SourceLocation AtLoc,
SourceLocation RParen) {
-
- StringRef Platform = getASTContext().getTargetInfo().getPlatformName();
-
- auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) {
- return Spec.getPlatform() == Platform;
- });
+ auto FindSpecVersion = [&](StringRef Platform) -> Optional<VersionTuple> {
+ auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) {
+ return Spec.getPlatform() == Platform;
+ });
+ // Transcribe the "ios" availability check to "maccatalyst" when compiling
+ // for "maccatalyst" if "maccatalyst" is not specified.
+ if (Spec == AvailSpecs.end() && Platform == "maccatalyst") {
+ Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) {
+ return Spec.getPlatform() == "ios";
+ });
+ }
+ if (Spec == AvailSpecs.end())
+ return None;
+ return Spec->getVersion();
+ };
VersionTuple Version;
- if (Spec != AvailSpecs.end())
- Version = Spec->getVersion();
+ if (auto MaybeVersion =
+ FindSpecVersion(Context.getTargetInfo().getPlatformName()))
+ Version = *MaybeVersion;
- // The use of `@available` in the enclosing function should be analyzed to
+ // The use of `@available` in the enclosing context should be analyzed to
// warn when it's used inappropriately (i.e. not if(@available)).
- if (getCurFunctionOrMethodDecl())
- getEnclosingFunction()->HasPotentialAvailabilityViolations = true;
- else if (getCurBlock() || getCurLambda())
- getCurFunction()->HasPotentialAvailabilityViolations = true;
+ if (FunctionScopeInfo *Context = getCurFunctionAvailabilityContext())
+ Context->HasPotentialAvailabilityViolations = true;
return new (Context)
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
@@ -19436,8 +19853,10 @@
if (isSFINAEContext())
return ExprError();
- if (T.isNull() || !Context.getLangOpts().RecoveryASTType)
+ if (T.isNull() || T->isUndeducedType() ||
+ !Context.getLangOpts().RecoveryASTType)
// We don't know the concrete type, fallback to dependent type.
T = Context.DependentTy;
+
return RecoveryExpr::Create(Context, T, Begin, End, SubExprs);
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaExprCXX.cpp b/src/llvm-project/clang/lib/Sema/SemaExprCXX.cpp
index d91db60..111ffa1 100644
--- a/src/llvm-project/clang/lib/Sema/SemaExprCXX.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaExprCXX.cpp
@@ -484,8 +484,25 @@
}
bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
- const UnqualifiedId &Name) {
+ const UnqualifiedId &Name, bool IsUDSuffix) {
assert(Name.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId);
+ if (!IsUDSuffix) {
+ // [over.literal] p8
+ //
+ // double operator""_Bq(long double); // OK: not a reserved identifier
+ // double operator"" _Bq(long double); // ill-formed, no diagnostic required
+ IdentifierInfo *II = Name.Identifier;
+ ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts());
+ SourceLocation Loc = Name.getEndLoc();
+ if (Status != ReservedIdentifierStatus::NotReserved &&
+ !PP.getSourceManager().isInSystemHeader(Loc)) {
+ Diag(Loc, diag::warn_reserved_extern_symbol)
+ << II << static_cast<int>(Status)
+ << FixItHint::CreateReplacement(
+ Name.getSourceRange(),
+ (StringRef("operator\"\"") + II->getName()).str());
+ }
+ }
if (!SS.isValid())
return false;
@@ -567,11 +584,14 @@
// polymorphic class type [...] [the] expression is an unevaluated
// operand. [...]
if (RecordD->isPolymorphic() && E->isGLValue()) {
- // The subexpression is potentially evaluated; switch the context
- // and recheck the subexpression.
- ExprResult Result = TransformToPotentiallyEvaluated(E);
- if (Result.isInvalid()) return ExprError();
- E = Result.get();
+ if (isUnevaluatedContext()) {
+ // The operand was processed in unevaluated context, switch the
+ // context and recheck the subexpression.
+ ExprResult Result = TransformToPotentiallyEvaluated(E);
+ if (Result.isInvalid())
+ return ExprError();
+ E = Result.get();
+ }
// We require a vtable to query the type at run time.
MarkVTableUsed(TypeidLoc, RecordD);
@@ -851,10 +871,6 @@
Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
if (Ex && !Ex->isTypeDependent()) {
- QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
- if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
- return ExprError();
-
// Initialize the exception result. This implicitly weeds out
// abstract types or types with inaccessible copy constructors.
@@ -870,15 +886,17 @@
// operation from the operand to the exception object (15.1) can be
// omitted by constructing the automatic object directly into the
// exception object
- const VarDecl *NRVOVariable = nullptr;
- if (IsThrownVarInScope)
- NRVOVariable = getCopyElisionCandidate(QualType(), Ex, CES_Strict);
+ NamedReturnInfo NRInfo =
+ IsThrownVarInScope ? getNamedReturnInfo(Ex) : NamedReturnInfo();
+
+ QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
+ if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
+ return ExprError();
InitializedEntity Entity = InitializedEntity::InitializeException(
OpLoc, ExceptionObjectTy,
- /*NRVO=*/NRVOVariable != nullptr);
- ExprResult Res = PerformMoveOrCopyInitialization(
- Entity, NRVOVariable, QualType(), Ex, IsThrownVarInScope);
+ /*NRVO=*/NRInfo.isCopyElidable());
+ ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRInfo, Ex);
if (Res.isInvalid())
return ExprError();
Ex = Res.get();
@@ -1176,15 +1194,11 @@
}
if (ThisTy.isNull() && isLambdaCallOperator(CurContext) &&
- inTemplateInstantiation()) {
-
- assert(isa<CXXRecordDecl>(DC) &&
- "Trying to get 'this' type from static method?");
+ inTemplateInstantiation() && isa<CXXRecordDecl>(DC)) {
// This is a lambda call operator that is being instantiated as a default
// initializer. DC must point to the enclosing class type, so we can recover
// the 'this' type from it.
-
QualType ClassTy = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
// There are no cv-qualifiers for 'this' within default initializers,
// per [expr.prim.general]p4.
@@ -1230,6 +1244,18 @@
}
}
+static void buildLambdaThisCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI) {
+ SourceLocation DiagLoc = LSI->IntroducerRange.getEnd();
+ assert(!LSI->isCXXThisCaptured());
+ // [=, this] {}; // until C++20: Error: this when = is the default
+ if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval &&
+ !Sema.getLangOpts().CPlusPlus20)
+ return;
+ Sema.Diag(DiagLoc, diag::note_lambda_this_capture_fixit)
+ << FixItHint::CreateInsertion(
+ DiagLoc, LSI->NumExplicitCaptures > 0 ? ", this" : "this");
+}
+
bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt,
const bool ByCopy) {
@@ -1278,9 +1304,12 @@
LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI);
if (LSI && isGenericLambdaCallOperatorSpecialization(LSI->CallOperator)) {
// This context can't implicitly capture 'this'; fail out.
- if (BuildAndDiagnose)
+ if (BuildAndDiagnose) {
Diag(Loc, diag::err_this_capture)
<< (Explicit && idx == MaxFunctionScopesIndex);
+ if (!Explicit)
+ buildLambdaThisCaptureFixit(*this, LSI);
+ }
return true;
}
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref ||
@@ -1300,6 +1329,9 @@
if (BuildAndDiagnose)
Diag(Loc, diag::err_this_capture)
<< (Explicit && idx == MaxFunctionScopesIndex);
+
+ if (!Explicit)
+ buildLambdaThisCaptureFixit(*this, LSI);
return true;
}
break;
@@ -2126,7 +2158,7 @@
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
return ExprError(
Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large)
- << Value->toString(10) << (*ArraySize)->getSourceRange());
+ << toString(*Value, 10) << (*ArraySize)->getSourceRange());
}
KnownArraySize = Value->getZExtValue();
@@ -2221,7 +2253,7 @@
SizeTy, SourceLocation());
// Otherwise, if we failed to constant-fold the allocation size, we'll
// just give up and pass-in something opaque, that isn't a null pointer.
- OpaqueValueExpr OpaqueAllocationSize(SourceLocation(), SizeTy, VK_RValue,
+ OpaqueValueExpr OpaqueAllocationSize(SourceLocation(), SizeTy, VK_PRValue,
OK_Ordinary, /*SourceExpr=*/nullptr);
// Let's synthesize the alignment argument in case we will need it.
@@ -2237,7 +2269,7 @@
SizeTy, SourceLocation());
ImplicitCastExpr DesiredAlignment(ImplicitCastExpr::OnStack, AlignValT,
CK_IntegralCast, &AlignmentLiteral,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
// Adjust placement args by prepending conjured size and alignment exprs.
llvm::SmallVector<Expr *, 8> CallArgs;
@@ -2462,12 +2494,27 @@
}
if (Diagnose) {
- PartialDiagnosticAt PD(R.getNameLoc(), S.PDiag(diag::err_ovl_no_viable_function_in_call)
- << R.getLookupName() << Range);
+ // If this is an allocation of the form 'new (p) X' for some object
+ // pointer p (or an expression that will decay to such a pointer),
+ // diagnose the missing inclusion of <new>.
+ if (!R.isClassLookup() && Args.size() == 2 &&
+ (Args[1]->getType()->isObjectPointerType() ||
+ Args[1]->getType()->isArrayType())) {
+ S.Diag(R.getNameLoc(), diag::err_need_header_before_placement_new)
+ << R.getLookupName() << Range;
+ // Listing the candidates is unlikely to be useful; skip it.
+ return true;
+ }
- // If we have aligned candidates, only note the align_val_t candidates
- // from AlignedCandidates and the non-align_val_t candidates from
- // Candidates.
+ // Finish checking all candidates before we note any. This checking can
+ // produce additional diagnostics so can't be interleaved with our
+ // emission of notes.
+ //
+ // For an aligned allocation, separately check the aligned and unaligned
+ // candidates with their respective argument lists.
+ SmallVector<OverloadCandidate*, 32> Cands;
+ SmallVector<OverloadCandidate*, 32> AlignedCands;
+ llvm::SmallVector<Expr*, 4> AlignedArgs;
if (AlignedCandidates) {
auto IsAligned = [](OverloadCandidate &C) {
return C.Function->getNumParams() > 1 &&
@@ -2475,17 +2522,26 @@
};
auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); };
- // This was an overaligned allocation, so list the aligned candidates
- // first.
- Args.insert(Args.begin() + 1, AlignArg);
- AlignedCandidates->NoteCandidates(PD, S, OCD_AllCandidates, Args, "",
- R.getNameLoc(), IsAligned);
- Args.erase(Args.begin() + 1);
- Candidates.NoteCandidates(PD, S, OCD_AllCandidates, Args, "", R.getNameLoc(),
- IsUnaligned);
+ AlignedArgs.reserve(Args.size() + 1);
+ AlignedArgs.push_back(Args[0]);
+ AlignedArgs.push_back(AlignArg);
+ AlignedArgs.append(Args.begin() + 1, Args.end());
+ AlignedCands = AlignedCandidates->CompleteCandidates(
+ S, OCD_AllCandidates, AlignedArgs, R.getNameLoc(), IsAligned);
+
+ Cands = Candidates.CompleteCandidates(S, OCD_AllCandidates, Args,
+ R.getNameLoc(), IsUnaligned);
} else {
- Candidates.NoteCandidates(PD, S, OCD_AllCandidates, Args);
+ Cands = Candidates.CompleteCandidates(S, OCD_AllCandidates, Args,
+ R.getNameLoc());
}
+
+ S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call)
+ << R.getLookupName() << Range;
+ if (AlignedCandidates)
+ AlignedCandidates->NoteCandidates(S, AlignedArgs, AlignedCands, "",
+ R.getNameLoc());
+ Candidates.NoteCandidates(S, Args, Cands, "", R.getNameLoc());
}
return true;
@@ -3855,7 +3911,7 @@
/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) {
- // C++ 6.4p4:
+ // C++11 6.4p4:
// The value of a condition that is an initialized declaration in a statement
// other than a switch statement is the value of the declared variable
// implicitly converted to type bool. If that conversion is ill-formed, the
@@ -3863,12 +3919,22 @@
// The value of a condition that is an expression is the value of the
// expression, implicitly converted to bool.
//
+ // C++2b 8.5.2p2
+ // If the if statement is of the form if constexpr, the value of the condition
+ // is contextually converted to bool and the converted expression shall be
+ // a constant expression.
+ //
+
+ ExprResult E = PerformContextuallyConvertToBool(CondExpr);
+ if (!IsConstexpr || E.isInvalid() || E.get()->isValueDependent())
+ return E;
+
// FIXME: Return this value to the caller so they don't need to recompute it.
- llvm::APSInt Value(/*BitWidth*/1);
- return (IsConstexpr && !CondExpr->isValueDependent())
- ? CheckConvertedConstantExpression(CondExpr, Context.BoolTy, Value,
- CCEK_ConstexprIf)
- : PerformContextuallyConvertToBool(CondExpr);
+ llvm::APSInt Cond;
+ E = VerifyIntegerConstantExpression(
+ E.get(), &Cond,
+ diag::err_constexpr_if_condition_expression_is_not_constant);
+ return E;
}
/// Helper function to determine whether this is the (deprecated) C++
@@ -3929,7 +3995,8 @@
diag::err_allocation_of_abstract_type))
return ExprError();
- if (S.CompleteConstructorCall(Constructor, From, CastLoc, ConstructorArgs))
+ if (S.CompleteConstructorCall(Constructor, Ty, From, CastLoc,
+ ConstructorArgs))
return ExprError();
S.CheckConstructorAccess(CastLoc, Constructor, FoundDecl,
@@ -4097,9 +4164,9 @@
assert(!ToType->isReferenceType());
if (SCS.Second == ICK_Derived_To_Base) {
SmallVector<Expr*, 8> ConstructorArgs;
- if (CompleteConstructorCall(cast<CXXConstructorDecl>(SCS.CopyConstructor),
- From, /*FIXME:ConstructLoc*/SourceLocation(),
- ConstructorArgs))
+ if (CompleteConstructorCall(
+ cast<CXXConstructorDecl>(SCS.CopyConstructor), ToType, From,
+ /*FIXME:ConstructLoc*/ SourceLocation(), ConstructorArgs))
return ExprError();
return BuildCXXConstructExpr(
/*FIXME:ConstructLoc*/ SourceLocation(), ToType,
@@ -4146,7 +4213,7 @@
if (const AtomicType *FromAtomic = FromType->getAs<AtomicType>()) {
FromType = FromAtomic->getValueType().getUnqualifiedType();
From = ImplicitCastExpr::Create(Context, FromType, CK_AtomicToNonAtomic,
- From, /*BasePath=*/nullptr, VK_RValue,
+ From, /*BasePath=*/nullptr, VK_PRValue,
FPOptionsOverride());
}
break;
@@ -4154,7 +4221,9 @@
case ICK_Lvalue_To_Rvalue: {
assert(From->getObjectKind() != OK_ObjCProperty);
ExprResult FromRes = DefaultLvalueConversion(From);
- assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!");
+ if (FromRes.isInvalid())
+ return ExprError();
+
From = FromRes.get();
FromType = From->getType();
break;
@@ -4162,14 +4231,16 @@
case ICK_Array_To_Pointer:
FromType = Context.getArrayDecayedType(FromType);
- From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
break;
case ICK_Function_To_Pointer:
FromType = Context.getPointerType(FromType);
From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ VK_PRValue, /*BasePath=*/nullptr, CCK)
+ .get();
break;
default:
@@ -4211,18 +4282,21 @@
assert(FromType->castAs<EnumType>()->getDecl()->isFixed() &&
SCS.Second == ICK_Integral_Promotion &&
"only enums with fixed underlying type can promote to bool");
- From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
} else {
- From = ImpCastExprToType(From, ToType, CK_IntegralCast,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, ToType, CK_IntegralCast, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
}
break;
case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
- From = ImpCastExprToType(From, ToType, CK_FloatingCast,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, ToType, CK_FloatingCast, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
break;
case ICK_Complex_Promotion:
@@ -4240,18 +4314,21 @@
} else {
CK = CK_IntegralComplexCast;
}
- From = ImpCastExprToType(From, ToType, CK,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, ToType, CK, VK_PRValue, /*BasePath=*/nullptr,
+ CCK)
+ .get();
break;
}
case ICK_Floating_Integral:
if (ToType->isRealFloatingType())
- From = ImpCastExprToType(From, ToType, CK_IntegralToFloating,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, ToType, CK_IntegralToFloating, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
else
- From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
break;
case ICK_Compatible_Conversion:
@@ -4319,8 +4396,8 @@
}
if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
CheckObjCConversion(SourceRange(), NewToType, From, CCK);
- From = ImpCastExprToType(From, NewToType, Kind, VK_RValue, &BasePath, CCK)
- .get();
+ From = ImpCastExprToType(From, NewToType, Kind, VK_PRValue, &BasePath, CCK)
+ .get();
break;
}
@@ -4339,8 +4416,8 @@
(void)isCompleteType(From->getExprLoc(), ToType);
}
- From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
- .get();
+ From =
+ ImpCastExprToType(From, ToType, Kind, VK_PRValue, &BasePath, CCK).get();
break;
}
@@ -4352,8 +4429,9 @@
}
From = ImpCastExprToType(From, Context.BoolTy,
- ScalarTypeToBooleanCastKind(FromType),
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ ScalarTypeToBooleanCastKind(FromType), VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
break;
case ICK_Derived_To_Base: {
@@ -4370,12 +4448,13 @@
}
case ICK_Vector_Conversion:
- From = ImpCastExprToType(From, ToType, CK_BitCast,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, ToType, CK_BitCast, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
break;
case ICK_SVE_Vector_Conversion:
- From = ImpCastExprToType(From, ToType, CK_BitCast, VK_RValue,
+ From = ImpCastExprToType(From, ToType, CK_BitCast, VK_PRValue,
/*BasePath=*/nullptr, CCK)
.get();
break;
@@ -4383,8 +4462,9 @@
case ICK_Vector_Splat: {
// Vector splat from any arithmetic type to a vector.
Expr *Elem = prepareVectorSplat(ToType, From).get();
- From = ImpCastExprToType(Elem, ToType, CK_VectorSplat, VK_RValue,
- /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(Elem, ToType, CK_VectorSplat, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
break;
}
@@ -4418,22 +4498,27 @@
// _Complex x -> x
From = ImpCastExprToType(From, ElType,
- isFloatingComplex ? CK_FloatingComplexToReal
- : CK_IntegralComplexToReal,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ isFloatingComplex ? CK_FloatingComplexToReal
+ : CK_IntegralComplexToReal,
+ VK_PRValue, /*BasePath=*/nullptr, CCK)
+ .get();
// x -> y
if (Context.hasSameUnqualifiedType(ElType, ToType)) {
// do nothing
} else if (ToType->isRealFloatingType()) {
From = ImpCastExprToType(From, ToType,
- isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ isFloatingComplex ? CK_FloatingCast
+ : CK_IntegralToFloating,
+ VK_PRValue, /*BasePath=*/nullptr, CCK)
+ .get();
} else {
assert(ToType->isIntegerType());
From = ImpCastExprToType(From, ToType,
- isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ isFloatingComplex ? CK_FloatingToIntegral
+ : CK_IntegralCast,
+ VK_PRValue, /*BasePath=*/nullptr, CCK)
+ .get();
}
}
break;
@@ -4448,7 +4533,8 @@
CastKind Kind =
AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
From = ImpCastExprToType(From, ToType.getUnqualifiedType(), Kind,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ VK_PRValue, /*BasePath=*/nullptr, CCK)
+ .get();
break;
}
@@ -4494,8 +4580,9 @@
if (CheckExceptionSpecCompatibility(From, ToType))
return ExprError();
- From = ImpCastExprToType(From, ToType, CK_NoOp,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ From = ImpCastExprToType(From, ToType, CK_NoOp, VK_PRValue,
+ /*BasePath=*/nullptr, CCK)
+ .get();
break;
case ICK_Qualification: {
@@ -4538,13 +4625,14 @@
assert(Context.hasSameType(
ToAtomicType->castAs<AtomicType>()->getValueType(), From->getType()));
From = ImpCastExprToType(From, ToAtomicType, CK_NonAtomicToAtomic,
- VK_RValue, nullptr, CCK).get();
+ VK_PRValue, nullptr, CCK)
+ .get();
}
// Materialize a temporary if we're implicitly converting to a reference
// type. This is not required by the C++ rules but is necessary to maintain
// AST invariants.
- if (ToType->isReferenceType() && From->isRValue()) {
+ if (ToType->isReferenceType() && From->isPRValue()) {
ExprResult Res = TemporaryMaterializationConversion(From);
if (Res.isInvalid())
return ExprError();
@@ -4835,9 +4923,11 @@
case UTT_IsSigned:
// Enum types should always return false.
// Floating points should always return true.
- return !T->isEnumeralType() && (T->isFloatingType() || T->isSignedIntegerType());
+ return T->isFloatingType() ||
+ (T->isSignedIntegerType() && !T->isEnumeralType());
case UTT_IsUnsigned:
- return T->isUnsignedIntegerType();
+ // Enum types should always return false.
+ return T->isUnsignedIntegerType() && !T->isEnumeralType();
// Type trait expressions which query classes regarding their construction,
// destruction, and copying. Rather than being based directly on the
@@ -5595,7 +5685,8 @@
static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) {
switch (ET) {
case ET_IsLValueExpr: return E->isLValue();
- case ET_IsRValueExpr: return E->isRValue();
+ case ET_IsRValueExpr:
+ return E->isPRValue();
}
llvm_unreachable("Expression trait not covered by switch");
}
@@ -5630,7 +5721,7 @@
// temporary materialization conversion otherwise.
if (isIndirect)
LHS = DefaultLvalueConversion(LHS.get());
- else if (LHS.get()->isRValue())
+ else if (LHS.get()->isPRValue())
LHS = TemporaryMaterializationConversion(LHS.get());
if (LHS.isInvalid())
return QualType();
@@ -5700,7 +5791,7 @@
QualType UseType = Context.getQualifiedType(Class, LHSType.getQualifiers());
if (isIndirect)
UseType = Context.getPointerType(UseType);
- ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind();
+ ExprValueKind VK = isIndirect ? VK_PRValue : LHS.get()->getValueKind();
LHS = ImpCastExprToType(LHS.get(), UseType, CK_DerivedToBase, VK,
&BasePath);
}
@@ -5762,7 +5853,7 @@
// result of an ->* expression is an lvalue if its second operand
// is a pointer to data member and a prvalue otherwise.
if (Result->isFunctionType()) {
- VK = VK_RValue;
+ VK = VK_PRValue;
return Context.BoundMemberTy;
} else if (isIndirect) {
VK = VK_LValue;
@@ -5949,19 +6040,18 @@
// extension.
static bool isValidVectorForConditionalCondition(ASTContext &Ctx,
QualType CondTy) {
- if (!CondTy->isVectorType() || CondTy->isExtVectorType())
+ if (!CondTy->isVectorType() && !CondTy->isExtVectorType())
return false;
const QualType EltTy =
cast<VectorType>(CondTy.getCanonicalType())->getElementType();
-
assert(!EltTy->isBooleanType() && !EltTy->isEnumeralType() &&
"Vectors cant be boolean or enum types");
return EltTy->isIntegralType(Ctx);
}
-QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
- ExprResult &RHS,
- SourceLocation QuestionLoc) {
+QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
+ ExprResult &RHS,
+ SourceLocation QuestionLoc) {
LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
@@ -5976,24 +6066,17 @@
QualType ResultType;
- // FIXME: In the future we should define what the Extvector conditional
- // operator looks like.
- if (LHSVT && isa<ExtVectorType>(LHSVT)) {
- Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
- << /*isExtVector*/ true << LHSType;
- return {};
- }
-
- if (RHSVT && isa<ExtVectorType>(RHSVT)) {
- Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
- << /*isExtVector*/ true << RHSType;
- return {};
- }
if (LHSVT && RHSVT) {
+ if (isa<ExtVectorType>(CondVT) != isa<ExtVectorType>(LHSVT)) {
+ Diag(QuestionLoc, diag::err_conditional_vector_cond_result_mismatch)
+ << /*isExtVector*/ isa<ExtVectorType>(CondVT);
+ return {};
+ }
+
// If both are vector types, they must be the same type.
if (!Context.hasSameType(LHSType, RHSType)) {
- Diag(QuestionLoc, diag::err_conditional_vector_mismatched_vectors)
+ Diag(QuestionLoc, diag::err_conditional_vector_mismatched)
<< LHSType << RHSType;
return {};
}
@@ -6018,18 +6101,22 @@
if (ResultElementTy->isEnumeralType()) {
Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
- << /*isExtVector*/ false << ResultElementTy;
+ << ResultElementTy;
return {};
}
- ResultType = Context.getVectorType(
- ResultElementTy, CondType->castAs<VectorType>()->getNumElements(),
- VectorType::GenericVector);
+ if (CondType->isExtVectorType())
+ ResultType =
+ Context.getExtVectorType(ResultElementTy, CondVT->getNumElements());
+ else
+ ResultType = Context.getVectorType(
+ ResultElementTy, CondVT->getNumElements(), VectorType::GenericVector);
LHS = ImpCastExprToType(LHS.get(), ResultType, CK_VectorSplat);
RHS = ImpCastExprToType(RHS.get(), ResultType, CK_VectorSplat);
}
assert(!ResultType.isNull() && ResultType->isVectorType() &&
+ (!CondType->isExtVectorType() || ResultType->isExtVectorType()) &&
"Result should have been a vector type");
auto *ResultVectorTy = ResultType->castAs<VectorType>();
QualType ResultElementTy = ResultVectorTy->getElementType();
@@ -6056,15 +6143,21 @@
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
/// extension. In this case, LHS == Cond. (But they're not aliases.)
///
-/// This function also implements GCC's vector extension for conditionals.
-/// GCC's vector extension permits the use of a?b:c where the type of
-/// a is that of a integer vector with the same number of elements and
-/// size as the vectors of b and c. If one of either b or c is a scalar
-/// it is implicitly converted to match the type of the vector.
-/// Otherwise the expression is ill-formed. If both b and c are scalars,
-/// then b and c are checked and converted to the type of a if possible.
-/// Unlike the OpenCL ?: operator, the expression is evaluated as
-/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]).
+/// This function also implements GCC's vector extension and the
+/// OpenCL/ext_vector_type extension for conditionals. The vector extensions
+/// permit the use of a?b:c where the type of a is that of a integer vector with
+/// the same number of elements and size as the vectors of b and c. If one of
+/// either b or c is a scalar it is implicitly converted to match the type of
+/// the vector. Otherwise the expression is ill-formed. If both b and c are
+/// scalars, then b and c are checked and converted to the type of a if
+/// possible.
+///
+/// The expressions are evaluated differently for GCC's and OpenCL's extensions.
+/// For the GCC extension, the ?: operator is evaluated as
+/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]).
+/// For the OpenCL extensions, the ?: operator is evaluated as
+/// (most-significant-bit-set(a[0]) ? b[0] : c[0], .. ,
+/// most-significant-bit-set(a[n]) ? b[n] : c[n]).
QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
ExprResult &RHS, ExprValueKind &VK,
ExprObjectKind &OK,
@@ -6073,7 +6166,7 @@
// pointers.
// Assume r-value.
- VK = VK_RValue;
+ VK = VK_PRValue;
OK = OK_Ordinary;
bool IsVectorConditional =
isValidVectorForConditionalCondition(Context, Cond.get()->getType());
@@ -6148,7 +6241,7 @@
// Neither is void.
if (IsVectorConditional)
- return CheckGNUVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
+ return CheckVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
// C++11 [expr.cond]p3
// Otherwise, if the second and third operand have different types, and
@@ -6198,8 +6291,7 @@
// that instead?
ExprValueKind LVK = LHS.get()->getValueKind();
ExprValueKind RVK = RHS.get()->getValueKind();
- if (!Context.hasSameType(LTy, RTy) &&
- LVK == RVK && LVK != VK_RValue) {
+ if (!Context.hasSameType(LTy, RTy) && LVK == RVK && LVK != VK_PRValue) {
// DerivedToBase was already handled by the class-specific case above.
// FIXME: Should we allow ObjC conversions here?
const ReferenceConversions AllowedConversions =
@@ -6234,7 +6326,7 @@
// We only extend this to bitfields, not to the crazy other kinds of
// l-values.
bool Same = Context.hasSameType(LTy, RTy);
- if (Same && LVK == RVK && LVK != VK_RValue &&
+ if (Same && LVK == RVK && LVK != VK_PRValue &&
LHS.get()->isOrdinaryOrBitFieldObject() &&
RHS.get()->isOrdinaryOrBitFieldObject()) {
VK = LHS.get()->getValueKind();
@@ -6805,7 +6897,7 @@
assert(!isa<CXXBindTemporaryExpr>(E) && "Double-bound temporary?");
// If the result is a glvalue, we shouldn't bind it.
- if (!E->isRValue())
+ if (E->isGLValue())
return E;
// In ARC, calls that return a retainable type can return retained,
@@ -6897,7 +6989,7 @@
CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject
: CK_ARCReclaimReturnedObject);
return ImplicitCastExpr::Create(Context, E->getType(), ck, E, nullptr,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
}
if (E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
@@ -7690,7 +7782,7 @@
NestedNameSpecifierLoc(), SourceLocation(), Method,
DeclAccessPair::make(FoundDecl, FoundDecl->getAccess()),
HadMultipleCandidates, DeclarationNameInfo(),
- Context.BoundMemberTy, VK_RValue, OK_Ordinary);
+ Context.BoundMemberTy, VK_PRValue, OK_Ordinary);
QualType ResultType = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
@@ -7704,7 +7796,7 @@
Method->getType()->castAs<FunctionProtoType>()))
return ExprError();
- return CE;
+ return CheckForImmediateInvocation(CE, CE->getMethodDecl());
}
ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
@@ -7739,9 +7831,38 @@
return BuildCXXNoexceptExpr(KeyLoc, Operand, RParen);
}
+static void MaybeDecrementCount(
+ Expr *E, llvm::DenseMap<const VarDecl *, int> &RefsMinusAssignments) {
+ DeclRefExpr *LHS = nullptr;
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getLHS()->getType()->isDependentType() ||
+ BO->getRHS()->getType()->isDependentType()) {
+ if (BO->getOpcode() != BO_Assign)
+ return;
+ } else if (!BO->isAssignmentOp())
+ return;
+ LHS = dyn_cast<DeclRefExpr>(BO->getLHS());
+ } else if (CXXOperatorCallExpr *COCE = dyn_cast<CXXOperatorCallExpr>(E)) {
+ if (COCE->getOperator() != OO_Equal)
+ return;
+ LHS = dyn_cast<DeclRefExpr>(COCE->getArg(0));
+ }
+ if (!LHS)
+ return;
+ VarDecl *VD = dyn_cast<VarDecl>(LHS->getDecl());
+ if (!VD)
+ return;
+ auto iter = RefsMinusAssignments.find(VD);
+ if (iter == RefsMinusAssignments.end())
+ return;
+ iter->getSecond()--;
+}
+
/// Perform the conversions required for an expression used in a
/// context that ignores the result.
ExprResult Sema::IgnoredValueConversions(Expr *E) {
+ MaybeDecrementCount(E, RefsMinusAssignments);
+
if (E->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return E;
@@ -7752,7 +7873,7 @@
// [Except in specific positions,] an lvalue that does not have
// array type is converted to the value stored in the
// designated object (and is no longer an lvalue).
- if (E->isRValue()) {
+ if (E->isPRValue()) {
// In C, function designators (i.e. expressions of function type)
// are r-values, but we still want to do function-to-pointer decay
// on them. This is both technically correct and convenient for
@@ -8232,6 +8353,7 @@
AmbiguousTypoExprs.remove(TE);
SemaRef.getTypoExprState(TE).Consumer->restoreSavedPosition();
+ TransformCache[TE] = SavedTransformCache[TE];
}
TransformCache = std::move(SavedTransformCache);
}
@@ -8586,8 +8708,9 @@
/*ParameterPack=*/false,
/*HasTypeConstraint=*/true);
- if (ActOnTypeConstraint(SS, TypeConstraint, TParam,
- /*EllpsisLoc=*/SourceLocation()))
+ if (BuildTypeConstraint(SS, TypeConstraint, TParam,
+ /*EllpsisLoc=*/SourceLocation(),
+ /*AllowUnexpandedPack=*/true))
// Just produce a requirement with no type requirements.
return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, {});
@@ -8620,7 +8743,7 @@
TemplateParameterList *TPL =
ReturnTypeRequirement.getTypeConstraintTemplateParameterList();
QualType MatchedType =
- BuildDecltypeType(E, E->getBeginLoc()).getCanonicalType();
+ getDecltypeForParenthesizedExpr(E).getCanonicalType();
llvm::SmallVector<TemplateArgument, 1> Args;
Args.push_back(TemplateArgument(MatchedType));
TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args);
diff --git a/src/llvm-project/clang/lib/Sema/SemaExprMember.cpp b/src/llvm-project/clang/lib/Sema/SemaExprMember.cpp
index f5afcb7..af2aa49 100644
--- a/src/llvm-project/clang/lib/Sema/SemaExprMember.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaExprMember.cpp
@@ -338,13 +338,12 @@
compStr++;
} while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);
- // Emit a warning if an rgba selector is used earlier than OpenCL 2.2
+ // Emit a warning if an rgba selector is used earlier than OpenCL C 3.0.
if (HasRGBA || (*compStr && IsRGBA(*compStr))) {
- if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion < 220) {
+ if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion < 300) {
const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr;
S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector)
- << StringRef(DiagBegin, 1)
- << S.getLangOpts().OpenCLVersion << SourceRange(CompLoc);
+ << StringRef(DiagBegin, 1) << SourceRange(CompLoc);
}
}
} else {
@@ -409,7 +408,8 @@
if (CompSize == 1)
return vecType->getElementType();
- if (HasRepeated) VK = VK_RValue;
+ if (HasRepeated)
+ VK = VK_PRValue;
QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);
// Now look up the TypeDefDecl from the vector type. Without this,
@@ -761,7 +761,7 @@
if (!Base) {
TypoExpr *TE = nullptr;
QualType RecordTy = BaseType;
- if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
+ if (IsArrow) RecordTy = RecordTy->castAs<PointerType>()->getPointeeType();
if (LookupMemberExprInRecord(
*this, R, nullptr, RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
SS, TemplateArgs != nullptr, TemplateKWLoc, TE))
@@ -910,7 +910,8 @@
bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
QualType Ty, ExprValueKind VK, ExprObjectKind OK,
const TemplateArgumentListInfo *TemplateArgs) {
- assert((!IsArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
+ assert((!IsArrow || Base->isPRValue()) &&
+ "-> base must be a pointer prvalue");
MemberExpr *E =
MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc,
Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty,
@@ -964,14 +965,13 @@
// C++1z [expr.ref]p2:
// For the first option (dot) the first expression shall be a glvalue [...]
- if (!IsArrow && BaseExpr && BaseExpr->isRValue()) {
+ if (!IsArrow && BaseExpr && BaseExpr->isPRValue()) {
ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);
if (Converted.isInvalid())
return ExprError();
BaseExpr = Converted.get();
}
-
const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
DeclarationName MemberName = MemberNameInfo.getName();
SourceLocation MemberLoc = MemberNameInfo.getLoc();
@@ -1119,7 +1119,7 @@
ExprValueKind valueKind;
QualType type;
if (MemberFn->isInstance()) {
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
type = Context.BoundMemberTy;
} else {
valueKind = VK_LValue;
@@ -1135,7 +1135,7 @@
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Enum,
FoundDecl, /*HadMultipleCandidates=*/false,
- MemberNameInfo, Enum->getType(), VK_RValue,
+ MemberNameInfo, Enum->getType(), VK_PRValue,
OK_Ordinary);
}
@@ -1779,9 +1779,9 @@
if (BaseExpr->getObjectKind() == OK_Ordinary)
VK = BaseExpr->getValueKind();
else
- VK = VK_RValue;
+ VK = VK_PRValue;
}
- if (VK != VK_RValue && Field->isBitField())
+ if (VK != VK_PRValue && Field->isBitField())
OK = OK_BitField;
// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
@@ -1791,7 +1791,7 @@
VK = VK_LValue;
} else {
QualType BaseType = BaseExpr->getType();
- if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType();
+ if (IsArrow) BaseType = BaseType->castAs<PointerType>()->getPointeeType();
Qualifiers BaseQuals = BaseType.getQualifiers();
diff --git a/src/llvm-project/clang/lib/Sema/SemaExprObjC.cpp b/src/llvm-project/clang/lib/Sema/SemaExprObjC.cpp
index f5456ee..8a9c933 100644
--- a/src/llvm-project/clang/lib/Sema/SemaExprObjC.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaExprObjC.cpp
@@ -1786,7 +1786,7 @@
} else {
ReturnType = Context.getObjCIdType();
}
- VK = VK_RValue;
+ VK = VK_PRValue;
return false;
}
@@ -1821,7 +1821,8 @@
ParmVarDecl *param = Method->parameters()[i];
assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
- if (param->hasAttr<NoEscapeAttr>())
+ if (param->hasAttr<NoEscapeAttr>() &&
+ param->getType()->isBlockPointerType())
if (auto *BE = dyn_cast<BlockExpr>(
argExpr->IgnoreParenNoopCasts(Context)))
BE->getBlockDecl()->setDoesNotEscape();
@@ -1872,7 +1873,7 @@
// If we are type-erasing a block to a block-compatible
// Objective-C pointer type, we may need to extend the lifetime
// of the block object.
- if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() &&
+ if (typeArgs && Args[i]->isPRValue() && paramType->isBlockPointerType() &&
Args[i]->getType()->isBlockPointerType() &&
origParamType->isObjCObjectPointerType()) {
ExprResult arg = Args[i];
@@ -2633,7 +2634,7 @@
Expr **Args = ArgsIn.data();
assert(SuperLoc.isInvalid() && "Message to super with dependent type");
return ObjCMessageExpr::Create(
- Context, ReceiverType, VK_RValue, LBracLoc, ReceiverTypeInfo, Sel,
+ Context, ReceiverType, VK_PRValue, LBracLoc, ReceiverTypeInfo, Sel,
SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs), RBracLoc,
isImplicit);
}
@@ -2681,7 +2682,7 @@
// Check the argument types and determine the result type.
QualType ReturnType;
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
@@ -2886,7 +2887,7 @@
Expr **Args = ArgsIn.data();
assert(SuperLoc.isInvalid() && "Message to super with dependent type");
return ObjCMessageExpr::Create(
- Context, Context.DependentTy, VK_RValue, LBracLoc, Receiver, Sel,
+ Context, Context.DependentTy, VK_PRValue, LBracLoc, Receiver, Sel,
SelectorLocs, /*Method=*/nullptr, makeArrayRef(Args, NumArgs),
RBracLoc, isImplicit);
}
@@ -3225,7 +3226,7 @@
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
QualType ReturnType;
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
bool ClassMessage = (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType());
if (CheckMessageArgumentTypes(Receiver, ReceiverType,
@@ -3847,9 +3848,12 @@
QualType QT = TDNDecl->getUnderlyingType();
if (QT->isPointerType()) {
QT = QT->getPointeeType();
- if (const RecordType *RT = QT->getAs<RecordType>())
- if (RecordDecl *RD = RT->getDecl()->getMostRecentDecl())
- return RD->getAttr<T>();
+ if (const RecordType *RT = QT->getAs<RecordType>()) {
+ for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) {
+ if (auto *attr = Redecl->getAttr<T>())
+ return attr;
+ }
+ }
}
return nullptr;
}
@@ -4469,7 +4473,7 @@
case ACC_plusOne:
castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(),
CK_ARCConsumeObject, castExpr, nullptr,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
Cleanup.setExprNeedsCleanups(true);
return ACR_okay;
}
@@ -4696,7 +4700,7 @@
case OBC_BridgeRetained:
// Produce the object before casting it.
SubExpr = ImplicitCastExpr::Create(Context, FromType, CK_ARCProduceObject,
- SubExpr, nullptr, VK_RValue,
+ SubExpr, nullptr, VK_PRValue,
FPOptionsOverride());
break;
@@ -4736,7 +4740,7 @@
if (MustConsume) {
Cleanup.setExprNeedsCleanups(true);
Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result,
- nullptr, VK_RValue, FPOptionsOverride());
+ nullptr, VK_PRValue, FPOptionsOverride());
}
return Result;
diff --git a/src/llvm-project/clang/lib/Sema/SemaFixItUtils.cpp b/src/llvm-project/clang/lib/Sema/SemaFixItUtils.cpp
index 41a7a90..2910a56 100644
--- a/src/llvm-project/clang/lib/Sema/SemaFixItUtils.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaFixItUtils.cpp
@@ -132,8 +132,8 @@
if (!Expr->isLValue() || Expr->getObjectKind() != OK_Ordinary)
return false;
- CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy,
- S, Begin, VK_RValue);
+ CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy, S,
+ Begin, VK_PRValue);
if (CanConvert) {
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) {
diff --git a/src/llvm-project/clang/lib/Sema/SemaInit.cpp b/src/llvm-project/clang/lib/Sema/SemaInit.cpp
index f4493d8..78574e3 100644
--- a/src/llvm-project/clang/lib/Sema/SemaInit.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaInit.cpp
@@ -24,6 +24,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -150,7 +151,7 @@
static void updateStringLiteralType(Expr *E, QualType Ty) {
while (true) {
E->setType(Ty);
- E->setValueKind(VK_RValue);
+ E->setValueKind(VK_PRValue);
if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E)) {
break;
} else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
@@ -172,7 +173,7 @@
/// as an rvalue.
static void updateGNUCompoundLiteralRValue(Expr *E) {
while (true) {
- E->setValueKind(VK_RValue);
+ E->setValueKind(VK_PRValue);
if (isa<CompoundLiteralExpr>(E)) {
break;
} else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
@@ -315,7 +316,8 @@
InitListExpr *IList, QualType ElemType,
unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex);
+ unsigned &StructuredIndex,
+ bool DirectlyDesignated = false);
void CheckComplexType(const InitializedEntity &Entity,
InitListExpr *IList, QualType DeclType,
unsigned &Index,
@@ -1005,21 +1007,33 @@
//
// (where std::array is an aggregate struct containing a single array field.
- // FIXME: Should aggregate initialization of a struct with a single
- // base class and no members also suppress the warning?
- if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent())
+ if (!Entity.getParent())
return false;
- auto *ParentRD =
- Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
- if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD))
- if (CXXRD->getNumBases())
- return false;
+ // Allows elide brace initialization for aggregates with empty base.
+ if (Entity.getKind() == InitializedEntity::EK_Base) {
+ auto *ParentRD =
+ Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
+ CXXRecordDecl *CXXRD = cast<CXXRecordDecl>(ParentRD);
+ return CXXRD->getNumBases() == 1 && CXXRD->field_empty();
+ }
- auto FieldIt = ParentRD->field_begin();
- assert(FieldIt != ParentRD->field_end() &&
- "no fields but have initializer for member?");
- return ++FieldIt == ParentRD->field_end();
+ // Allow brace elision if the only subobject is a field.
+ if (Entity.getKind() == InitializedEntity::EK_Member) {
+ auto *ParentRD =
+ Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
+ if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD)) {
+ if (CXXRD->getNumBases()) {
+ return false;
+ }
+ }
+ auto FieldIt = ParentRD->field_begin();
+ assert(FieldIt != ParentRD->field_end() &&
+ "no fields but have initializer for member?");
+ return ++FieldIt == ParentRD->field_end();
+ }
+
+ return false;
}
/// Check whether the range of the initializer \p ParentIList from element
@@ -1326,7 +1340,8 @@
QualType ElemType,
unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex) {
+ unsigned &StructuredIndex,
+ bool DirectlyDesignated) {
Expr *expr = IList->getInit(Index);
if (ElemType->isReferenceType())
@@ -1462,6 +1477,20 @@
CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
StructuredIndex);
++StructuredIndex;
+
+ // In C++20, brace elision is not permitted for a designated initializer.
+ if (DirectlyDesignated && SemaRef.getLangOpts().CPlusPlus && !hadError) {
+ if (InOverloadResolution)
+ hadError = true;
+ if (!VerifyOnly) {
+ SemaRef.Diag(expr->getBeginLoc(),
+ diag::ext_designated_init_brace_elision)
+ << expr->getSourceRange()
+ << FixItHint::CreateInsertion(expr->getBeginLoc(), "{")
+ << FixItHint::CreateInsertion(
+ SemaRef.getLocForEndOfToken(expr->getEndLoc()), "}");
+ }
+ }
} else {
if (!VerifyOnly) {
// We cannot initialize this element, so let PerformCopyInitialization
@@ -2413,8 +2442,8 @@
unsigned OldIndex = Index;
IList->setInit(OldIndex, DIE->getInit());
- CheckSubElementType(Entity, IList, CurrentObjectType, Index,
- StructuredList, StructuredIndex);
+ CheckSubElementType(Entity, IList, CurrentObjectType, Index, StructuredList,
+ StructuredIndex, /*DirectlyDesignated=*/true);
// Restore the designated initializer expression in the syntactic
// form of the initializer list.
@@ -2844,7 +2873,7 @@
if (!VerifyOnly)
SemaRef.Diag(IndexExpr->getBeginLoc(),
diag::err_array_designator_too_large)
- << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
+ << toString(DesignatedEndIndex, 10) << toString(MaxElements, 10)
<< IndexExpr->getSourceRange();
++Index;
return true;
@@ -2895,9 +2924,9 @@
Expr *Init = new (Context) IntegerLiteral(
Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
if (CharTy != PromotedCharTy)
- Init =
- ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init,
- nullptr, VK_RValue, FPOptionsOverride());
+ Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
+ Init, nullptr, VK_PRValue,
+ FPOptionsOverride());
StructuredList->updateInit(Context, i, Init);
}
} else {
@@ -2918,9 +2947,9 @@
Expr *Init = new (Context) IntegerLiteral(
Context, CodeUnit, PromotedCharTy, SubExpr->getExprLoc());
if (CharTy != PromotedCharTy)
- Init =
- ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast, Init,
- nullptr, VK_RValue, FPOptionsOverride());
+ Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
+ Init, nullptr, VK_PRValue,
+ FPOptionsOverride());
StructuredList->updateInit(Context, i, Init);
}
}
@@ -3138,7 +3167,7 @@
if (Value.isSigned() && Value.isNegative())
return S.Diag(Loc, diag::err_array_designator_negative)
- << Value.toString(10) << Index->getSourceRange();
+ << toString(Value, 10) << Index->getSourceRange();
Value.setIsUnsigned(true);
return Result;
@@ -3207,7 +3236,7 @@
if (!StartDependent && !EndDependent && EndValue < StartValue) {
Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range)
- << StartValue.toString(10) << EndValue.toString(10)
+ << toString(StartValue, 10) << toString(EndValue, 10)
<< StartIndex->getSourceRange() << EndIndex->getSourceRange();
Invalid = true;
} else {
@@ -3265,10 +3294,7 @@
InitializedEntity Result;
Result.Kind = EK_Base;
Result.Parent = Parent;
- Result.Base = reinterpret_cast<uintptr_t>(Base);
- if (IsInheritedVirtualBase)
- Result.Base |= 0x01;
-
+ Result.Base = {Base, IsInheritedVirtualBase};
Result.Type = Base->getType();
return Result;
}
@@ -3277,7 +3303,7 @@
switch (getKind()) {
case EK_Parameter:
case EK_Parameter_CF_Audited: {
- ParmVarDecl *D = reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
+ ParmVarDecl *D = Parameter.getPointer();
return (D ? D->getDeclName() : DeclarationName());
}
@@ -3320,7 +3346,7 @@
case EK_Parameter:
case EK_Parameter_CF_Audited:
- return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
+ return Parameter.getPointer();
case EK_Result:
case EK_StmtExprResult:
@@ -3431,7 +3457,7 @@
void InitializationSequence::Step::Destroy() {
switch (Kind) {
case SK_ResolveAddressOfOverloadedFunction:
- case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBasePRValue:
case SK_CastDerivedToBaseXValue:
case SK_CastDerivedToBaseLValue:
case SK_BindReference:
@@ -3439,7 +3465,7 @@
case SK_FinalCopy:
case SK_ExtraneousCopyToTemporary:
case SK_UserConversion:
- case SK_QualificationConversionRValue:
+ case SK_QualificationConversionPRValue:
case SK_QualificationConversionXValue:
case SK_QualificationConversionLValue:
case SK_FunctionReferenceConversion:
@@ -3558,7 +3584,9 @@
ExprValueKind VK) {
Step S;
switch (VK) {
- case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break;
+ case VK_PRValue:
+ S.Kind = SK_CastDerivedToBasePRValue;
+ break;
case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break;
case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break;
}
@@ -3605,10 +3633,10 @@
void InitializationSequence::AddQualificationConversionStep(QualType Ty,
ExprValueKind VK) {
Step S;
- S.Kind = SK_QualificationConversionRValue; // work around a gcc warning
+ S.Kind = SK_QualificationConversionPRValue; // work around a gcc warning
switch (VK) {
- case VK_RValue:
- S.Kind = SK_QualificationConversionRValue;
+ case VK_PRValue:
+ S.Kind = SK_QualificationConversionPRValue;
break;
case VK_XValue:
S.Kind = SK_QualificationConversionXValue;
@@ -4047,10 +4075,10 @@
Entity.getKind() != InitializedEntity::EK_Delegating &&
Entity.getKind() !=
InitializedEntity::EK_LambdaToBlockConversionBlockElement &&
- UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() &&
+ UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() &&
S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) {
// Convert qualifications if necessary.
- Sequence.AddQualificationConversionStep(DestType, VK_RValue);
+ Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
if (ILE)
Sequence.RewrapReferenceInitList(DestType, ILE);
return;
@@ -4136,7 +4164,7 @@
Sequence.AddUserConversionStep(CD, Best->FoundDecl, ConvType,
HadMultipleCandidates);
if (!S.Context.hasSameType(ConvType, DestType))
- Sequence.AddQualificationConversionStep(DestType, VK_RValue);
+ Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
if (IsListInit)
Sequence.RewrapReferenceInitList(Entity.getType(), ILE);
return;
@@ -4289,17 +4317,36 @@
if (Sequence.step_begin() != Sequence.step_end())
Sequence.RewrapReferenceInitList(cv1T1, InitList);
}
-
+ // Perform address space compatibility check.
+ QualType cv1T1IgnoreAS = cv1T1;
+ if (T1Quals.hasAddressSpace()) {
+ Qualifiers T2Quals;
+ (void)S.Context.getUnqualifiedArrayType(InitList->getType(), T2Quals);
+ if (!T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
+ Sequence.SetFailed(
+ InitializationSequence::FK_ReferenceInitDropsQualifiers);
+ return;
+ }
+ // Ignore address space of reference type at this point and perform address
+ // space conversion after the reference binding step.
+ cv1T1IgnoreAS =
+ S.Context.getQualifiedType(T1, T1Quals.withoutAddressSpace());
+ }
// Not reference-related. Create a temporary and bind to that.
- InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
+ InitializedEntity TempEntity =
+ InitializedEntity::InitializeTemporary(cv1T1IgnoreAS);
TryListInitialization(S, TempEntity, Kind, InitList, Sequence,
TreatUnavailableAsInvalid);
if (Sequence) {
if (DestType->isRValueReferenceType() ||
- (T1Quals.hasConst() && !T1Quals.hasVolatile()))
- Sequence.AddReferenceBindingStep(cv1T1, /*BindingTemporary=*/true);
- else
+ (T1Quals.hasConst() && !T1Quals.hasVolatile())) {
+ Sequence.AddReferenceBindingStep(cv1T1IgnoreAS,
+ /*BindingTemporary=*/true);
+ if (T1Quals.hasAddressSpace())
+ Sequence.AddQualificationConversionStep(
+ cv1T1, DestType->isRValueReferenceType() ? VK_XValue : VK_LValue);
+ } else
Sequence.SetFailed(
InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
}
@@ -4441,7 +4488,7 @@
ImplicitConversionSequence ICS;
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
- if (!E->isRValue())
+ if (!E->isPRValue())
ICS.Standard.First = ICK_Lvalue_To_Rvalue;
// If E is of a floating-point type, then the conversion is ill-formed
// due to narrowing, but go through the motions in order to produce the
@@ -4626,7 +4673,7 @@
else
cv3T3 = T1;
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
if (cv3T3->isLValueReferenceType())
VK = VK_LValue;
else if (const auto *RRef = cv3T3->getAs<RValueReferenceType>())
@@ -4657,7 +4704,7 @@
// Every implicit conversion results in a prvalue, except for a glvalue
// derived-to-base conversion, which we handle below.
cv3T3 = ICS.Standard.getToType(2);
- VK = VK_RValue;
+ VK = VK_PRValue;
}
// If the converted initializer is a prvalue, its type T4 is adjusted to
@@ -4669,7 +4716,7 @@
QualType cv1T4 = S.Context.getQualifiedType(cv3T3, cv1T1.getQualifiers());
if (cv1T4.getQualifiers() != cv3T3.getQualifiers())
Sequence.AddQualificationConversionStep(cv1T4, VK);
- Sequence.AddReferenceBindingStep(cv1T4, VK == VK_RValue);
+ Sequence.AddReferenceBindingStep(cv1T4, VK == VK_PRValue);
VK = IsLValueRef ? VK_LValue : VK_XValue;
if (RefConv & Sema::ReferenceConversions::DerivedToBase)
@@ -4884,7 +4931,7 @@
(InitCategory.isPRValue() &&
(S.getLangOpts().CPlusPlus17 || T2->isRecordType() ||
T2->isArrayType())))) {
- ExprValueKind ValueKind = InitCategory.isXValue() ? VK_XValue : VK_RValue;
+ ExprValueKind ValueKind = InitCategory.isXValue() ? VK_XValue : VK_PRValue;
if (InitCategory.isPRValue() && T2->isRecordType()) {
// The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
// compiler the freedom to perform a copy here or bind to the
@@ -4916,7 +4963,7 @@
QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1QualsIgnoreAS);
if (T1QualsIgnoreAS != T2QualsIgnoreAS)
Sequence.AddQualificationConversionStep(cv1T4, ValueKind);
- Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue);
+ Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_PRValue);
ValueKind = isLValueRef ? VK_LValue : VK_XValue;
// Add addr space conversion if required.
if (T1Quals.getAddressSpace() != T2Quals.getAddressSpace()) {
@@ -5018,9 +5065,9 @@
// than, cv2; otherwise, the program is ill-formed.
unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
- if ((RefRelationship == Sema::Ref_Related &&
- (T1CVRQuals | T2CVRQuals) != T1CVRQuals) ||
- !T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
+ if (RefRelationship == Sema::Ref_Related &&
+ ((T1CVRQuals | T2CVRQuals) != T1CVRQuals ||
+ !T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
return;
}
@@ -5319,7 +5366,7 @@
if (!S.getLangOpts().CPlusPlus17)
Sequence.AddFinalCopy(DestType);
else if (DestType.hasQualifiers())
- Sequence.AddQualificationConversionStep(DestType, VK_RValue);
+ Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
return;
}
@@ -5343,7 +5390,7 @@
!S.Context.hasSameUnqualifiedType(ConvType, DestType))
Sequence.AddFinalCopy(DestType);
else if (!S.Context.hasSameType(ConvType, DestType))
- Sequence.AddQualificationConversionStep(DestType, VK_RValue);
+ Sequence.AddQualificationConversionStep(DestType, VK_PRValue);
return;
}
@@ -5448,7 +5495,7 @@
/// Check whether the given expression is a valid operand for an
/// indirect copy/restore.
static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
- assert(src->isRValue());
+ assert(src->isPRValue());
bool isWeakAccess = false;
InvalidICRKind iik = isInvalidICRSource(S.Context, src, false, isWeakAccess);
// If isWeakAccess to true, there will be an implicit
@@ -5572,8 +5619,8 @@
// We should allow zero initialization for all types defined in the
// cl_intel_device_side_avc_motion_estimation extension, except
// intel_sub_group_avc_mce_payload_t and intel_sub_group_avc_mce_result_t.
- if (S.getOpenCLOptions().isEnabled(
- "cl_intel_device_side_avc_motion_estimation") &&
+ if (S.getOpenCLOptions().isAvailableOption(
+ "cl_intel_device_side_avc_motion_estimation", S.getLangOpts()) &&
DestType->isOCLIntelSubgroupAVCType()) {
if (DestType->isOCLIntelSubgroupAVCMcePayloadType() ||
DestType->isOCLIntelSubgroupAVCMceResultType())
@@ -5785,7 +5832,7 @@
Entity.getType()) &&
canPerformArrayCopy(Entity)) {
// If source is a prvalue, use it directly.
- if (Initializer->getValueKind() == VK_RValue) {
+ if (Initializer->isPRValue()) {
AddArrayInitStep(DestType, /*IsGNUExtension*/false);
return;
}
@@ -6284,7 +6331,8 @@
// Determine the arguments required to actually perform the
// constructor call (we might have derived-to-base conversions, or
// the copy constructor may have default arguments).
- if (S.CompleteConstructorCall(Constructor, CurInitExpr, Loc, ConstructorArgs))
+ if (S.CompleteConstructorCall(Constructor, T, CurInitExpr, Loc,
+ ConstructorArgs))
return ExprError();
// C++0x [class.copy]p32:
@@ -6481,13 +6529,11 @@
// Determine the arguments required to actually perform the constructor
// call.
- if (S.CompleteConstructorCall(Constructor, Args,
- Loc, ConstructorArgs,
- AllowExplicitConv,
+ if (S.CompleteConstructorCall(Constructor, Step.Type, Args, Loc,
+ ConstructorArgs, AllowExplicitConv,
IsListInitialization))
return ExprError();
-
if (isExplicitTemporary(Entity, Kind, NumArgs)) {
// An explicitly-constructed temporary, e.g., X(1, 2).
if (S.DiagnoseUseOfDecl(Constructor, Loc))
@@ -6501,22 +6547,23 @@
? SourceRange(LBraceLoc, RBraceLoc)
: Kind.getParenOrBraceRange();
+ CXXConstructorDecl *CalleeDecl = Constructor;
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(
Step.Function.FoundDecl.getDecl())) {
- Constructor = S.findInheritingConstructor(Loc, Constructor, Shadow);
- if (S.DiagnoseUseOfDecl(Constructor, Loc))
+ CalleeDecl = S.findInheritingConstructor(Loc, Constructor, Shadow);
+ if (S.DiagnoseUseOfDecl(CalleeDecl, Loc))
return ExprError();
}
- S.MarkFunctionReferenced(Loc, Constructor);
+ S.MarkFunctionReferenced(Loc, CalleeDecl);
CurInit = S.CheckForImmediateInvocation(
CXXTemporaryObjectExpr::Create(
- S.Context, Constructor,
+ S.Context, CalleeDecl,
Entity.getType().getNonLValueExprType(S.Context), TSInfo,
ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates,
IsListInitialization, IsStdInitListInitialization,
ConstructorInitRequiresZeroInit),
- Constructor);
+ CalleeDecl);
} else {
CXXConstructExpr::ConstructionKind ConstructKind =
CXXConstructExpr::CK_Complete;
@@ -7485,6 +7532,8 @@
continue;
if (It->Kind == IndirectLocalPathEntry::AddressOf)
continue;
+ if (It->Kind == IndirectLocalPathEntry::LifetimeBoundCall)
+ continue;
return It->Kind == IndirectLocalPathEntry::GslPointerInit ||
It->Kind == IndirectLocalPathEntry::GslReferenceInit;
}
@@ -7833,7 +7882,7 @@
} else {
DiagID = diag::warn_pessimizing_move_on_initialization;
const Expr *ArgStripped = Arg->IgnoreImplicit()->IgnoreParens();
- if (!ArgStripped->isRValue() || !ArgStripped->getType()->isRecordType())
+ if (!ArgStripped->isPRValue() || !ArgStripped->getType()->isRecordType())
return;
}
@@ -7903,7 +7952,7 @@
// FIXME: This means that AST consumers need to deal with "prvalues" that
// denote materialized temporaries. Maybe we should add another ValueKind
// for "xvalue pretending to be a prvalue" for C++98 support.
- if (!E->isRValue() || !getLangOpts().CPlusPlus11)
+ if (!E->isPRValue() || !getLangOpts().CPlusPlus11)
return E;
// C++1z [conv.rval]/1: T shall be a complete type.
@@ -7922,7 +7971,7 @@
CastKind CK = CK_NoOp;
- if (VK == VK_RValue) {
+ if (VK == VK_PRValue) {
auto PointeeTy = Ty->getPointeeType();
auto ExprPointeeTy = E->getType()->getPointeeType();
if (!PointeeTy.isNull() &&
@@ -8057,7 +8106,7 @@
// initializer.
switch (Steps.front().Kind) {
case SK_ResolveAddressOfOverloadedFunction:
- case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBasePRValue:
case SK_CastDerivedToBaseXValue:
case SK_CastDerivedToBaseLValue:
case SK_BindReference:
@@ -8067,7 +8116,7 @@
case SK_UserConversion:
case SK_QualificationConversionLValue:
case SK_QualificationConversionXValue:
- case SK_QualificationConversionRValue:
+ case SK_QualificationConversionPRValue:
case SK_FunctionReferenceConversion:
case SK_AtomicConversion:
case SK_ConversionSequence:
@@ -8142,7 +8191,7 @@
Step->Function.Function);
break;
- case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBasePRValue:
case SK_CastDerivedToBaseXValue:
case SK_CastDerivedToBaseLValue: {
// We have a derived-to-base cast that produces either an rvalue or an
@@ -8158,11 +8207,10 @@
return ExprError();
ExprValueKind VK =
- Step->Kind == SK_CastDerivedToBaseLValue ?
- VK_LValue :
- (Step->Kind == SK_CastDerivedToBaseXValue ?
- VK_XValue :
- VK_RValue);
+ Step->Kind == SK_CastDerivedToBaseLValue
+ ? VK_LValue
+ : (Step->Kind == SK_CastDerivedToBaseXValue ? VK_XValue
+ : VK_PRValue);
CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
CK_DerivedToBase, CurInit.get(),
&BasePath, VK, FPOptionsOverride());
@@ -8194,7 +8242,7 @@
case SK_BindReferenceToTemporary: {
// Make sure the "temporary" is actually an rvalue.
- assert(CurInit.get()->isRValue() && "not a temporary");
+ assert(CurInit.get()->isPRValue() && "not a temporary");
// Check exception specifications
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
@@ -8261,9 +8309,9 @@
// Determine the arguments required to actually perform the constructor
// call.
Expr *Arg = CurInit.get();
- if (S.CompleteConstructorCall(Constructor,
- MultiExprArg(&Arg, 1),
- Loc, ConstructorArgs))
+ if (S.CompleteConstructorCall(Constructor, Step->Type,
+ MultiExprArg(&Arg, 1), Loc,
+ ConstructorArgs))
return ExprError();
// Build an expression that constructs a temporary.
@@ -8335,13 +8383,13 @@
case SK_QualificationConversionLValue:
case SK_QualificationConversionXValue:
- case SK_QualificationConversionRValue: {
+ case SK_QualificationConversionPRValue: {
// Perform a qualification conversion; these can never go wrong.
ExprValueKind VK =
Step->Kind == SK_QualificationConversionLValue
? VK_LValue
: (Step->Kind == SK_QualificationConversionXValue ? VK_XValue
- : VK_RValue);
+ : VK_PRValue);
CurInit = S.PerformQualificationConversion(CurInit.get(), Step->Type, VK);
break;
}
@@ -8354,9 +8402,9 @@
break;
case SK_AtomicConversion: {
- assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic");
+ assert(CurInit.get()->isPRValue() && "cannot convert glvalue to atomic");
CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
- CK_NonAtomicToAtomic, VK_RValue);
+ CK_NonAtomicToAtomic, VK_PRValue);
break;
}
@@ -8659,7 +8707,7 @@
case SK_ProduceObjCObject:
CurInit = ImplicitCastExpr::Create(
S.Context, Step->Type, CK_ARCProduceObject, CurInit.get(), nullptr,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
break;
case SK_StdInitializerList: {
@@ -8715,7 +8763,7 @@
if (!Var->hasGlobalStorage()) {
CurInit = ImplicitCastExpr::Create(
S.Context, Step->Type, CK_LValueToRValue, Init,
- /*BasePath=*/nullptr, VK_RValue, FPOptionsOverride());
+ /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
break;
}
// Case 1a
@@ -8758,8 +8806,8 @@
unsigned AddressingMode = (0x0E & SamplerValue) >> 1;
unsigned FilterMode = (0x30 & SamplerValue) >> 4;
if (FilterMode != 1 && FilterMode != 2 &&
- !S.getOpenCLOptions().isEnabled(
- "cl_intel_device_side_avc_motion_estimation"))
+ !S.getOpenCLOptions().isAvailableOption(
+ "cl_intel_device_side_avc_motion_estimation", S.getLangOpts()))
S.Diag(Kind.getLocation(),
diag::warn_sampler_initializer_invalid_bits)
<< "Filter Mode";
@@ -9569,8 +9617,8 @@
OS << "resolve address of overloaded function";
break;
- case SK_CastDerivedToBaseRValue:
- OS << "derived-to-base (rvalue)";
+ case SK_CastDerivedToBasePRValue:
+ OS << "derived-to-base (prvalue)";
break;
case SK_CastDerivedToBaseXValue:
@@ -9601,8 +9649,8 @@
OS << "user-defined conversion via " << *S->Function.Function;
break;
- case SK_QualificationConversionRValue:
- OS << "qualification conversion (rvalue)";
+ case SK_QualificationConversionPRValue:
+ OS << "qualification conversion (prvalue)";
break;
case SK_QualificationConversionXValue:
diff --git a/src/llvm-project/clang/lib/Sema/SemaLambda.cpp b/src/llvm-project/clang/lib/Sema/SemaLambda.cpp
index c1c6a4b..eb1e9c3 100644
--- a/src/llvm-project/clang/lib/Sema/SemaLambda.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaLambda.cpp
@@ -386,11 +386,8 @@
// trailing-return-type respectively.
DeclarationName MethodName
= Context.DeclarationNames.getCXXOperatorName(OO_Call);
- DeclarationNameLoc MethodNameLoc;
- MethodNameLoc.CXXOperatorName.BeginOpNameLoc
- = IntroducerRange.getBegin().getRawEncoding();
- MethodNameLoc.CXXOperatorName.EndOpNameLoc
- = IntroducerRange.getEnd().getRawEncoding();
+ DeclarationNameLoc MethodNameLoc =
+ DeclarationNameLoc::makeCXXOperatorNameLoc(IntroducerRange);
CXXMethodDecl *Method = CXXMethodDecl::Create(
Context, Class, EndLoc,
DeclarationNameInfo(MethodName, IntroducerRange.getBegin(),
@@ -464,11 +461,15 @@
std::tie(MCtx, ManglingContextDecl) =
getCurrentMangleNumberContext(Class->getDeclContext());
bool HasKnownInternalLinkage = false;
- if (!MCtx && getLangOpts().CUDA) {
+ if (!MCtx && (getLangOpts().CUDA || getLangOpts().SYCLIsDevice ||
+ getLangOpts().SYCLIsHost)) {
// Force lambda numbering in CUDA/HIP as we need to name lambdas following
// ODR. Both device- and host-compilation need to have a consistent naming
// on kernel functions. As lambdas are potential part of these `__global__`
// function names, they needs numbering following ODR.
+ // Also force for SYCL, since we need this for the
+ // __builtin_sycl_unique_stable_name implementation, which depends on lambda
+ // mangling.
MCtx = getMangleNumberingContext(Class, ManglingContextDecl);
assert(MCtx && "Retrieving mangle numbering context failed!");
HasKnownInternalLinkage = true;
@@ -685,7 +686,7 @@
Expr *E = (cleanups ? cleanups->getSubExpr() : retValue);
E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, E,
- /*base path*/ nullptr, VK_RValue,
+ /*base path*/ nullptr, VK_PRValue,
FPOptionsOverride());
if (cleanups) {
cleanups->setSubExpr(E);
@@ -1380,7 +1381,6 @@
DeclarationName ConversionName
= S.Context.DeclarationNames.getCXXConversionFunctionName(
S.Context.getCanonicalType(PtrToFunctionTy));
- DeclarationNameLoc ConvNameLoc;
// Construct a TypeSourceInfo for the conversion function, and wire
// all the parameters appropriately for the FunctionProtoTypeLoc
// so that everything works during transformation/instantiation of
@@ -1399,7 +1399,8 @@
// operators ParmVarDecls below.
TypeSourceInfo *ConvNamePtrToFunctionTSI =
S.Context.getTrivialTypeSourceInfo(PtrToFunctionTy, Loc);
- ConvNameLoc.NamedType.TInfo = ConvNamePtrToFunctionTSI;
+ DeclarationNameLoc ConvNameLoc =
+ DeclarationNameLoc::makeNamedTypeLoc(ConvNamePtrToFunctionTSI);
// The conversion function is a conversion to a pointer-to-function.
TypeSourceInfo *ConvTSI = S.Context.getTrivialTypeSourceInfo(ConvTy, Loc);
@@ -1550,8 +1551,8 @@
DeclarationName Name
= S.Context.DeclarationNames.getCXXConversionFunctionName(
S.Context.getCanonicalType(BlockPtrTy));
- DeclarationNameLoc NameLoc;
- NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc);
+ DeclarationNameLoc NameLoc = DeclarationNameLoc::makeNamedTypeLoc(
+ S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc));
CXXConversionDecl *Conversion = CXXConversionDecl::Create(
S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy,
S.Context.getTrivialTypeSourceInfo(ConvTy, Loc),
diff --git a/src/llvm-project/clang/lib/Sema/SemaLookup.cpp b/src/llvm-project/clang/lib/Sema/SemaLookup.cpp
index 29038ab..5e8c4de 100644
--- a/src/llvm-project/clang/lib/Sema/SemaLookup.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaLookup.cpp
@@ -638,8 +638,8 @@
void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) {
CXXBasePaths::const_paths_iterator I, E;
for (I = P.begin(), E = P.end(); I != E; ++I)
- for (DeclContext::lookup_iterator DI = I->Decls.begin(),
- DE = I->Decls.end(); DI != DE; ++DI)
+ for (DeclContext::lookup_iterator DI = I->Decls, DE = DI.end(); DI != DE;
+ ++DI)
addDecl(*DI);
}
@@ -677,9 +677,43 @@
D->dump();
}
+/// Diagnose a missing builtin type.
+static QualType diagOpenCLBuiltinTypeError(Sema &S, llvm::StringRef TypeClass,
+ llvm::StringRef Name) {
+ S.Diag(SourceLocation(), diag::err_opencl_type_not_found)
+ << TypeClass << Name;
+ return S.Context.VoidTy;
+}
+
+/// Lookup an OpenCL enum type.
+static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name) {
+ LookupResult Result(S, &S.Context.Idents.get(Name), SourceLocation(),
+ Sema::LookupTagName);
+ S.LookupName(Result, S.TUScope);
+ if (Result.empty())
+ return diagOpenCLBuiltinTypeError(S, "enum", Name);
+ EnumDecl *Decl = Result.getAsSingle<EnumDecl>();
+ if (!Decl)
+ return diagOpenCLBuiltinTypeError(S, "enum", Name);
+ return S.Context.getEnumType(Decl);
+}
+
+/// Lookup an OpenCL typedef type.
+static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name) {
+ LookupResult Result(S, &S.Context.Idents.get(Name), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ S.LookupName(Result, S.TUScope);
+ if (Result.empty())
+ return diagOpenCLBuiltinTypeError(S, "typedef", Name);
+ TypedefNameDecl *Decl = Result.getAsSingle<TypedefNameDecl>();
+ if (!Decl)
+ return diagOpenCLBuiltinTypeError(S, "typedef", Name);
+ return S.Context.getTypedefType(Decl);
+}
+
/// Get the QualType instances of the return type and arguments for an OpenCL
/// builtin function signature.
-/// \param Context (in) The Context instance.
+/// \param S (in) The Sema instance.
/// \param OpenCLBuiltin (in) The signature currently handled.
/// \param GenTypeMaxCnt (out) Maximum number of types contained in a generic
/// type used as return type or as argument.
@@ -689,20 +723,20 @@
/// argument, ArgTypes contains QualTypes for the Cartesian product
/// of (vector sizes) x (types) .
static void GetQualTypesForOpenCLBuiltin(
- ASTContext &Context, const OpenCLBuiltinStruct &OpenCLBuiltin,
- unsigned &GenTypeMaxCnt, SmallVector<QualType, 1> &RetTypes,
+ Sema &S, const OpenCLBuiltinStruct &OpenCLBuiltin, unsigned &GenTypeMaxCnt,
+ SmallVector<QualType, 1> &RetTypes,
SmallVector<SmallVector<QualType, 1>, 5> &ArgTypes) {
// Get the QualType instances of the return types.
unsigned Sig = SignatureTable[OpenCLBuiltin.SigTableIndex];
- OCL2Qual(Context, TypeTable[Sig], RetTypes);
+ OCL2Qual(S, TypeTable[Sig], RetTypes);
GenTypeMaxCnt = RetTypes.size();
// Get the QualType instances of the arguments.
// First type is the return type, skip it.
for (unsigned Index = 1; Index < OpenCLBuiltin.NumTypes; Index++) {
SmallVector<QualType, 1> Ty;
- OCL2Qual(Context,
- TypeTable[SignatureTable[OpenCLBuiltin.SigTableIndex + Index]], Ty);
+ OCL2Qual(S, TypeTable[SignatureTable[OpenCLBuiltin.SigTableIndex + Index]],
+ Ty);
GenTypeMaxCnt = (Ty.size() > GenTypeMaxCnt) ? Ty.size() : GenTypeMaxCnt;
ArgTypes.push_back(std::move(Ty));
}
@@ -721,14 +755,24 @@
ASTContext &Context, unsigned GenTypeMaxCnt,
std::vector<QualType> &FunctionList, SmallVector<QualType, 1> &RetTypes,
SmallVector<SmallVector<QualType, 1>, 5> &ArgTypes) {
- FunctionProtoType::ExtProtoInfo PI;
+ FunctionProtoType::ExtProtoInfo PI(
+ Context.getDefaultCallingConvention(false, false, true));
PI.Variadic = false;
+ // Do not attempt to create any FunctionTypes if there are no return types,
+ // which happens when a type belongs to a disabled extension.
+ if (RetTypes.size() == 0)
+ return;
+
// Create FunctionTypes for each (gen)type.
for (unsigned IGenType = 0; IGenType < GenTypeMaxCnt; IGenType++) {
SmallVector<QualType, 5> ArgList;
for (unsigned A = 0; A < ArgTypes.size(); A++) {
+ // Bail out if there is an argument that has no available types.
+ if (ArgTypes[A].size() == 0)
+ return;
+
// Builtins such as "max" have an "sgentype" argument that represents
// the corresponding scalar type of a gentype. The number of gentypes
// must be a multiple of the number of sgentypes.
@@ -743,18 +787,6 @@
}
}
-/// Add extensions to the function declaration.
-/// \param S (in/out) The Sema instance.
-/// \param BIDecl (in) Description of the builtin.
-/// \param FDecl (in/out) FunctionDecl instance.
-static void AddOpenCLExtensions(Sema &S, const OpenCLBuiltinStruct &BIDecl,
- FunctionDecl *FDecl) {
- // Fetch extension associated with a function prototype.
- StringRef E = FunctionExtensionTable[BIDecl.Extension];
- if (E != "")
- S.setOpenCLExtensionForDecl(FDecl, E);
-}
-
/// When trying to resolve a function name, if isOpenCLBuiltin() returns a
/// non-null <Index, Len> pair, then the name is referencing an OpenCL
/// builtin function. Add all candidate signatures to the LookUpResult.
@@ -775,27 +807,42 @@
// as argument. Only meaningful for generic types, otherwise equals 1.
unsigned GenTypeMaxCnt;
+ ASTContext &Context = S.Context;
+
for (unsigned SignatureIndex = 0; SignatureIndex < Len; SignatureIndex++) {
const OpenCLBuiltinStruct &OpenCLBuiltin =
BuiltinTable[FctIndex + SignatureIndex];
- ASTContext &Context = S.Context;
- // Ignore this BIF if its version does not match the language options.
- unsigned OpenCLVersion = Context.getLangOpts().OpenCLVersion;
- if (Context.getLangOpts().OpenCLCPlusPlus)
- OpenCLVersion = 200;
- if (OpenCLVersion < OpenCLBuiltin.MinVersion)
+ // Ignore this builtin function if it is not available in the currently
+ // selected language version.
+ if (!isOpenCLVersionContainedInMask(Context.getLangOpts(),
+ OpenCLBuiltin.Versions))
continue;
- if ((OpenCLBuiltin.MaxVersion != 0) &&
- (OpenCLVersion >= OpenCLBuiltin.MaxVersion))
- continue;
+
+ // Ignore this builtin function if it carries an extension macro that is
+ // not defined. This indicates that the extension is not supported by the
+ // target, so the builtin function should not be available.
+ StringRef Extensions = FunctionExtensionTable[OpenCLBuiltin.Extension];
+ if (!Extensions.empty()) {
+ SmallVector<StringRef, 2> ExtVec;
+ Extensions.split(ExtVec, " ");
+ bool AllExtensionsDefined = true;
+ for (StringRef Ext : ExtVec) {
+ if (!S.getPreprocessor().isMacroDefined(Ext)) {
+ AllExtensionsDefined = false;
+ break;
+ }
+ }
+ if (!AllExtensionsDefined)
+ continue;
+ }
SmallVector<QualType, 1> RetTypes;
SmallVector<SmallVector<QualType, 1>, 5> ArgTypes;
// Obtain QualType lists for the function signature.
- GetQualTypesForOpenCLBuiltin(Context, OpenCLBuiltin, GenTypeMaxCnt,
- RetTypes, ArgTypes);
+ GetQualTypesForOpenCLBuiltin(S, OpenCLBuiltin, GenTypeMaxCnt, RetTypes,
+ ArgTypes);
if (GenTypeMaxCnt > 1) {
HasGenType = true;
}
@@ -809,28 +856,24 @@
DeclContext *Parent = Context.getTranslationUnitDecl();
FunctionDecl *NewOpenCLBuiltin;
- for (unsigned Index = 0; Index < GenTypeMaxCnt; Index++) {
+ for (const auto &FTy : FunctionList) {
NewOpenCLBuiltin = FunctionDecl::Create(
- Context, Parent, Loc, Loc, II, FunctionList[Index],
- /*TInfo=*/nullptr, SC_Extern, false,
- FunctionList[Index]->isFunctionProtoType());
+ Context, Parent, Loc, Loc, II, FTy, /*TInfo=*/nullptr, SC_Extern,
+ false, FTy->isFunctionProtoType());
NewOpenCLBuiltin->setImplicit();
// Create Decl objects for each parameter, adding them to the
// FunctionDecl.
- if (const FunctionProtoType *FP =
- dyn_cast<FunctionProtoType>(FunctionList[Index])) {
- SmallVector<ParmVarDecl *, 16> ParmList;
- for (unsigned IParm = 0, e = FP->getNumParams(); IParm != e; ++IParm) {
- ParmVarDecl *Parm = ParmVarDecl::Create(
- Context, NewOpenCLBuiltin, SourceLocation(), SourceLocation(),
- nullptr, FP->getParamType(IParm),
- /*TInfo=*/nullptr, SC_None, nullptr);
- Parm->setScopeInfo(0, IParm);
- ParmList.push_back(Parm);
- }
- NewOpenCLBuiltin->setParams(ParmList);
+ const auto *FP = cast<FunctionProtoType>(FTy);
+ SmallVector<ParmVarDecl *, 4> ParmList;
+ for (unsigned IParm = 0, e = FP->getNumParams(); IParm != e; ++IParm) {
+ ParmVarDecl *Parm = ParmVarDecl::Create(
+ Context, NewOpenCLBuiltin, SourceLocation(), SourceLocation(),
+ nullptr, FP->getParamType(IParm), nullptr, SC_None, nullptr);
+ Parm->setScopeInfo(0, IParm);
+ ParmList.push_back(Parm);
}
+ NewOpenCLBuiltin->setParams(ParmList);
// Add function attributes.
if (OpenCLBuiltin.IsPure)
@@ -843,8 +886,6 @@
if (!S.getLangOpts().OpenCLCPlusPlus)
NewOpenCLBuiltin->addAttr(OverloadableAttr::CreateImplicit(Context));
- AddOpenCLExtensions(S, OpenCLBuiltin, NewOpenCLBuiltin);
-
LR.addDecl(NewOpenCLBuiltin);
}
}
@@ -2191,9 +2232,9 @@
CXXRecordDecl *BaseRecord = Specifier->getType()->getAsCXXRecordDecl();
// Drop leading non-matching lookup results from the declaration list so
// we don't need to consider them again below.
- for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
- Path.Decls = Path.Decls.slice(1)) {
- if (Path.Decls.front()->isInIdentifierNamespace(IDNS))
+ for (Path.Decls = BaseRecord->lookup(Name).begin();
+ Path.Decls != Path.Decls.end(); ++Path.Decls) {
+ if ((*Path.Decls)->isInIdentifierNamespace(IDNS))
return true;
}
return false;
@@ -2217,9 +2258,9 @@
AccessSpecifier SubobjectAccess = AS_none;
// Check whether the given lookup result contains only static members.
- auto HasOnlyStaticMembers = [&](DeclContextLookupResult Result) {
- for (NamedDecl *ND : Result)
- if (ND->isInIdentifierNamespace(IDNS) && ND->isCXXInstanceMember())
+ auto HasOnlyStaticMembers = [&](DeclContext::lookup_iterator Result) {
+ for (DeclContext::lookup_iterator I = Result, E = I.end(); I != E; ++I)
+ if ((*I)->isInIdentifierNamespace(IDNS) && (*I)->isCXXInstanceMember())
return false;
return true;
};
@@ -2228,8 +2269,8 @@
// Determine whether two sets of members contain the same members, as
// required by C++ [class.member.lookup]p6.
- auto HasSameDeclarations = [&](DeclContextLookupResult A,
- DeclContextLookupResult B) {
+ auto HasSameDeclarations = [&](DeclContext::lookup_iterator A,
+ DeclContext::lookup_iterator B) {
using Iterator = DeclContextLookupResult::iterator;
using Result = const void *;
@@ -2266,7 +2307,7 @@
// We'll often find the declarations are in the same order. Handle this
// case (and the special case of only one declaration) efficiently.
- Iterator AIt = A.begin(), BIt = B.begin(), AEnd = A.end(), BEnd = B.end();
+ Iterator AIt = A, BIt = B, AEnd, BEnd;
while (true) {
Result AResult = Next(AIt, AEnd);
Result BResult = Next(BIt, BEnd);
@@ -2349,10 +2390,11 @@
// Lookup in a base class succeeded; return these results.
- for (auto *D : Paths.front().Decls) {
+ for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
+ I != E; ++I) {
AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess,
- D->getAccess());
- if (NamedDecl *ND = R.getAcceptableDecl(D))
+ (*I)->getAccess());
+ if (NamedDecl *ND = R.getAcceptableDecl(*I))
R.addDecl(ND, AS);
}
R.resolveKind();
@@ -2495,7 +2537,7 @@
<< Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths)
<< LookupRange;
- DeclContext::lookup_iterator Found = Paths->front().Decls.begin();
+ DeclContext::lookup_iterator Found = Paths->front().Decls;
while (isa<CXXMethodDecl>(*Found) &&
cast<CXXMethodDecl>(*Found)->isStatic())
++Found;
@@ -2513,7 +2555,7 @@
for (CXXBasePaths::paths_iterator Path = Paths->begin(),
PathEnd = Paths->end();
Path != PathEnd; ++Path) {
- const NamedDecl *D = Path->Decls.front();
+ const NamedDecl *D = *Path->Decls;
if (!D->isInIdentifierNamespace(Result.getIdentifierNamespace()))
continue;
if (DeclsPrinted.insert(D).second) {
@@ -3117,7 +3159,7 @@
ArgType.addVolatile();
// This isn't /really/ specified by the standard, but it's implied
- // we should be working from an RValue in the case of move to ensure
+ // we should be working from a PRValue in the case of move to ensure
// that we prefer to bind to rvalue references, and an LValue in the
// case of copy to ensure we don't bind to rvalue references.
// Possibly an XValue is actually correct in the case of move, but
@@ -3126,7 +3168,7 @@
if (SM == CXXCopyConstructor || SM == CXXCopyAssignment)
VK = VK_LValue;
else
- VK = VK_RValue;
+ VK = VK_PRValue;
}
OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK);
@@ -3143,8 +3185,8 @@
if (VolatileThis)
ThisTy.addVolatile();
Expr::Classification Classification =
- OpaqueValueExpr(LookupLoc, ThisTy,
- RValueThis ? VK_RValue : VK_LValue).Classify(Context);
+ OpaqueValueExpr(LookupLoc, ThisTy, RValueThis ? VK_PRValue : VK_LValue)
+ .Classify(Context);
// Now we perform lookup on the name we computed earlier and do overload
// resolution. Lookup is only performed directly into the class since there
@@ -3690,7 +3732,7 @@
// A shadow declaration that's created by a resolved using declaration
// is not hidden by the same using declaration.
if (isa<UsingShadowDecl>(ND) && isa<UsingDecl>(D) &&
- cast<UsingShadowDecl>(ND)->getUsingDecl() == D)
+ cast<UsingShadowDecl>(ND)->getIntroducer() == D)
continue;
// We've found a declaration that hides this one.
@@ -3793,6 +3835,7 @@
if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
Result.getSema().ForceDeclarationOfImplicitMembers(Class);
+ llvm::SmallVector<NamedDecl *, 4> DeclsToVisit;
// We sometimes skip loading namespace-level results (they tend to be huge).
bool Load = LoadExternal ||
!(isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx));
@@ -3802,12 +3845,21 @@
: Ctx->noload_lookups(/*PreserveInternalState=*/false)) {
for (auto *D : R) {
if (auto *ND = Result.getAcceptableDecl(D)) {
- Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
- Visited.add(ND);
+ // Rather than visit immediatelly, we put ND into a vector and visit
+ // all decls, in order, outside of this loop. The reason is that
+ // Consumer.FoundDecl() may invalidate the iterators used in the two
+ // loops above.
+ DeclsToVisit.push_back(ND);
}
}
}
+ for (auto *ND : DeclsToVisit) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+ Visited.add(ND);
+ }
+ DeclsToVisit.clear();
+
// Traverse using directives for qualified name lookup.
if (QualifiedNameLookup) {
ShadowContextRAII Shadow(Visited);
diff --git a/src/llvm-project/clang/lib/Sema/SemaObjCProperty.cpp b/src/llvm-project/clang/lib/Sema/SemaObjCProperty.cpp
index fdc30fe..a329d0f 100644
--- a/src/llvm-project/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaObjCProperty.cpp
@@ -112,12 +112,10 @@
return;
// Look for a property with the same name.
- DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName());
- for (unsigned I = 0, N = R.size(); I != N; ++I) {
- if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
- S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true);
- return;
- }
+ if (ObjCPropertyDecl *ProtoProp =
+ Proto->lookup(Prop->getDeclName()).find_first<ObjCPropertyDecl>()) {
+ S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true);
+ return;
}
// Check this property against any protocols we inherit.
@@ -233,18 +231,13 @@
bool FoundInSuper = false;
ObjCInterfaceDecl *CurrentInterfaceDecl = IFace;
while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) {
- DeclContext::lookup_result R = Super->lookup(Res->getDeclName());
- for (unsigned I = 0, N = R.size(); I != N; ++I) {
- if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
- DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
- FoundInSuper = true;
- break;
- }
- }
- if (FoundInSuper)
+ if (ObjCPropertyDecl *SuperProp =
+ Super->lookup(Res->getDeclName()).find_first<ObjCPropertyDecl>()) {
+ DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
+ FoundInSuper = true;
break;
- else
- CurrentInterfaceDecl = Super;
+ }
+ CurrentInterfaceDecl = Super;
}
if (FoundInSuper) {
@@ -1149,14 +1142,13 @@
// redeclared 'readwrite', then no warning is to be issued.
for (auto *Ext : IDecl->known_extensions()) {
DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
- if (!R.empty())
- if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) {
- PIkind = ExtProp->getPropertyAttributesAsWritten();
- if (PIkind & ObjCPropertyAttribute::kind_readwrite) {
- ReadWriteProperty = true;
- break;
- }
+ if (auto *ExtProp = R.find_first<ObjCPropertyDecl>()) {
+ PIkind = ExtProp->getPropertyAttributesAsWritten();
+ if (PIkind & ObjCPropertyAttribute::kind_readwrite) {
+ ReadWriteProperty = true;
+ break;
}
+ }
}
if (!ReadWriteProperty) {
@@ -1466,7 +1458,7 @@
MarkDeclRefReferenced(SelfExpr);
Expr *LoadSelfExpr = ImplicitCastExpr::Create(
Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
Expr *IvarRefExpr =
new (Context) ObjCIvarRefExpr(Ivar,
Ivar->getUsageType(SelfDecl->getType()),
@@ -1529,7 +1521,7 @@
MarkDeclRefReferenced(SelfExpr);
Expr *LoadSelfExpr = ImplicitCastExpr::Create(
Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
Expr *lhs =
new (Context) ObjCIvarRefExpr(Ivar,
Ivar->getUsageType(SelfDecl->getType()),
diff --git a/src/llvm-project/clang/lib/Sema/SemaOpenMP.cpp b/src/llvm-project/clang/lib/Sema/SemaOpenMP.cpp
index 4063c18..c0cd2bf 100644
--- a/src/llvm-project/clang/lib/Sema/SemaOpenMP.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaOpenMP.cpp
@@ -1939,20 +1939,23 @@
FunctionDecl *FD) {
assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice &&
"Expected OpenMP host compilation.");
- FunctionEmissionStatus FES = getEmissionStatus(FD);
+
SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
- switch (FES) {
- case FunctionEmissionStatus::Emitted:
- Kind = SemaDiagnosticBuilder::K_Immediate;
- break;
- case FunctionEmissionStatus::Unknown:
- Kind = SemaDiagnosticBuilder::K_Deferred;
- break;
- case FunctionEmissionStatus::TemplateDiscarded:
- case FunctionEmissionStatus::OMPDiscarded:
- case FunctionEmissionStatus::CUDADiscarded:
- Kind = SemaDiagnosticBuilder::K_Nop;
- break;
+ if (FD) {
+ FunctionEmissionStatus FES = getEmissionStatus(FD);
+ switch (FES) {
+ case FunctionEmissionStatus::Emitted:
+ Kind = SemaDiagnosticBuilder::K_Immediate;
+ break;
+ case FunctionEmissionStatus::Unknown:
+ Kind = SemaDiagnosticBuilder::K_Deferred;
+ break;
+ case FunctionEmissionStatus::TemplateDiscarded:
+ case FunctionEmissionStatus::OMPDiscarded:
+ case FunctionEmissionStatus::CUDADiscarded:
+ Kind = SemaDiagnosticBuilder::K_Nop;
+ break;
+ }
}
return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this);
@@ -2184,15 +2187,11 @@
//
if (VD && !VD->hasLocalStorage() &&
(getCurCapturedRegion() || getCurBlock() || getCurLambda())) {
- if (isInOpenMPDeclareTargetContext()) {
- // Try to mark variable as declare target if it is used in capturing
- // regions.
- if (LangOpts.OpenMP <= 45 &&
- !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
- checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
- return nullptr;
- }
if (isInOpenMPTargetExecutionDirective()) {
+ DSAStackTy::DSAVarData DVarTop =
+ DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
+ if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
+ return VD;
// If the declaration is enclosed in a 'declare target' directive,
// then it should not be captured.
//
@@ -2217,6 +2216,14 @@
if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
return VD;
}
+ if (isInOpenMPDeclareTargetContext()) {
+ // Try to mark variable as declare target if it is used in capturing
+ // regions.
+ if (LangOpts.OpenMP <= 45 &&
+ !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
+ checkDeclIsAllowedInOpenMPTarget(nullptr, VD);
+ return nullptr;
+ }
}
if (CheckScopeInfo) {
@@ -2474,8 +2481,8 @@
Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
// Ignore host functions during device analyzis.
- if (LangOpts.OpenMPIsDevice && DevTy &&
- *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
+ if (LangOpts.OpenMPIsDevice &&
+ (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
return;
// Ignore nohost functions during host analyzis.
if (!LangOpts.OpenMPIsDevice && DevTy &&
@@ -2520,6 +2527,7 @@
void Sema::EndOpenMPClause() {
DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
+ CleanupVarDeclMarking();
}
static std::pair<ValueDecl *, bool>
@@ -3421,7 +3429,9 @@
if (S->getDirectiveKind() == OMPD_atomic ||
S->getDirectiveKind() == OMPD_critical ||
S->getDirectiveKind() == OMPD_section ||
- S->getDirectiveKind() == OMPD_master) {
+ S->getDirectiveKind() == OMPD_master ||
+ S->getDirectiveKind() == OMPD_masked ||
+ isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
Visit(S->getAssociatedStmt());
return;
}
@@ -3563,9 +3573,11 @@
!Stack->isLoopControlVariable(VD).first) {
if (!Stack->checkMappableExprComponentListsForDecl(
VD, /*CurrentRegionOnly=*/true,
- [](OMPClauseMappableExprCommon::MappableExprComponentListRef
- StackComponents,
- OpenMPClauseKind) {
+ [this](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
+ if (SemaRef.LangOpts.OpenMP >= 50)
+ return !StackComponents.empty();
// Variable is used if it has been marked as an array, array
// section, array shaping or the variable iself.
return StackComponents.size() == 1 ||
@@ -3792,6 +3804,17 @@
// Check implicitly captured variables.
VisitSubCaptures(S);
}
+
+ void VisitOMPTileDirective(OMPTileDirective *S) {
+ // #pragma omp tile does not introduce data sharing.
+ VisitStmt(S);
+ }
+
+ void VisitOMPUnrollDirective(OMPUnrollDirective *S) {
+ // #pragma omp unroll does not introduce data sharing.
+ VisitStmt(S);
+ }
+
void VisitStmt(Stmt *S) {
for (Stmt *C : S->children()) {
if (C) {
@@ -3956,6 +3979,9 @@
case OMPD_critical:
case OMPD_section:
case OMPD_master:
+ case OMPD_masked:
+ case OMPD_tile:
+ case OMPD_unroll:
break;
case OMPD_simd:
case OMPD_for:
@@ -3966,7 +3992,8 @@
case OMPD_distribute:
case OMPD_distribute_simd:
case OMPD_ordered:
- case OMPD_target_data: {
+ case OMPD_target_data:
+ case OMPD_dispatch: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -4436,7 +4463,8 @@
if (DSAStack->getCurrentDirective() == OMPD_atomic ||
DSAStack->getCurrentDirective() == OMPD_critical ||
DSAStack->getCurrentDirective() == OMPD_section ||
- DSAStack->getCurrentDirective() == OMPD_master)
+ DSAStack->getCurrentDirective() == OMPD_master ||
+ DSAStack->getCurrentDirective() == OMPD_masked)
return S;
bool ErrorFound = false;
@@ -4478,6 +4506,10 @@
}
}
DSAStack->setForceVarCapturing(/*V=*/false);
+ } else if (isOpenMPLoopTransformationDirective(
+ DSAStack->getCurrentDirective())) {
+ assert(CaptureRegions.empty() &&
+ "No captured regions in loop transformation directives.");
} else if (CaptureRegions.size() > 1 ||
CaptureRegions.back() != OMPD_unknown) {
if (auto *C = OMPClauseWithPreInit::get(Clause))
@@ -4575,6 +4607,22 @@
}
}
}
+ if (ThisCaptureRegion == OMPD_parallel) {
+ // Capture temp arrays for inscan reductions and locals in aligned
+ // clauses.
+ for (OMPClause *C : Clauses) {
+ if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
+ if (RC->getModifier() != OMPC_REDUCTION_inscan)
+ continue;
+ for (Expr *E : RC->copy_array_temps())
+ MarkDeclarationsReferencedInExpr(E);
+ }
+ if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
+ for (Expr *E : AC->varlists())
+ MarkDeclarationsReferencedInExpr(E);
+ }
+ }
+ }
if (++CompletedRegions == CaptureRegions.size())
DSAStack->setBodyComplete();
SR = ActOnCapturedRegionEnd(SR.get());
@@ -4701,10 +4749,10 @@
(ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
ParentRegion == OMPD_parallel_sections)));
OrphanSeen = ParentRegion == OMPD_unknown;
- } else if (CurrentRegion == OMPD_master) {
- // OpenMP [2.16, Nesting of Regions]
- // A master region may not be closely nested inside a worksharing,
- // atomic, or explicit task region.
+ } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
+ // OpenMP 5.1 [2.22, Nesting of Regions]
+ // A masked region may not be closely nested inside a worksharing, loop,
+ // atomic, task, or taskloop region.
NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
isOpenMPTaskingDirective(ParentRegion);
} else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
@@ -4734,27 +4782,28 @@
return true;
}
} else if (CurrentRegion == OMPD_barrier) {
- // OpenMP [2.16, Nesting of Regions]
- // A barrier region may not be closely nested inside a worksharing,
- // explicit task, critical, ordered, atomic, or master region.
- NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- isOpenMPTaskingDirective(ParentRegion) ||
- ParentRegion == OMPD_master ||
- ParentRegion == OMPD_parallel_master ||
- ParentRegion == OMPD_critical ||
- ParentRegion == OMPD_ordered;
+ // OpenMP 5.1 [2.22, Nesting of Regions]
+ // A barrier region may not be closely nested inside a worksharing, loop,
+ // task, taskloop, critical, ordered, atomic, or masked region.
+ NestingProhibited =
+ isOpenMPWorksharingDirective(ParentRegion) ||
+ isOpenMPTaskingDirective(ParentRegion) ||
+ ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
+ ParentRegion == OMPD_parallel_master ||
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
!isOpenMPParallelDirective(CurrentRegion) &&
!isOpenMPTeamsDirective(CurrentRegion)) {
- // OpenMP [2.16, Nesting of Regions]
- // A worksharing region may not be closely nested inside a worksharing,
- // explicit task, critical, ordered, atomic, or master region.
- NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- isOpenMPTaskingDirective(ParentRegion) ||
- ParentRegion == OMPD_master ||
- ParentRegion == OMPD_parallel_master ||
- ParentRegion == OMPD_critical ||
- ParentRegion == OMPD_ordered;
+ // OpenMP 5.1 [2.22, Nesting of Regions]
+ // A loop region that binds to a parallel region or a worksharing region
+ // may not be closely nested inside a worksharing, loop, task, taskloop,
+ // critical, ordered, atomic, or masked region.
+ NestingProhibited =
+ isOpenMPWorksharingDirective(ParentRegion) ||
+ isOpenMPTaskingDirective(ParentRegion) ||
+ ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
+ ParentRegion == OMPD_parallel_master ||
+ ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
Recommend = ShouldBeInParallelRegion;
} else if (CurrentRegion == OMPD_ordered) {
// OpenMP [2.16, Nesting of Regions]
@@ -5137,6 +5186,534 @@
}
}
+namespace {
+/// Rewrite statements and expressions for Sema \p Actions CurContext.
+///
+/// Used to wrap already parsed statements/expressions into a new CapturedStmt
+/// context. DeclRefExpr used inside the new context are changed to refer to the
+/// captured variable instead.
+class CaptureVars : public TreeTransform<CaptureVars> {
+ using BaseTransform = TreeTransform<CaptureVars>;
+
+public:
+ CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
+
+ bool AlwaysRebuild() { return true; }
+};
+} // namespace
+
+static VarDecl *precomputeExpr(Sema &Actions,
+ SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
+ StringRef Name) {
+ Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
+ VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
+ dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
+ auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
+ Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
+ Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
+ BodyStmts.push_back(NewDeclStmt);
+ return NewVar;
+}
+
+/// Create a closure that computes the number of iterations of a loop.
+///
+/// \param Actions The Sema object.
+/// \param LogicalTy Type for the logical iteration number.
+/// \param Rel Comparison operator of the loop condition.
+/// \param StartExpr Value of the loop counter at the first iteration.
+/// \param StopExpr Expression the loop counter is compared against in the loop
+/// condition. \param StepExpr Amount of increment after each iteration.
+///
+/// \return Closure (CapturedStmt) of the distance calculation.
+static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
+ BinaryOperator::Opcode Rel,
+ Expr *StartExpr, Expr *StopExpr,
+ Expr *StepExpr) {
+ ASTContext &Ctx = Actions.getASTContext();
+ TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
+
+ // Captured regions currently don't support return values, we use an
+ // out-parameter instead. All inputs are implicit captures.
+ // TODO: Instead of capturing each DeclRefExpr occurring in
+ // StartExpr/StopExpr/Step, these could also be passed as a value capture.
+ QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
+ Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
+ {StringRef(), QualType()}};
+ Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
+
+ Stmt *Body;
+ {
+ Sema::CompoundScopeRAII CompoundScope(Actions);
+ CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
+
+ // Get the LValue expression for the result.
+ ImplicitParamDecl *DistParam = CS->getParam(0);
+ DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
+ DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
+
+ SmallVector<Stmt *, 4> BodyStmts;
+
+ // Capture all referenced variable references.
+ // TODO: Instead of computing NewStart/NewStop/NewStep inside the
+ // CapturedStmt, we could compute them before and capture the result, to be
+ // used jointly with the LoopVar function.
+ VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
+ VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
+ VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
+ auto BuildVarRef = [&](VarDecl *VD) {
+ return buildDeclRefExpr(Actions, VD, VD->getType(), {});
+ };
+
+ IntegerLiteral *Zero = IntegerLiteral::Create(
+ Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
+ Expr *Dist;
+ if (Rel == BO_NE) {
+ // When using a != comparison, the increment can be +1 or -1. This can be
+ // dynamic at runtime, so we need to check for the direction.
+ Expr *IsNegStep = AssertSuccess(
+ Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
+
+ // Positive increment.
+ Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
+ nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
+ ForwardRange = AssertSuccess(
+ Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
+ Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
+ nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
+
+ // Negative increment.
+ Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
+ nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
+ BackwardRange = AssertSuccess(
+ Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
+ Expr *NegIncAmount = AssertSuccess(
+ Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
+ Expr *BackwardDist = AssertSuccess(
+ Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
+
+ // Use the appropriate case.
+ Dist = AssertSuccess(Actions.ActOnConditionalOp(
+ {}, {}, IsNegStep, BackwardDist, ForwardDist));
+ } else {
+ assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
+ "Expected one of these relational operators");
+
+ // We can derive the direction from any other comparison operator. It is
+ // non well-formed OpenMP if Step increments/decrements in the other
+ // directions. Whether at least the first iteration passes the loop
+ // condition.
+ Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
+ nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
+
+ // Compute the range between first and last counter value.
+ Expr *Range;
+ if (Rel == BO_GE || Rel == BO_GT)
+ Range = AssertSuccess(Actions.BuildBinOp(
+ nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
+ else
+ Range = AssertSuccess(Actions.BuildBinOp(
+ nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
+
+ // Ensure unsigned range space.
+ Range =
+ AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
+
+ if (Rel == BO_LE || Rel == BO_GE) {
+ // Add one to the range if the relational operator is inclusive.
+ Range =
+ AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_PreInc, Range));
+ }
+
+ // Divide by the absolute step amount.
+ Expr *Divisor = BuildVarRef(NewStep);
+ if (Rel == BO_GE || Rel == BO_GT)
+ Divisor =
+ AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
+ Dist = AssertSuccess(
+ Actions.BuildBinOp(nullptr, {}, BO_Div, Range, Divisor));
+
+ // If there is not at least one iteration, the range contains garbage. Fix
+ // to zero in this case.
+ Dist = AssertSuccess(
+ Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
+ }
+
+ // Assign the result to the out-parameter.
+ Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
+ Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
+ BodyStmts.push_back(ResultAssign);
+
+ Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
+ }
+
+ return cast<CapturedStmt>(
+ AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
+}
+
+/// Create a closure that computes the loop variable from the logical iteration
+/// number.
+///
+/// \param Actions The Sema object.
+/// \param LoopVarTy Type for the loop variable used for result value.
+/// \param LogicalTy Type for the logical iteration number.
+/// \param StartExpr Value of the loop counter at the first iteration.
+/// \param Step Amount of increment after each iteration.
+/// \param Deref Whether the loop variable is a dereference of the loop
+/// counter variable.
+///
+/// \return Closure (CapturedStmt) of the loop value calculation.
+static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
+ QualType LogicalTy,
+ DeclRefExpr *StartExpr, Expr *Step,
+ bool Deref) {
+ ASTContext &Ctx = Actions.getASTContext();
+
+ // Pass the result as an out-parameter. Passing as return value would require
+ // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
+ // invoke a copy constructor.
+ QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
+ Sema::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
+ {"Logical", LogicalTy},
+ {StringRef(), QualType()}};
+ Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
+
+ // Capture the initial iterator which represents the LoopVar value at the
+ // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
+ // it in every iteration, capture it by value before it is modified.
+ VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
+ bool Invalid = Actions.tryCaptureVariable(StartVar, {},
+ Sema::TryCapture_ExplicitByVal, {});
+ (void)Invalid;
+ assert(!Invalid && "Expecting capture-by-value to work.");
+
+ Expr *Body;
+ {
+ Sema::CompoundScopeRAII CompoundScope(Actions);
+ auto *CS = cast<CapturedDecl>(Actions.CurContext);
+
+ ImplicitParamDecl *TargetParam = CS->getParam(0);
+ DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
+ TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
+ ImplicitParamDecl *IndvarParam = CS->getParam(1);
+ DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
+ IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
+
+ // Capture the Start expression.
+ CaptureVars Recap(Actions);
+ Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
+ Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
+
+ Expr *Skip = AssertSuccess(
+ Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
+ // TODO: Explicitly cast to the iterator's difference_type instead of
+ // relying on implicit conversion.
+ Expr *Advanced =
+ AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
+
+ if (Deref) {
+ // For range-based for-loops convert the loop counter value to a concrete
+ // loop variable value by dereferencing the iterator.
+ Advanced =
+ AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
+ }
+
+ // Assign the result to the output parameter.
+ Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
+ BO_Assign, TargetRef, Advanced));
+ }
+ return cast<CapturedStmt>(
+ AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
+}
+
+StmtResult Sema::ActOnOpenMPCanonicalLoop(Stmt *AStmt) {
+ ASTContext &Ctx = getASTContext();
+
+ // Extract the common elements of ForStmt and CXXForRangeStmt:
+ // Loop variable, repeat condition, increment
+ Expr *Cond, *Inc;
+ VarDecl *LIVDecl, *LUVDecl;
+ if (auto *For = dyn_cast<ForStmt>(AStmt)) {
+ Stmt *Init = For->getInit();
+ if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
+ // For statement declares loop variable.
+ LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
+ } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
+ // For statement reuses variable.
+ assert(LCAssign->getOpcode() == BO_Assign &&
+ "init part must be a loop variable assignment");
+ auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
+ LIVDecl = cast<VarDecl>(CounterRef->getDecl());
+ } else
+ llvm_unreachable("Cannot determine loop variable");
+ LUVDecl = LIVDecl;
+
+ Cond = For->getCond();
+ Inc = For->getInc();
+ } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
+ DeclStmt *BeginStmt = RangeFor->getBeginStmt();
+ LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
+ LUVDecl = RangeFor->getLoopVariable();
+
+ Cond = RangeFor->getCond();
+ Inc = RangeFor->getInc();
+ } else
+ llvm_unreachable("unhandled kind of loop");
+
+ QualType CounterTy = LIVDecl->getType();
+ QualType LVTy = LUVDecl->getType();
+
+ // Analyze the loop condition.
+ Expr *LHS, *RHS;
+ BinaryOperator::Opcode CondRel;
+ Cond = Cond->IgnoreImplicit();
+ if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
+ LHS = CondBinExpr->getLHS();
+ RHS = CondBinExpr->getRHS();
+ CondRel = CondBinExpr->getOpcode();
+ } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
+ assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
+ LHS = CondCXXOp->getArg(0);
+ RHS = CondCXXOp->getArg(1);
+ switch (CondCXXOp->getOperator()) {
+ case OO_ExclaimEqual:
+ CondRel = BO_NE;
+ break;
+ case OO_Less:
+ CondRel = BO_LT;
+ break;
+ case OO_LessEqual:
+ CondRel = BO_LE;
+ break;
+ case OO_Greater:
+ CondRel = BO_GT;
+ break;
+ case OO_GreaterEqual:
+ CondRel = BO_GE;
+ break;
+ default:
+ llvm_unreachable("unexpected iterator operator");
+ }
+ } else
+ llvm_unreachable("unexpected loop condition");
+
+ // Normalize such that the loop counter is on the LHS.
+ if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
+ cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
+ std::swap(LHS, RHS);
+ CondRel = BinaryOperator::reverseComparisonOp(CondRel);
+ }
+ auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
+
+ // Decide the bit width for the logical iteration counter. By default use the
+ // unsigned ptrdiff_t integer size (for iterators and pointers).
+ // TODO: For iterators, use iterator::difference_type,
+ // std::iterator_traits<>::difference_type or decltype(it - end).
+ QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
+ if (CounterTy->isIntegerType()) {
+ unsigned BitWidth = Ctx.getIntWidth(CounterTy);
+ LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
+ }
+
+ // Analyze the loop increment.
+ Expr *Step;
+ if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
+ int Direction;
+ switch (IncUn->getOpcode()) {
+ case UO_PreInc:
+ case UO_PostInc:
+ Direction = 1;
+ break;
+ case UO_PreDec:
+ case UO_PostDec:
+ Direction = -1;
+ break;
+ default:
+ llvm_unreachable("unhandled unary increment operator");
+ }
+ Step = IntegerLiteral::Create(
+ Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
+ } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
+ if (IncBin->getOpcode() == BO_AddAssign) {
+ Step = IncBin->getRHS();
+ } else if (IncBin->getOpcode() == BO_SubAssign) {
+ Step =
+ AssertSuccess(BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
+ } else
+ llvm_unreachable("unhandled binary increment operator");
+ } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
+ switch (CondCXXOp->getOperator()) {
+ case OO_PlusPlus:
+ Step = IntegerLiteral::Create(
+ Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
+ break;
+ case OO_MinusMinus:
+ Step = IntegerLiteral::Create(
+ Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
+ break;
+ case OO_PlusEqual:
+ Step = CondCXXOp->getArg(1);
+ break;
+ case OO_MinusEqual:
+ Step = AssertSuccess(
+ BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
+ break;
+ default:
+ llvm_unreachable("unhandled overloaded increment operator");
+ }
+ } else
+ llvm_unreachable("unknown increment expression");
+
+ CapturedStmt *DistanceFunc =
+ buildDistanceFunc(*this, LogicalTy, CondRel, LHS, RHS, Step);
+ CapturedStmt *LoopVarFunc = buildLoopVarFunc(
+ *this, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
+ DeclRefExpr *LVRef = BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue,
+ {}, nullptr, nullptr, {}, nullptr);
+ return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
+ LoopVarFunc, LVRef);
+}
+
+static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
+ CXXScopeSpec &MapperIdScopeSpec,
+ const DeclarationNameInfo &MapperId,
+ QualType Type,
+ Expr *UnresolvedMapper);
+
+/// Perform DFS through the structure/class data members trying to find
+/// member(s) with user-defined 'default' mapper and generate implicit map
+/// clauses for such members with the found 'default' mapper.
+static void
+processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack,
+ SmallVectorImpl<OMPClause *> &Clauses) {
+ // Check for the deault mapper for data members.
+ if (S.getLangOpts().OpenMP < 50)
+ return;
+ SmallVector<OMPClause *, 4> ImplicitMaps;
+ for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
+ auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
+ if (!C)
+ continue;
+ SmallVector<Expr *, 4> SubExprs;
+ auto *MI = C->mapperlist_begin();
+ for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
+ ++I, ++MI) {
+ // Expression is mapped using mapper - skip it.
+ if (*MI)
+ continue;
+ Expr *E = *I;
+ // Expression is dependent - skip it, build the mapper when it gets
+ // instantiated.
+ if (E->isTypeDependent() || E->isValueDependent() ||
+ E->containsUnexpandedParameterPack())
+ continue;
+ // Array section - need to check for the mapping of the array section
+ // element.
+ QualType CanonType = E->getType().getCanonicalType();
+ if (CanonType->isSpecificBuiltinType(BuiltinType::OMPArraySection)) {
+ const auto *OASE = cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts());
+ QualType BaseType =
+ OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
+ QualType ElemType;
+ if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
+ ElemType = ATy->getElementType();
+ else
+ ElemType = BaseType->getPointeeType();
+ CanonType = ElemType;
+ }
+
+ // DFS over data members in structures/classes.
+ SmallVector<std::pair<QualType, FieldDecl *>, 4> Types(
+ 1, {CanonType, nullptr});
+ llvm::DenseMap<const Type *, Expr *> Visited;
+ SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(
+ 1, {nullptr, 1});
+ while (!Types.empty()) {
+ QualType BaseType;
+ FieldDecl *CurFD;
+ std::tie(BaseType, CurFD) = Types.pop_back_val();
+ while (ParentChain.back().second == 0)
+ ParentChain.pop_back();
+ --ParentChain.back().second;
+ if (BaseType.isNull())
+ continue;
+ // Only structs/classes are allowed to have mappers.
+ const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
+ if (!RD)
+ continue;
+ auto It = Visited.find(BaseType.getTypePtr());
+ if (It == Visited.end()) {
+ // Try to find the associated user-defined mapper.
+ CXXScopeSpec MapperIdScopeSpec;
+ DeclarationNameInfo DefaultMapperId;
+ DefaultMapperId.setName(S.Context.DeclarationNames.getIdentifier(
+ &S.Context.Idents.get("default")));
+ DefaultMapperId.setLoc(E->getExprLoc());
+ ExprResult ER = buildUserDefinedMapperRef(
+ S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
+ BaseType, /*UnresolvedMapper=*/nullptr);
+ if (ER.isInvalid())
+ continue;
+ It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
+ }
+ // Found default mapper.
+ if (It->second) {
+ auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
+ VK_LValue, OK_Ordinary, E);
+ OE->setIsUnique(/*V=*/true);
+ Expr *BaseExpr = OE;
+ for (const auto &P : ParentChain) {
+ if (P.first) {
+ BaseExpr = S.BuildMemberExpr(
+ BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
+ NestedNameSpecifierLoc(), SourceLocation(), P.first,
+ DeclAccessPair::make(P.first, P.first->getAccess()),
+ /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
+ P.first->getType(), VK_LValue, OK_Ordinary);
+ BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
+ }
+ }
+ if (CurFD)
+ BaseExpr = S.BuildMemberExpr(
+ BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
+ NestedNameSpecifierLoc(), SourceLocation(), CurFD,
+ DeclAccessPair::make(CurFD, CurFD->getAccess()),
+ /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
+ CurFD->getType(), VK_LValue, OK_Ordinary);
+ SubExprs.push_back(BaseExpr);
+ continue;
+ }
+ // Check for the "default" mapper for data memebers.
+ bool FirstIter = true;
+ for (FieldDecl *FD : RD->fields()) {
+ if (!FD)
+ continue;
+ QualType FieldTy = FD->getType();
+ if (FieldTy.isNull() ||
+ !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
+ continue;
+ if (FirstIter) {
+ FirstIter = false;
+ ParentChain.emplace_back(CurFD, 1);
+ } else {
+ ++ParentChain.back().second;
+ }
+ Types.emplace_back(FieldTy, FD);
+ }
+ }
+ }
+ if (SubExprs.empty())
+ continue;
+ CXXScopeSpec MapperIdScopeSpec;
+ DeclarationNameInfo MapperId;
+ if (OMPClause *NewClause = S.ActOnOpenMPMapClause(
+ C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
+ MapperIdScopeSpec, MapperId, C->getMapType(),
+ /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
+ SubExprs, OMPVarListLocTy()))
+ Clauses.push_back(NewClause);
+ }
+}
+
StmtResult Sema::ActOnOpenMPExecutableDirective(
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
@@ -5153,7 +5730,8 @@
bool ErrorFound = false;
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
- Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master) {
+ Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
+ Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
// Check default data sharing attributes for referenced variables.
@@ -5256,6 +5834,11 @@
}
}
}
+ // Build expressions for implicit maps of data members with 'default'
+ // mappers.
+ if (LangOpts.OpenMP >= 50)
+ processImplicitMapsWithDefaultMappers(*this, DSAStack,
+ ClausesWithImplicit);
}
llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
@@ -5271,6 +5854,14 @@
if (LangOpts.OpenMP >= 50)
AllowedNameModifiers.push_back(OMPD_simd);
break;
+ case OMPD_tile:
+ Res =
+ ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+ break;
+ case OMPD_unroll:
+ Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
case OMPD_for:
Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
VarsWithInheritedDSA);
@@ -5299,6 +5890,10 @@
"No clauses are allowed for 'omp master' directive");
Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
break;
+ case OMPD_masked:
+ Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
case OMPD_critical:
Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
@@ -5561,6 +6156,15 @@
if (LangOpts.OpenMP >= 50)
AllowedNameModifiers.push_back(OMPD_simd);
break;
+ case OMPD_interop:
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp interop' directive");
+ Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
+ break;
+ case OMPD_dispatch:
+ Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ break;
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_threadprivate:
@@ -5609,6 +6213,8 @@
case OMPC_num_tasks:
case OMPC_final:
case OMPC_priority:
+ case OMPC_novariants:
+ case OMPC_nocontext:
// Do not analyze if no parent parallel directive.
if (isOpenMPParallelDirective(Kind))
break;
@@ -5621,6 +6227,7 @@
case OMPC_collapse:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_default:
case OMPC_proc_bind:
case OMPC_private:
@@ -6122,7 +6729,8 @@
auto *VariantFuncRef = DeclRefExpr::Create(
Context, NestedNameSpecifierLoc(), SourceLocation(), FD,
/* RefersToEnclosingVariableOrCapture */ false,
- /* NameLoc */ FD->getLocation(), FD->getType(), ExprValueKind::VK_RValue);
+ /* NameLoc */ FD->getLocation(), FD->getType(),
+ ExprValueKind::VK_PRValue);
OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
@@ -6585,6 +7193,8 @@
class OpenMPIterationSpaceChecker {
/// Reference to Sema.
Sema &SemaRef;
+ /// Does the loop associated directive support non-rectangular loops?
+ bool SupportsNonRectangular;
/// Data-sharing stack.
DSAStackTy &Stack;
/// A location for diagnostics (when there is no some better location).
@@ -6633,10 +7243,10 @@
Expr *Condition = nullptr;
public:
- OpenMPIterationSpaceChecker(Sema &SemaRef, DSAStackTy &Stack,
- SourceLocation DefaultLoc)
- : SemaRef(SemaRef), Stack(Stack), DefaultLoc(DefaultLoc),
- ConditionLoc(DefaultLoc) {}
+ OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
+ DSAStackTy &Stack, SourceLocation DefaultLoc)
+ : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
+ Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
/// Check init-expr for canonical loop form and save loop counter
/// variable - #Var and its initialization value - #LB.
bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
@@ -6840,6 +7450,7 @@
const ValueDecl *DepDecl = nullptr;
const ValueDecl *PrevDepDecl = nullptr;
bool IsInitializer = true;
+ bool SupportsNonRectangular;
unsigned BaseLoopId = 0;
bool checkDecl(const Expr *E, const ValueDecl *VD) {
if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
@@ -6862,6 +7473,10 @@
SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
return false;
}
+ if (Data.first && !SupportsNonRectangular) {
+ SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
+ return false;
+ }
if (Data.first &&
(DepDecl || (PrevDepDecl &&
getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
@@ -6906,9 +7521,11 @@
}
explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
const ValueDecl *CurLCDecl, bool IsInitializer,
- const ValueDecl *PrevDepDecl = nullptr)
+ const ValueDecl *PrevDepDecl = nullptr,
+ bool SupportsNonRectangular = true)
: SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
- PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer) {}
+ PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
+ SupportsNonRectangular(SupportsNonRectangular) {}
unsigned getBaseLoopId() const {
assert(CurLCDecl && "Expected loop dependency.");
return BaseLoopId;
@@ -6925,7 +7542,7 @@
bool IsInitializer) {
// Check for the non-rectangular loops.
LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
- DepDecl);
+ DepDecl, SupportsNonRectangular);
if (LoopStmtChecker.Visit(S)) {
DepDecl = LoopStmtChecker.getDepDecl();
return LoopStmtChecker.getBaseLoopId();
@@ -7056,53 +7673,43 @@
Condition = S;
S = getExprAsWritten(S);
SourceLocation CondLoc = S->getBeginLoc();
- if (auto *BO = dyn_cast<BinaryOperator>(S)) {
- if (BO->isRelationalOp()) {
- if (getInitLCDecl(BO->getLHS()) == LCDecl)
- return setUB(BO->getRHS(),
- (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_LE),
- (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
- BO->getSourceRange(), BO->getOperatorLoc());
- if (getInitLCDecl(BO->getRHS()) == LCDecl)
- return setUB(BO->getLHS(),
- (BO->getOpcode() == BO_GT || BO->getOpcode() == BO_GE),
- (BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
- BO->getSourceRange(), BO->getOperatorLoc());
- } else if (IneqCondIsCanonical && BO->getOpcode() == BO_NE)
- return setUB(
- getInitLCDecl(BO->getLHS()) == LCDecl ? BO->getRHS() : BO->getLHS(),
- /*LessOp=*/llvm::None,
- /*StrictOp=*/true, BO->getSourceRange(), BO->getOperatorLoc());
+ auto &&CheckAndSetCond = [this, IneqCondIsCanonical](
+ BinaryOperatorKind Opcode, const Expr *LHS,
+ const Expr *RHS, SourceRange SR,
+ SourceLocation OpLoc) -> llvm::Optional<bool> {
+ if (BinaryOperator::isRelationalOp(Opcode)) {
+ if (getInitLCDecl(LHS) == LCDecl)
+ return setUB(const_cast<Expr *>(RHS),
+ (Opcode == BO_LT || Opcode == BO_LE),
+ (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
+ if (getInitLCDecl(RHS) == LCDecl)
+ return setUB(const_cast<Expr *>(LHS),
+ (Opcode == BO_GT || Opcode == BO_GE),
+ (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
+ } else if (IneqCondIsCanonical && Opcode == BO_NE) {
+ return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
+ /*LessOp=*/llvm::None,
+ /*StrictOp=*/true, SR, OpLoc);
+ }
+ return llvm::None;
+ };
+ llvm::Optional<bool> Res;
+ if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
+ CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
+ Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
+ RBO->getOperatorLoc());
+ } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
+ Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
+ BO->getSourceRange(), BO->getOperatorLoc());
} else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
if (CE->getNumArgs() == 2) {
- auto Op = CE->getOperator();
- switch (Op) {
- case OO_Greater:
- case OO_GreaterEqual:
- case OO_Less:
- case OO_LessEqual:
- if (getInitLCDecl(CE->getArg(0)) == LCDecl)
- return setUB(CE->getArg(1), Op == OO_Less || Op == OO_LessEqual,
- Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
- CE->getOperatorLoc());
- if (getInitLCDecl(CE->getArg(1)) == LCDecl)
- return setUB(CE->getArg(0), Op == OO_Greater || Op == OO_GreaterEqual,
- Op == OO_Less || Op == OO_Greater, CE->getSourceRange(),
- CE->getOperatorLoc());
- break;
- case OO_ExclaimEqual:
- if (IneqCondIsCanonical)
- return setUB(getInitLCDecl(CE->getArg(0)) == LCDecl ? CE->getArg(1)
- : CE->getArg(0),
- /*LessOp=*/llvm::None,
- /*StrictOp=*/true, CE->getSourceRange(),
- CE->getOperatorLoc());
- break;
- default:
- break;
- }
+ Res = CheckAndSetCond(
+ BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
+ CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
}
}
+ if (Res.hasValue())
+ return *Res;
if (dependent() || SemaRef.CurContext->isDependentContext())
return false;
SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
@@ -7420,10 +8027,7 @@
// LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
// max(LB(MinVal), LB(MaxVal))
if (InitDependOnLC) {
- const LoopIterationSpace &IS =
- ResultIterSpaces[ResultIterSpaces.size() - 1 -
- InitDependOnLC.getValueOr(
- CondDependOnLC.getValueOr(0))];
+ const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
if (!IS.MinValue || !IS.MaxValue)
return nullptr;
// OuterVar = Min
@@ -7500,10 +8104,7 @@
// UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
// min(UB(MinVal), UB(MaxVal))
if (CondDependOnLC) {
- const LoopIterationSpace &IS =
- ResultIterSpaces[ResultIterSpaces.size() - 1 -
- InitDependOnLC.getValueOr(
- CondDependOnLC.getValueOr(0))];
+ const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
if (!IS.MinValue || !IS.MaxValue)
return nullptr;
// OuterVar = Min
@@ -7584,9 +8185,9 @@
if (!Upper || !Lower)
return nullptr;
- ExprResult Diff =
- calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
- TestIsStrictOp, /*RoundToStep=*/true, Captures);
+ ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
+ Step, VarType, TestIsStrictOp,
+ /*RoundToStep=*/true, Captures);
if (!Diff.isUsable())
return nullptr;
@@ -7662,9 +8263,9 @@
// Build minimum/maximum value based on number of iterations.
QualType VarType = LCDecl->getType().getNonReferenceType();
- ExprResult Diff =
- calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
- TestIsStrictOp, /*RoundToStep=*/false, Captures);
+ ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
+ Step, VarType, TestIsStrictOp,
+ /*RoundToStep=*/false, Captures);
if (!Diff.isUsable())
return std::make_pair(nullptr, nullptr);
@@ -7855,9 +8456,9 @@
if (!Upper || !Lower)
return nullptr;
- ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
- Step, VarType, /*TestIsStrictOp=*/false,
- /*RoundToStep=*/false, Captures);
+ ExprResult Diff = calculateNumIters(
+ SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
+ /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
if (!Diff.isUsable())
return nullptr;
@@ -7872,7 +8473,8 @@
if (AssociatedLoops > 0 &&
isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
DSAStack->loopStart();
- OpenMPIterationSpaceChecker ISC(*this, *DSAStack, ForLoc);
+ OpenMPIterationSpaceChecker ISC(*this, /*SupportsNonRectangular=*/true,
+ *DSAStack, ForLoc);
if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
if (ValueDecl *D = ISC.getLoopDecl()) {
auto *VD = dyn_cast<VarDecl>(D);
@@ -7957,9 +8559,12 @@
Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
+ bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
// OpenMP [2.9.1, Canonical Loop Form]
// for (init-expr; test-expr; incr-expr) structured-block
// for (range-decl: range-expr) structured-block
+ if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
+ S = CanonLoop->getLoopStmt();
auto *For = dyn_cast_or_null<ForStmt>(S);
auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
// Ranged for is supported only in OpenMP 5.0.
@@ -7988,7 +8593,7 @@
assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
"No loop body.");
- OpenMPIterationSpaceChecker ISC(SemaRef, DSA,
+ OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
For ? For->getForLoc() : CXXFor->getForLoc());
// Check init.
@@ -8044,7 +8649,8 @@
ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
(isOpenMPWorksharingDirective(DKind) ||
isOpenMPTaskLoopDirective(DKind) ||
- isOpenMPDistributeDirective(DKind)),
+ isOpenMPDistributeDirective(DKind) ||
+ isOpenMPLoopTransformationDirective(DKind)),
Captures);
ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
ISC.buildCounterVar(Captures, DSA);
@@ -8301,8 +8907,11 @@
Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
DSAStackTy &DSA,
Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
- OMPLoopDirective::HelperExprs &Built) {
+ OMPLoopBasedDirective::HelperExprs &Built) {
unsigned NestedLoopCount = 1;
+ bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
+ !isOpenMPLoopTransformationDirective(DKind);
+
if (CollapseLoopCountExpr) {
// Found 'collapse' clause - calculate collapse number.
Expr::EvalResult Result;
@@ -8339,58 +8948,48 @@
// This is helper routine for loop directives (e.g., 'for', 'simd',
// 'for simd', etc.).
llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
- SmallVector<LoopIterationSpace, 4> IterSpaces(
- std::max(OrderedLoopCount, NestedLoopCount));
- Stmt *CurStmt = AStmt->IgnoreContainers(/* IgnoreCaptured */ true);
- for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
- if (checkOpenMPIterationSpace(
- DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
- std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
- OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces, Captures))
- return 0;
- // Move on to the next nested for loop, or to the loop body.
- // OpenMP [2.8.1, simd construct, Restrictions]
- // All loops associated with the construct must be perfectly nested; that
- // is, there must be no intervening code nor any OpenMP directive between
- // any two loops.
- if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
- CurStmt = For->getBody();
- } else {
- assert(isa<CXXForRangeStmt>(CurStmt) &&
- "Expected canonical for or range-based for loops.");
- CurStmt = cast<CXXForRangeStmt>(CurStmt)->getBody();
- }
- CurStmt = OMPLoopDirective::tryToFindNextInnerLoop(
- CurStmt, SemaRef.LangOpts.OpenMP >= 50);
- }
- for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) {
- if (checkOpenMPIterationSpace(
- DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
- std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
- OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces, Captures))
- return 0;
- if (Cnt > 0 && IterSpaces[Cnt].CounterVar) {
- // Handle initialization of captured loop iterator variables.
- auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
- if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
- Captures[DRE] = DRE;
- }
- }
- // Move on to the next nested for loop, or to the loop body.
- // OpenMP [2.8.1, simd construct, Restrictions]
- // All loops associated with the construct must be perfectly nested; that
- // is, there must be no intervening code nor any OpenMP directive between
- // any two loops.
- if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
- CurStmt = For->getBody();
- } else {
- assert(isa<CXXForRangeStmt>(CurStmt) &&
- "Expected canonical for or range-based for loops.");
- CurStmt = cast<CXXForRangeStmt>(CurStmt)->getBody();
- }
- CurStmt = OMPLoopDirective::tryToFindNextInnerLoop(
- CurStmt, SemaRef.LangOpts.OpenMP >= 50);
- }
+ unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
+ SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
+ if (!OMPLoopBasedDirective::doForAllLoops(
+ AStmt->IgnoreContainers(!isOpenMPLoopTransformationDirective(DKind)),
+ SupportsNonPerfectlyNested, NumLoops,
+ [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
+ CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
+ &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
+ if (checkOpenMPIterationSpace(
+ DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
+ NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
+ VarsWithImplicitDSA, IterSpaces, Captures))
+ return true;
+ if (Cnt > 0 && Cnt >= NestedLoopCount &&
+ IterSpaces[Cnt].CounterVar) {
+ // Handle initialization of captured loop iterator variables.
+ auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
+ if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
+ Captures[DRE] = DRE;
+ }
+ }
+ return false;
+ },
+ [&SemaRef, &Captures](OMPLoopBasedDirective *Transform) {
+ Stmt *DependentPreInits;
+ if (auto *Dir = dyn_cast<OMPTileDirective>(Transform)) {
+ DependentPreInits = Dir->getPreInits();
+ } else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform)) {
+ DependentPreInits = Dir->getPreInits();
+ } else {
+ llvm_unreachable("Unexpected loop transformation");
+ }
+ if (!DependentPreInits)
+ return;
+ for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
+ auto *D = cast<VarDecl>(C);
+ DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
+ Transform->getBeginLoc());
+ Captures[Ref] = Ref;
+ }
+ }))
+ return 0;
Built.clear(/* size */ NestedLoopCount);
@@ -8538,7 +9137,8 @@
// Build variables passed into runtime, necessary for worksharing directives.
ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
- isOpenMPDistributeDirective(DKind)) {
+ isOpenMPDistributeDirective(DKind) ||
+ isOpenMPLoopTransformationDirective(DKind)) {
// Lower bound variable, initialized with zero.
VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
@@ -8636,11 +9236,12 @@
{
VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
- Expr *RHS =
- (isOpenMPWorksharingDirective(DKind) ||
- isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind))
- ? LB.get()
- : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
+ Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind) ||
+ isOpenMPLoopTransformationDirective(DKind))
+ ? LB.get()
+ : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
@@ -8678,7 +9279,8 @@
}
ExprResult Cond =
(isOpenMPWorksharingDirective(DKind) ||
- isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind))
+ isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind) ||
+ isOpenMPLoopTransformationDirective(DKind))
? SemaRef.BuildBinOp(CurScope, CondLoc,
UseStrictCompare ? BO_LT : BO_LE, IV.get(),
BoundUB)
@@ -8726,7 +9328,8 @@
// base variables for the update
ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
- isOpenMPDistributeDirective(DKind)) {
+ isOpenMPDistributeDirective(DKind) ||
+ isOpenMPLoopTransformationDirective(DKind)) {
// LB + ST
NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
if (!NextLB.isUsable())
@@ -8798,11 +9401,21 @@
// Build expression: UB = min(UB, prevUB) for #for in composite or combined
// construct
+ ExprResult NewPrevUB = PrevUB;
SourceLocation DistEUBLoc = AStmt->getBeginLoc();
- ExprResult IsUBGreater =
- SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT, UB.get(), PrevUB.get());
+ if (!SemaRef.Context.hasSameType(UB.get()->getType(),
+ PrevUB.get()->getType())) {
+ NewPrevUB = SemaRef.BuildCStyleCastExpr(
+ DistEUBLoc,
+ SemaRef.Context.getTrivialTypeSourceInfo(UB.get()->getType()),
+ DistEUBLoc, NewPrevUB.get());
+ if (!NewPrevUB.isUsable())
+ return 0;
+ }
+ ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
+ UB.get(), NewPrevUB.get());
ExprResult CondOp = SemaRef.ActOnConditionalOp(
- DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get());
+ DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
CondOp.get());
PrevEUB =
@@ -9052,7 +9665,7 @@
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -9091,7 +9704,7 @@
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -9127,7 +9740,7 @@
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -9211,6 +9824,64 @@
DSAStack->isCancelRegion());
}
+static Expr *getDirectCallExpr(Expr *E) {
+ E = E->IgnoreParenCasts()->IgnoreImplicit();
+ if (auto *CE = dyn_cast<CallExpr>(E))
+ if (CE->getDirectCallee())
+ return E;
+ return nullptr;
+}
+
+StmtResult Sema::ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
+
+ // 5.1 OpenMP
+ // expression-stmt : an expression statement with one of the following forms:
+ // expression = target-call ( [expression-list] );
+ // target-call ( [expression-list] );
+
+ SourceLocation TargetCallLoc;
+
+ if (!CurContext->isDependentContext()) {
+ Expr *TargetCall = nullptr;
+
+ auto *E = dyn_cast<Expr>(S);
+ if (!E) {
+ Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
+ return StmtError();
+ }
+
+ E = E->IgnoreParenCasts()->IgnoreImplicit();
+
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Assign)
+ TargetCall = getDirectCallExpr(BO->getRHS());
+ } else {
+ if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
+ if (COCE->getOperator() == OO_Equal)
+ TargetCall = getDirectCallExpr(COCE->getArg(1));
+ if (!TargetCall)
+ TargetCall = getDirectCallExpr(E);
+ }
+ if (!TargetCall) {
+ Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
+ return StmtError();
+ }
+ TargetCallLoc = TargetCall->getExprLoc();
+ }
+
+ setFunctionHasBranchProtectedScope();
+
+ return OMPDispatchDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ TargetCallLoc);
+}
+
StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
@@ -9253,6 +9924,18 @@
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
+StmtResult Sema::ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ setFunctionHasBranchProtectedScope();
+
+ return OMPMaskedDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
StmtResult Sema::ActOnOpenMPCriticalDirective(
const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
@@ -9287,14 +9970,14 @@
Diag(StartLoc, diag::err_omp_critical_with_hint);
if (HintLoc.isValid())
Diag(HintLoc, diag::note_omp_critical_hint_here)
- << 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false);
+ << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
else
Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
<< 1
- << C->getHint()->EvaluateKnownConstInt(Context).toString(
- /*Radix=*/10, /*Signed=*/false);
+ << toString(C->getHint()->EvaluateKnownConstInt(Context),
+ /*Radix=*/10, /*Signed=*/false);
} else {
Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
}
@@ -9324,7 +10007,7 @@
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -9368,7 +10051,7 @@
// longjmp() and throw() must not violate the entry/exit criteria.
CS->getCapturedDecl()->setNothrow();
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -9460,14 +10143,14 @@
DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
}
-/// detach and mergeable clauses are mutially exclusive, check for it.
-static bool checkDetachMergeableClauses(Sema &S,
- ArrayRef<OMPClause *> Clauses) {
+/// Find and diagnose mutually exclusive clause kinds.
+static bool checkMutuallyExclusiveClauses(
+ Sema &S, ArrayRef<OMPClause *> Clauses,
+ ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
const OMPClause *PrevClause = nullptr;
bool ErrorFound = false;
for (const OMPClause *C : Clauses) {
- if (C->getClauseKind() == OMPC_detach ||
- C->getClauseKind() == OMPC_mergeable) {
+ if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
if (!PrevClause) {
PrevClause = C;
} else if (PrevClause->getClauseKind() != C->getClauseKind()) {
@@ -9492,7 +10175,8 @@
// OpenMP 5.0, 2.10.1 task Construct
// If a detach clause appears on the directive, then a mergeable clause cannot
// appear on the same directive.
- if (checkDetachMergeableClauses(*this, Clauses))
+ if (checkMutuallyExclusiveClauses(*this, Clauses,
+ {OMPC_detach, OMPC_mergeable}))
return StmtError();
auto *CS = cast<CapturedStmt>(AStmt);
@@ -9950,9 +10634,9 @@
// OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
// OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
auto *OVEX = new (SemaRef.getASTContext())
- OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_RValue);
+ OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
auto *OVEExpr = new (SemaRef.getASTContext())
- OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_RValue);
+ OpaqueValueExpr(E->getExprLoc(), E->getType(), VK_PRValue);
ExprResult Update =
SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
IsXLHSInRHSPart ? OVEExpr : OVEX);
@@ -10562,7 +11246,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -10796,28 +11480,6 @@
CancelRegion);
}
-static bool checkGrainsizeNumTasksClauses(Sema &S,
- ArrayRef<OMPClause *> Clauses) {
- const OMPClause *PrevClause = nullptr;
- bool ErrorFound = false;
- for (const OMPClause *C : Clauses) {
- if (C->getClauseKind() == OMPC_grainsize ||
- C->getClauseKind() == OMPC_num_tasks) {
- if (!PrevClause)
- PrevClause = C;
- else if (PrevClause->getClauseKind() != C->getClauseKind()) {
- S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
- << getOpenMPClauseName(C->getClauseKind())
- << getOpenMPClauseName(PrevClause->getClauseKind());
- S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
- << getOpenMPClauseName(PrevClause->getClauseKind());
- ErrorFound = true;
- }
- }
- }
- return ErrorFound;
-}
-
static bool checkReductionClauseWithNogroup(Sema &S,
ArrayRef<OMPClause *> Clauses) {
const OMPClause *ReductionClause = nullptr;
@@ -10852,7 +11514,7 @@
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -10868,7 +11530,8 @@
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// The grainsize clause and num_tasks clause are mutually exclusive and may
// not appear on the same taskloop directive.
- if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ if (checkMutuallyExclusiveClauses(*this, Clauses,
+ {OMPC_grainsize, OMPC_num_tasks}))
return StmtError();
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// If a reduction clause is present on the taskloop directive, the nogroup
@@ -10889,7 +11552,7 @@
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -10916,7 +11579,8 @@
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// The grainsize clause and num_tasks clause are mutually exclusive and may
// not appear on the same taskloop directive.
- if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ if (checkMutuallyExclusiveClauses(*this, Clauses,
+ {OMPC_grainsize, OMPC_num_tasks}))
return StmtError();
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// If a reduction clause is present on the taskloop directive, the nogroup
@@ -10938,7 +11602,7 @@
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -10954,7 +11618,8 @@
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// The grainsize clause and num_tasks clause are mutually exclusive and may
// not appear on the same taskloop directive.
- if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ if (checkMutuallyExclusiveClauses(*this, Clauses,
+ {OMPC_grainsize, OMPC_num_tasks}))
return StmtError();
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// If a reduction clause is present on the taskloop directive, the nogroup
@@ -10975,7 +11640,7 @@
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -11002,7 +11667,8 @@
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// The grainsize clause and num_tasks clause are mutually exclusive and may
// not appear on the same taskloop directive.
- if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ if (checkMutuallyExclusiveClauses(*this, Clauses,
+ {OMPC_grainsize, OMPC_num_tasks}))
return StmtError();
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// If a reduction clause is present on the taskloop directive, the nogroup
@@ -11043,7 +11709,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11059,7 +11725,8 @@
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// The grainsize clause and num_tasks clause are mutually exclusive and may
// not appear on the same taskloop directive.
- if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ if (checkMutuallyExclusiveClauses(*this, Clauses,
+ {OMPC_grainsize, OMPC_num_tasks}))
return StmtError();
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// If a reduction clause is present on the taskloop directive, the nogroup
@@ -11099,7 +11766,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11126,7 +11793,8 @@
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// The grainsize clause and num_tasks clause are mutually exclusive and may
// not appear on the same taskloop directive.
- if (checkGrainsizeNumTasksClauses(*this, Clauses))
+ if (checkMutuallyExclusiveClauses(*this, Clauses,
+ {OMPC_grainsize, OMPC_num_tasks}))
return StmtError();
// OpenMP, [2.9.2 taskloop Construct, Restrictions]
// If a reduction clause is present on the taskloop directive, the nogroup
@@ -11148,7 +11816,7 @@
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -11191,7 +11859,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11235,7 +11903,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11291,7 +11959,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -11347,7 +12015,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' or 'ordered' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11402,7 +12070,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will define the
// nested loops number.
unsigned NestedLoopCount =
@@ -11458,7 +12126,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -11504,7 +12172,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11566,7 +12234,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11628,7 +12296,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11707,7 +12375,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11750,7 +12418,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11805,7 +12473,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount =
@@ -11864,7 +12532,7 @@
CS->getCapturedDecl()->setNothrow();
}
- OMPLoopDirective::HelperExprs B;
+ OMPLoopBasedDirective::HelperExprs B;
// In presence of clause 'collapse' with number of loops, it will
// define the nested loops number.
unsigned NestedLoopCount = checkOpenMPLoop(
@@ -11896,6 +12564,542 @@
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
+bool Sema::checkTransformableLoopNest(
+ OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
+ SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
+ Stmt *&Body,
+ SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
+ &OriginalInits) {
+ OriginalInits.emplace_back();
+ bool Result = OMPLoopBasedDirective::doForAllLoops(
+ AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
+ [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
+ Stmt *CurStmt) {
+ VarsWithInheritedDSAType TmpDSA;
+ unsigned SingleNumLoops =
+ checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, *this, *DSAStack,
+ TmpDSA, LoopHelpers[Cnt]);
+ if (SingleNumLoops == 0)
+ return true;
+ assert(SingleNumLoops == 1 && "Expect single loop iteration space");
+ if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
+ OriginalInits.back().push_back(For->getInit());
+ Body = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(CurStmt) &&
+ "Expected canonical for or range-based for loops.");
+ auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
+ OriginalInits.back().push_back(CXXFor->getBeginStmt());
+ Body = CXXFor->getBody();
+ }
+ OriginalInits.emplace_back();
+ return false;
+ },
+ [&OriginalInits](OMPLoopBasedDirective *Transform) {
+ Stmt *DependentPreInits;
+ if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
+ DependentPreInits = Dir->getPreInits();
+ else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
+ DependentPreInits = Dir->getPreInits();
+ else
+ llvm_unreachable("Unhandled loop transformation");
+ if (!DependentPreInits)
+ return;
+ for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup())
+ OriginalInits.back().push_back(C);
+ });
+ assert(OriginalInits.back().empty() && "No preinit after innermost loop");
+ OriginalInits.pop_back();
+ return Result;
+}
+
+StmtResult Sema::ActOnOpenMPTileDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ auto SizesClauses =
+ OMPExecutableDirective::getClausesOfKind<OMPSizesClause>(Clauses);
+ if (SizesClauses.empty()) {
+ // A missing 'sizes' clause is already reported by the parser.
+ return StmtError();
+ }
+ const OMPSizesClause *SizesClause = *SizesClauses.begin();
+ unsigned NumLoops = SizesClause->getNumSizes();
+
+ // Empty statement should only be possible if there already was an error.
+ if (!AStmt)
+ return StmtError();
+
+ // Verify and diagnose loop nest.
+ SmallVector<OMPLoopBasedDirective::HelperExprs, 4> LoopHelpers(NumLoops);
+ Stmt *Body = nullptr;
+ SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, 4>
+ OriginalInits;
+ if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
+ OriginalInits))
+ return StmtError();
+
+ // Delay tiling to when template is completely instantiated.
+ if (CurContext->isDependentContext())
+ return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ NumLoops, AStmt, nullptr, nullptr);
+
+ SmallVector<Decl *, 4> PreInits;
+
+ // Create iteration variables for the generated loops.
+ SmallVector<VarDecl *, 4> FloorIndVars;
+ SmallVector<VarDecl *, 4> TileIndVars;
+ FloorIndVars.resize(NumLoops);
+ TileIndVars.resize(NumLoops);
+ for (unsigned I = 0; I < NumLoops; ++I) {
+ OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
+
+ assert(LoopHelper.Counters.size() == 1 &&
+ "Expect single-dimensional loop iteration space");
+ auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
+ std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
+ DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
+ QualType CntTy = IterVarRef->getType();
+
+ // Iteration variable for the floor (i.e. outer) loop.
+ {
+ std::string FloorCntName =
+ (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
+ VarDecl *FloorCntDecl =
+ buildVarDecl(*this, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
+ FloorIndVars[I] = FloorCntDecl;
+ }
+
+ // Iteration variable for the tile (i.e. inner) loop.
+ {
+ std::string TileCntName =
+ (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
+
+ // Reuse the iteration variable created by checkOpenMPLoop. It is also
+ // used by the expressions to derive the original iteration variable's
+ // value from the logical iteration number.
+ auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
+ TileCntDecl->setDeclName(&PP.getIdentifierTable().get(TileCntName));
+ TileIndVars[I] = TileCntDecl;
+ }
+ for (auto &P : OriginalInits[I]) {
+ if (auto *D = P.dyn_cast<Decl *>())
+ PreInits.push_back(D);
+ else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
+ PreInits.append(PI->decl_begin(), PI->decl_end());
+ }
+ if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
+ PreInits.append(PI->decl_begin(), PI->decl_end());
+ // Gather declarations for the data members used as counters.
+ for (Expr *CounterRef : LoopHelper.Counters) {
+ auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
+ if (isa<OMPCapturedExprDecl>(CounterDecl))
+ PreInits.push_back(CounterDecl);
+ }
+ }
+
+ // Once the original iteration values are set, append the innermost body.
+ Stmt *Inner = Body;
+
+ // Create tile loops from the inside to the outside.
+ for (int I = NumLoops - 1; I >= 0; --I) {
+ OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
+ Expr *NumIterations = LoopHelper.NumIterations;
+ auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
+ QualType CntTy = OrigCntVar->getType();
+ Expr *DimTileSize = SizesClause->getSizesRefs()[I];
+ Scope *CurScope = getCurScope();
+
+ // Commonly used variables.
+ DeclRefExpr *TileIV = buildDeclRefExpr(*this, TileIndVars[I], CntTy,
+ OrigCntVar->getExprLoc());
+ DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
+ OrigCntVar->getExprLoc());
+
+ // For init-statement: auto .tile.iv = .floor.iv
+ AddInitializerToDecl(TileIndVars[I], DefaultLvalueConversion(FloorIV).get(),
+ /*DirectInit=*/false);
+ Decl *CounterDecl = TileIndVars[I];
+ StmtResult InitStmt = new (Context)
+ DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
+ OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
+ if (!InitStmt.isUsable())
+ return StmtError();
+
+ // For cond-expression: .tile.iv < min(.floor.iv + DimTileSize,
+ // NumIterations)
+ ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
+ BO_Add, FloorIV, DimTileSize);
+ if (!EndOfTile.isUsable())
+ return StmtError();
+ ExprResult IsPartialTile =
+ BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
+ NumIterations, EndOfTile.get());
+ if (!IsPartialTile.isUsable())
+ return StmtError();
+ ExprResult MinTileAndIterSpace = ActOnConditionalOp(
+ LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
+ IsPartialTile.get(), NumIterations, EndOfTile.get());
+ if (!MinTileAndIterSpace.isUsable())
+ return StmtError();
+ ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
+ BO_LT, TileIV, MinTileAndIterSpace.get());
+ if (!CondExpr.isUsable())
+ return StmtError();
+
+ // For incr-statement: ++.tile.iv
+ ExprResult IncrStmt =
+ BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, TileIV);
+ if (!IncrStmt.isUsable())
+ return StmtError();
+
+ // Statements to set the original iteration variable's value from the
+ // logical iteration number.
+ // Generated for loop is:
+ // Original_for_init;
+ // for (auto .tile.iv = .floor.iv; .tile.iv < min(.floor.iv + DimTileSize,
+ // NumIterations); ++.tile.iv) {
+ // Original_Body;
+ // Original_counter_update;
+ // }
+ // FIXME: If the innermost body is an loop itself, inserting these
+ // statements stops it being recognized as a perfectly nested loop (e.g.
+ // for applying tiling again). If this is the case, sink the expressions
+ // further into the inner loop.
+ SmallVector<Stmt *, 4> BodyParts;
+ BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
+ BodyParts.push_back(Inner);
+ Inner = CompoundStmt::Create(Context, BodyParts, Inner->getBeginLoc(),
+ Inner->getEndLoc());
+ Inner = new (Context)
+ ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
+ IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
+ LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
+ }
+
+ // Create floor loops from the inside to the outside.
+ for (int I = NumLoops - 1; I >= 0; --I) {
+ auto &LoopHelper = LoopHelpers[I];
+ Expr *NumIterations = LoopHelper.NumIterations;
+ DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
+ QualType CntTy = OrigCntVar->getType();
+ Expr *DimTileSize = SizesClause->getSizesRefs()[I];
+ Scope *CurScope = getCurScope();
+
+ // Commonly used variables.
+ DeclRefExpr *FloorIV = buildDeclRefExpr(*this, FloorIndVars[I], CntTy,
+ OrigCntVar->getExprLoc());
+
+ // For init-statement: auto .floor.iv = 0
+ AddInitializerToDecl(
+ FloorIndVars[I],
+ ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
+ /*DirectInit=*/false);
+ Decl *CounterDecl = FloorIndVars[I];
+ StmtResult InitStmt = new (Context)
+ DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
+ OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
+ if (!InitStmt.isUsable())
+ return StmtError();
+
+ // For cond-expression: .floor.iv < NumIterations
+ ExprResult CondExpr = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
+ BO_LT, FloorIV, NumIterations);
+ if (!CondExpr.isUsable())
+ return StmtError();
+
+ // For incr-statement: .floor.iv += DimTileSize
+ ExprResult IncrStmt = BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(),
+ BO_AddAssign, FloorIV, DimTileSize);
+ if (!IncrStmt.isUsable())
+ return StmtError();
+
+ Inner = new (Context)
+ ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
+ IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
+ LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
+ }
+
+ return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
+ AStmt, Inner,
+ buildPreInits(Context, PreInits));
+}
+
+StmtResult Sema::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ // Empty statement should only be possible if there already was an error.
+ if (!AStmt)
+ return StmtError();
+
+ if (checkMutuallyExclusiveClauses(*this, Clauses, {OMPC_partial, OMPC_full}))
+ return StmtError();
+
+ const OMPFullClause *FullClause =
+ OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
+ const OMPPartialClause *PartialClause =
+ OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
+ assert(!(FullClause && PartialClause) &&
+ "mutual exclusivity must have been checked before");
+
+ constexpr unsigned NumLoops = 1;
+ Stmt *Body = nullptr;
+ SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
+ NumLoops);
+ SmallVector<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>, NumLoops + 1>
+ OriginalInits;
+ if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
+ Body, OriginalInits))
+ return StmtError();
+
+ // Delay unrolling to when template is completely instantiated.
+ if (CurContext->isDependentContext())
+ return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ nullptr, nullptr);
+
+ OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
+
+ if (FullClause) {
+ if (!VerifyPositiveIntegerConstantInClause(
+ LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
+ /*SuppressExprDigs=*/true)
+ .isUsable()) {
+ Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
+ Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
+ << "#pragma omp unroll full";
+ return StmtError();
+ }
+ }
+
+ // The generated loop may only be passed to other loop-associated directive
+ // when a partial clause is specified. Without the requirement it is
+ // sufficient to generate loop unroll metadata at code-generation.
+ if (!PartialClause)
+ return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ nullptr, nullptr);
+
+ // Otherwise, we need to provide a de-sugared/transformed AST that can be
+ // associated with another loop directive.
+ //
+ // The canonical loop analysis return by checkTransformableLoopNest assumes
+ // the following structure to be the same loop without transformations or
+ // directives applied: \code OriginalInits; LoopHelper.PreInits;
+ // LoopHelper.Counters;
+ // for (; IV < LoopHelper.NumIterations; ++IV) {
+ // LoopHelper.Updates;
+ // Body;
+ // }
+ // \endcode
+ // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
+ // and referenced by LoopHelper.IterationVarRef.
+ //
+ // The unrolling directive transforms this into the following loop:
+ // \code
+ // OriginalInits; \
+ // LoopHelper.PreInits; > NewPreInits
+ // LoopHelper.Counters; /
+ // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
+ // #pragma clang loop unroll_count(Factor)
+ // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
+ // {
+ // LoopHelper.Updates;
+ // Body;
+ // }
+ // }
+ // \endcode
+ // where UIV is a new logical iteration counter. IV must be the same VarDecl
+ // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
+ // references it. If the partially unrolled loop is associated with another
+ // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
+ // analyze this loop, i.e. the outer loop must fulfill the constraints of an
+ // OpenMP canonical loop. The inner loop is not an associable canonical loop
+ // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
+ // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
+ // property of the OMPLoopBasedDirective instead of statements in
+ // CompoundStatement. This is to allow the loop to become a non-outermost loop
+ // of a canonical loop nest where these PreInits are emitted before the
+ // outermost directive.
+
+ // Determine the PreInit declarations.
+ SmallVector<Decl *, 4> PreInits;
+ assert(OriginalInits.size() == 1 &&
+ "Expecting a single-dimensional loop iteration space");
+ for (auto &P : OriginalInits[0]) {
+ if (auto *D = P.dyn_cast<Decl *>())
+ PreInits.push_back(D);
+ else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
+ PreInits.append(PI->decl_begin(), PI->decl_end());
+ }
+ if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
+ PreInits.append(PI->decl_begin(), PI->decl_end());
+ // Gather declarations for the data members used as counters.
+ for (Expr *CounterRef : LoopHelper.Counters) {
+ auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
+ if (isa<OMPCapturedExprDecl>(CounterDecl))
+ PreInits.push_back(CounterDecl);
+ }
+
+ auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
+ QualType IVTy = IterationVarRef->getType();
+ assert(LoopHelper.Counters.size() == 1 &&
+ "Expecting a single-dimensional loop iteration space");
+ auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
+
+ // Determine the unroll factor.
+ uint64_t Factor;
+ SourceLocation FactorLoc;
+ if (Expr *FactorVal = PartialClause->getFactor()) {
+ Factor =
+ FactorVal->getIntegerConstantExpr(Context).getValue().getZExtValue();
+ FactorLoc = FactorVal->getExprLoc();
+ } else {
+ // TODO: Use a better profitability model.
+ Factor = 2;
+ }
+ assert(Factor > 0 && "Expected positive unroll factor");
+ auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
+ return IntegerLiteral::Create(
+ Context, llvm::APInt(Context.getIntWidth(IVTy), Factor), IVTy,
+ FactorLoc);
+ };
+
+ // Iteration variable SourceLocations.
+ SourceLocation OrigVarLoc = OrigVar->getExprLoc();
+ SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
+ SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
+
+ // Internal variable names.
+ std::string OrigVarName = OrigVar->getNameInfo().getAsString();
+ std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
+ std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
+ std::string InnerTripCountName =
+ (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
+
+ // Create the iteration variable for the unrolled loop.
+ VarDecl *OuterIVDecl =
+ buildVarDecl(*this, {}, IVTy, OuterIVName, nullptr, OrigVar);
+ auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
+ return buildDeclRefExpr(*this, OuterIVDecl, IVTy, OrigVarLoc);
+ };
+
+ // Iteration variable for the inner loop: Reuse the iteration variable created
+ // by checkOpenMPLoop.
+ auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
+ InnerIVDecl->setDeclName(&PP.getIdentifierTable().get(InnerIVName));
+ auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
+ return buildDeclRefExpr(*this, InnerIVDecl, IVTy, OrigVarLoc);
+ };
+
+ // Make a copy of the NumIterations expression for each use: By the AST
+ // constraints, every expression object in a DeclContext must be unique.
+ CaptureVars CopyTransformer(*this);
+ auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
+ return AssertSuccess(
+ CopyTransformer.TransformExpr(LoopHelper.NumIterations));
+ };
+
+ // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
+ ExprResult LValueConv = DefaultLvalueConversion(MakeOuterRef());
+ AddInitializerToDecl(InnerIVDecl, LValueConv.get(), /*DirectInit=*/false);
+ StmtResult InnerInit = new (Context)
+ DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
+ if (!InnerInit.isUsable())
+ return StmtError();
+
+ // Inner For cond-expression:
+ // \code
+ // .unroll_inner.iv < .unrolled.iv + Factor &&
+ // .unroll_inner.iv < NumIterations
+ // \endcode
+ // This conjunction of two conditions allows ScalarEvolution to derive the
+ // maximum trip count of the inner loop.
+ ExprResult EndOfTile = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
+ BO_Add, MakeOuterRef(), MakeFactorExpr());
+ if (!EndOfTile.isUsable())
+ return StmtError();
+ ExprResult InnerCond1 = BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
+ BO_LE, MakeInnerRef(), EndOfTile.get());
+ if (!InnerCond1.isUsable())
+ return StmtError();
+ ExprResult InnerCond2 =
+ BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LE, MakeInnerRef(),
+ MakeNumIterations());
+ if (!InnerCond2.isUsable())
+ return StmtError();
+ ExprResult InnerCond =
+ BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
+ InnerCond1.get(), InnerCond2.get());
+ if (!InnerCond.isUsable())
+ return StmtError();
+
+ // Inner For incr-statement: ++.unroll_inner.iv
+ ExprResult InnerIncr = BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
+ UO_PreInc, MakeInnerRef());
+ if (!InnerIncr.isUsable())
+ return StmtError();
+
+ // Inner For statement.
+ SmallVector<Stmt *> InnerBodyStmts;
+ InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
+ InnerBodyStmts.push_back(Body);
+ CompoundStmt *InnerBody = CompoundStmt::Create(
+ Context, InnerBodyStmts, Body->getBeginLoc(), Body->getEndLoc());
+ ForStmt *InnerFor = new (Context)
+ ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
+ InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
+ LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
+
+ // Unroll metadata for the inner loop.
+ // This needs to take into account the remainder portion of the unrolled loop,
+ // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
+ // supports multiple loop exits. Instead, unroll using a factor equivalent to
+ // the maximum trip count, which will also generate a remainder loop. Just
+ // `unroll(enable)` (which could have been useful if the user has not
+ // specified a concrete factor; even though the outer loop cannot be
+ // influenced anymore, would avoid more code bloat than necessary) will refuse
+ // the loop because "Won't unroll; remainder loop could not be generated when
+ // assuming runtime trip count". Even if it did work, it must not choose a
+ // larger unroll factor than the maximum loop length, or it would always just
+ // execute the remainder loop.
+ LoopHintAttr *UnrollHintAttr =
+ LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
+ LoopHintAttr::Numeric, MakeFactorExpr());
+ AttributedStmt *InnerUnrolled =
+ AttributedStmt::Create(Context, StartLoc, {UnrollHintAttr}, InnerFor);
+
+ // Outer For init-statement: auto .unrolled.iv = 0
+ AddInitializerToDecl(
+ OuterIVDecl, ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
+ /*DirectInit=*/false);
+ StmtResult OuterInit = new (Context)
+ DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
+ if (!OuterInit.isUsable())
+ return StmtError();
+
+ // Outer For cond-expression: .unrolled.iv < NumIterations
+ ExprResult OuterConde =
+ BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeOuterRef(),
+ MakeNumIterations());
+ if (!OuterConde.isUsable())
+ return StmtError();
+
+ // Outer For incr-statement: .unrolled.iv += Factor
+ ExprResult OuterIncr =
+ BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
+ MakeOuterRef(), MakeFactorExpr());
+ if (!OuterIncr.isUsable())
+ return StmtError();
+
+ // Outer For statement.
+ ForStmt *OuterFor = new (Context)
+ ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
+ OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
+ LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
+
+ return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
+ OuterFor, buildPreInits(Context, PreInits));
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -11947,6 +13151,18 @@
case OMPC_detach:
Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_novariants:
+ Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_nocontext:
+ Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_filter:
+ Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
+ case OMPC_partial:
+ Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_device:
case OMPC_if:
case OMPC_default:
@@ -11967,6 +13183,7 @@
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
+ case OMPC_sizes:
case OMPC_allocate:
case OMPC_flush:
case OMPC_read:
@@ -12147,11 +13364,14 @@
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_teams:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -12223,12 +13443,15 @@
case OMPD_end_declare_target:
case OMPD_teams:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -12302,12 +13525,15 @@
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -12379,12 +13605,15 @@
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -12457,10 +13686,13 @@
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -12491,7 +13723,7 @@
case OMPD_distribute_parallel_for_simd:
case OMPD_distribute:
case OMPD_distribute_simd:
- // Do not capture thread_limit-clause expressions.
+ // Do not capture dist_schedule-clause expressions.
break;
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
@@ -12534,19 +13766,22 @@
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_ordered:
case OMPD_atomic:
case OMPD_target_teams:
case OMPD_requires:
- llvm_unreachable("Unexpected OpenMP directive with schedule clause");
+ llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
case OMPD_unknown:
default:
llvm_unreachable("Unknown OpenMP directive");
@@ -12567,9 +13802,11 @@
case OMPD_target_parallel_for_simd:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
+ case OMPD_dispatch:
CaptureRegion = OMPD_task;
break;
case OMPD_target_data:
+ case OMPD_interop:
// Do not capture device-clause expressions.
break;
case OMPD_teams_distribute_parallel_for:
@@ -12610,12 +13847,15 @@
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -12623,7 +13863,7 @@
case OMPD_atomic:
case OMPD_distribute_simd:
case OMPD_requires:
- llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
+ llvm_unreachable("Unexpected OpenMP directive with device-clause");
case OMPD_unknown:
default:
llvm_unreachable("Unknown OpenMP directive");
@@ -12689,12 +13929,15 @@
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
+ case OMPD_tile:
+ case OMPD_unroll:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
case OMPD_section:
case OMPD_single:
case OMPD_master:
+ case OMPD_masked:
case OMPD_critical:
case OMPD_taskgroup:
case OMPD_distribute:
@@ -12708,6 +13951,19 @@
llvm_unreachable("Unknown OpenMP directive");
}
break;
+ case OMPC_novariants:
+ case OMPC_nocontext:
+ switch (DKind) {
+ case OMPD_dispatch:
+ CaptureRegion = OMPD_task;
+ break;
+ default:
+ llvm_unreachable("Unexpected OpenMP directive");
+ }
+ break;
+ case OMPC_filter:
+ // Do not capture filter-clause expressions.
+ break;
case OMPC_firstprivate:
case OMPC_lastprivate:
case OMPC_reduction:
@@ -12718,6 +13974,7 @@
case OMPC_proc_bind:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_private:
@@ -12957,17 +14214,33 @@
ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
OpenMPClauseKind CKind,
- bool StrictlyPositive) {
+ bool StrictlyPositive,
+ bool SuppressExprDiags) {
if (!E)
return ExprError();
if (E->isValueDependent() || E->isTypeDependent() ||
E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
return E;
+
llvm::APSInt Result;
- ExprResult ICE =
- VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
+ ExprResult ICE;
+ if (SuppressExprDiags) {
+ // Use a custom diagnoser that suppresses 'note' diagnostics about the
+ // expression.
+ struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
+ SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
+ Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
+ SourceLocation Loc) override {
+ llvm_unreachable("Diagnostic suppressed");
+ }
+ } Diagnoser;
+ ICE = VerifyIntegerConstantExpression(E, &Result, Diagnoser, AllowFold);
+ } else {
+ ICE = VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold);
+ }
if (ICE.isInvalid())
return ExprError();
+
if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
(!StrictlyPositive && !Result.isNonNegative())) {
Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
@@ -13151,6 +14424,7 @@
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_schedule:
@@ -13210,6 +14484,8 @@
case OMPC_match:
case OMPC_nontemporal:
case OMPC_destroy:
+ case OMPC_novariants:
+ case OMPC_nocontext:
case OMPC_detach:
case OMPC_inclusive:
case OMPC_exclusive:
@@ -13282,10 +14558,21 @@
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
<< getListOfPossibleValues(OMPC_proc_bind,
/*First=*/unsigned(OMP_PROC_BIND_master),
- /*Last=*/5)
+ /*Last=*/
+ unsigned(LangOpts.OpenMP > 50
+ ? OMP_PROC_BIND_primary
+ : OMP_PROC_BIND_spread) +
+ 1)
<< getOpenMPClauseName(OMPC_proc_bind);
return nullptr;
}
+ if (Kind == OMP_PROC_BIND_primary && LangOpts.OpenMP < 51)
+ Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
+ << getListOfPossibleValues(OMPC_proc_bind,
+ /*First=*/unsigned(OMP_PROC_BIND_master),
+ /*Last=*/
+ unsigned(OMP_PROC_BIND_spread) + 1)
+ << getOpenMPClauseName(OMPC_proc_bind);
return new (Context)
OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
}
@@ -13342,6 +14629,45 @@
EndLoc);
}
+OMPClause *Sema::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ for (Expr *SizeExpr : SizeExprs) {
+ ExprResult NumForLoopsResult = VerifyPositiveIntegerConstantInClause(
+ SizeExpr, OMPC_sizes, /*StrictlyPositive=*/true);
+ if (!NumForLoopsResult.isUsable())
+ return nullptr;
+ }
+
+ DSAStack->setAssociatedLoops(SizeExprs.size());
+ return OMPSizesClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ SizeExprs);
+}
+
+OMPClause *Sema::ActOnOpenMPFullClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return OMPFullClause::Create(Context, StartLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ if (FactorExpr) {
+ // If an argument is specified, it must be a constant (or an unevaluated
+ // template expression).
+ ExprResult FactorResult = VerifyPositiveIntegerConstantInClause(
+ FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
+ if (FactorResult.isInvalid())
+ return nullptr;
+ FactorExpr = FactorResult.get();
+ }
+
+ return OMPPartialClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ FactorExpr);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
SourceLocation StartLoc, SourceLocation LParenLoc,
@@ -13389,6 +14715,7 @@
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_default:
@@ -13449,6 +14776,8 @@
case OMPC_nontemporal:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_novariants:
+ case OMPC_nocontext:
case OMPC_detach:
case OMPC_inclusive:
case OMPC_exclusive:
@@ -13637,13 +14966,22 @@
Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
break;
case OMPC_destroy:
- Res = ActOnOpenMPDestroyClause(StartLoc, EndLoc);
+ Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
+ /*LParenLoc=*/SourceLocation(),
+ /*VarLoc=*/SourceLocation(), EndLoc);
+ break;
+ case OMPC_full:
+ Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
+ break;
+ case OMPC_partial:
+ Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_schedule:
@@ -13687,6 +15025,8 @@
case OMPC_match:
case OMPC_nontemporal:
case OMPC_order:
+ case OMPC_novariants:
+ case OMPC_nocontext:
case OMPC_detach:
case OMPC_inclusive:
case OMPC_exclusive:
@@ -13794,9 +15134,270 @@
return new (Context) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
}
-OMPClause *Sema::ActOnOpenMPDestroyClause(SourceLocation StartLoc,
+StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+
+ // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
+ // At least one action-clause must appear on a directive.
+ if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
+ StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
+ Diag(StartLoc, diag::err_omp_no_clause_for_directive)
+ << Expected << getOpenMPDirectiveName(OMPD_interop);
+ return StmtError();
+ }
+
+ // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
+ // A depend clause can only appear on the directive if a targetsync
+ // interop-type is present or the interop-var was initialized with
+ // the targetsync interop-type.
+
+ // If there is any 'init' clause diagnose if there is no 'init' clause with
+ // interop-type of 'targetsync'. Cases involving other directives cannot be
+ // diagnosed.
+ const OMPDependClause *DependClause = nullptr;
+ bool HasInitClause = false;
+ bool IsTargetSync = false;
+ for (const OMPClause *C : Clauses) {
+ if (IsTargetSync)
+ break;
+ if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
+ HasInitClause = true;
+ if (InitClause->getIsTargetSync())
+ IsTargetSync = true;
+ } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
+ DependClause = DC;
+ }
+ }
+ if (DependClause && HasInitClause && !IsTargetSync) {
+ Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
+ return StmtError();
+ }
+
+ // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
+ // Each interop-var may be specified for at most one action-clause of each
+ // interop construct.
+ llvm::SmallPtrSet<const VarDecl *, 4> InteropVars;
+ for (const OMPClause *C : Clauses) {
+ OpenMPClauseKind ClauseKind = C->getClauseKind();
+ const DeclRefExpr *DRE = nullptr;
+ SourceLocation VarLoc;
+
+ if (ClauseKind == OMPC_init) {
+ const auto *IC = cast<OMPInitClause>(C);
+ VarLoc = IC->getVarLoc();
+ DRE = dyn_cast_or_null<DeclRefExpr>(IC->getInteropVar());
+ } else if (ClauseKind == OMPC_use) {
+ const auto *UC = cast<OMPUseClause>(C);
+ VarLoc = UC->getVarLoc();
+ DRE = dyn_cast_or_null<DeclRefExpr>(UC->getInteropVar());
+ } else if (ClauseKind == OMPC_destroy) {
+ const auto *DC = cast<OMPDestroyClause>(C);
+ VarLoc = DC->getVarLoc();
+ DRE = dyn_cast_or_null<DeclRefExpr>(DC->getInteropVar());
+ }
+
+ if (!DRE)
+ continue;
+
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (!InteropVars.insert(VD->getCanonicalDecl()).second) {
+ Diag(VarLoc, diag::err_omp_interop_var_multiple_actions) << VD;
+ return StmtError();
+ }
+ }
+ }
+
+ return OMPInteropDirective::Create(Context, StartLoc, EndLoc, Clauses);
+}
+
+static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
+ SourceLocation VarLoc,
+ OpenMPClauseKind Kind) {
+ if (InteropVarExpr->isValueDependent() || InteropVarExpr->isTypeDependent() ||
+ InteropVarExpr->isInstantiationDependent() ||
+ InteropVarExpr->containsUnexpandedParameterPack())
+ return true;
+
+ const auto *DRE = dyn_cast<DeclRefExpr>(InteropVarExpr);
+ if (!DRE || !isa<VarDecl>(DRE->getDecl())) {
+ SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected) << 0;
+ return false;
+ }
+
+ // Interop variable should be of type omp_interop_t.
+ bool HasError = false;
+ QualType InteropType;
+ LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
+ VarLoc, Sema::LookupOrdinaryName);
+ if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
+ NamedDecl *ND = Result.getFoundDecl();
+ if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
+ InteropType = QualType(TD->getTypeForDecl(), 0);
+ } else {
+ HasError = true;
+ }
+ } else {
+ HasError = true;
+ }
+
+ if (HasError) {
+ SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
+ << "omp_interop_t";
+ return false;
+ }
+
+ QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
+ if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
+ SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
+ return false;
+ }
+
+ // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
+ // The interop-var passed to init or destroy must be non-const.
+ if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
+ isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
+ SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
+ << /*non-const*/ 1;
+ return false;
+ }
+ return true;
+}
+
+OMPClause *
+Sema::ActOnOpenMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs,
+ bool IsTarget, bool IsTargetSync,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation VarLoc, SourceLocation EndLoc) {
+
+ if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_init))
+ return nullptr;
+
+ // Check prefer_type values. These foreign-runtime-id values are either
+ // string literals or constant integral expressions.
+ for (const Expr *E : PrefExprs) {
+ if (E->isValueDependent() || E->isTypeDependent() ||
+ E->isInstantiationDependent() || E->containsUnexpandedParameterPack())
+ continue;
+ if (E->isIntegerConstantExpr(Context))
+ continue;
+ if (isa<StringLiteral>(E))
+ continue;
+ Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
+ return nullptr;
+ }
+
+ return OMPInitClause::Create(Context, InteropVar, PrefExprs, IsTarget,
+ IsTargetSync, StartLoc, LParenLoc, VarLoc,
+ EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation VarLoc,
+ SourceLocation EndLoc) {
+
+ if (!isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_use))
+ return nullptr;
+
+ return new (Context)
+ OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPDestroyClause(Expr *InteropVar,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation VarLoc,
SourceLocation EndLoc) {
- return new (Context) OMPDestroyClause(StartLoc, EndLoc);
+ if (InteropVar &&
+ !isValidInteropVariable(*this, InteropVar, VarLoc, OMPC_destroy))
+ return nullptr;
+
+ return new (Context)
+ OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNovariantsClause(Expr *Condition,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Condition;
+ Stmt *HelperValStmt = nullptr;
+ OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
+ if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
+ !Condition->isInstantiationDependent() &&
+ !Condition->containsUnexpandedParameterPack()) {
+ ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
+ if (Val.isInvalid())
+ return nullptr;
+
+ ValExpr = MakeFullExpr(Val.get()).get();
+
+ OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
+ CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
+ LangOpts.OpenMP);
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
+ ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
+ HelperValStmt = buildPreInits(Context, Captures);
+ }
+ }
+
+ return new (Context) OMPNovariantsClause(
+ ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPNocontextClause(Expr *Condition,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = Condition;
+ Stmt *HelperValStmt = nullptr;
+ OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
+ if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
+ !Condition->isInstantiationDependent() &&
+ !Condition->containsUnexpandedParameterPack()) {
+ ExprResult Val = CheckBooleanCondition(StartLoc, Condition);
+ if (Val.isInvalid())
+ return nullptr;
+
+ ValExpr = MakeFullExpr(Val.get()).get();
+
+ OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
+ CaptureRegion =
+ getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext, LangOpts.OpenMP);
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
+ ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
+ HelperValStmt = buildPreInits(Context, Captures);
+ }
+ }
+
+ return new (Context) OMPNocontextClause(ValExpr, HelperValStmt, CaptureRegion,
+ StartLoc, LParenLoc, EndLoc);
+}
+
+OMPClause *Sema::ActOnOpenMPFilterClause(Expr *ThreadID,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ Expr *ValExpr = ThreadID;
+ Stmt *HelperValStmt = nullptr;
+
+ OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
+ OpenMPDirectiveKind CaptureRegion =
+ getOpenMPCaptureRegionForClause(DKind, OMPC_filter, LangOpts.OpenMP);
+ if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) {
+ ValExpr = MakeFullExpr(ValExpr).get();
+ llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
+ ValExpr = tryBuildCapture(*this, ValExpr, Captures).get();
+ HelperValStmt = buildPreInits(Context, Captures);
+ }
+
+ return new (Context) OMPFilterClause(ValExpr, HelperValStmt, CaptureRegion,
+ StartLoc, LParenLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPVarListClause(
@@ -13926,6 +15527,7 @@
case OMPC_num_threads:
case OMPC_safelen:
case OMPC_simdlen:
+ case OMPC_sizes:
case OMPC_allocator:
case OMPC_collapse:
case OMPC_default:
@@ -13968,6 +15570,8 @@
case OMPC_match:
case OMPC_order:
case OMPC_destroy:
+ case OMPC_novariants:
+ case OMPC_nocontext:
case OMPC_detach:
case OMPC_uses_allocators:
default:
@@ -15094,6 +16698,21 @@
return true;
}
+static BinaryOperatorKind
+getRelatedCompoundReductionOp(BinaryOperatorKind BOK) {
+ if (BOK == BO_Add)
+ return BO_AddAssign;
+ if (BOK == BO_Mul)
+ return BO_MulAssign;
+ if (BOK == BO_And)
+ return BO_AndAssign;
+ if (BOK == BO_Or)
+ return BO_OrAssign;
+ if (BOK == BO_Xor)
+ return BO_XorAssign;
+ return BOK;
+}
+
static bool actOnOMPReductionKindClause(
Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
@@ -15440,7 +17059,8 @@
// (type of the variable or single array element).
PrivateTy = Context.getVariableArrayType(
Type,
- new (Context) OpaqueValueExpr(ELoc, Context.getSizeType(), VK_RValue),
+ new (Context)
+ OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
ArrayType::Normal, /*IndexTypeQuals=*/0, SourceRange());
} else if (!ASE && !OASE &&
Context.getAsArrayType(D->getType().getNonReferenceType())) {
@@ -15459,7 +17079,6 @@
auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
if (DRD->getInitializer()) {
- S.ActOnUninitializedDecl(PrivateVD);
Init = DRDRef;
RHSVD->setInit(DRDRef);
RHSVD->setInitStyle(VarDecl::CallInit);
@@ -15581,8 +17200,7 @@
}
if (RHSVD->isInvalidDecl())
continue;
- if (!RHSVD->hasInit() &&
- (DeclareReductionRef.isUnset() || !S.LangOpts.CPlusPlus)) {
+ if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
<< Type << ReductionIdRange;
bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
@@ -15613,32 +17231,42 @@
QualType Params[] = {PtrRedTy, PtrRedTy};
QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
auto *OVE = new (Context) OpaqueValueExpr(
- ELoc, Context.getPointerType(FnTy), VK_RValue, OK_Ordinary,
+ ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
Expr *Args[] = {LHS.get(), RHS.get()};
ReductionOp =
- CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc,
+ CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
S.CurFPFeatureOverrides());
} else {
- ReductionOp = S.BuildBinOp(
- Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE);
- if (ReductionOp.isUsable()) {
- if (BOK != BO_LT && BOK != BO_GT) {
- ReductionOp =
- S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
- BO_Assign, LHSDRE, ReductionOp.get());
- } else {
- auto *ConditionalOp = new (Context)
- ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc, RHSDRE,
- Type, VK_LValue, OK_Ordinary);
- ReductionOp =
- S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
- BO_Assign, LHSDRE, ConditionalOp);
- }
- if (ReductionOp.isUsable())
- ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
- /*DiscardedValue*/ false);
+ BinaryOperatorKind CombBOK = getRelatedCompoundReductionOp(BOK);
+ if (Type->isRecordType() && CombBOK != BOK) {
+ Sema::TentativeAnalysisScope Trap(S);
+ ReductionOp =
+ S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
+ CombBOK, LHSDRE, RHSDRE);
}
+ if (!ReductionOp.isUsable()) {
+ ReductionOp =
+ S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
+ LHSDRE, RHSDRE);
+ if (ReductionOp.isUsable()) {
+ if (BOK != BO_LT && BOK != BO_GT) {
+ ReductionOp =
+ S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
+ BO_Assign, LHSDRE, ReductionOp.get());
+ } else {
+ auto *ConditionalOp = new (Context)
+ ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
+ RHSDRE, Type, VK_LValue, OK_Ordinary);
+ ReductionOp =
+ S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
+ BO_Assign, LHSDRE, ConditionalOp);
+ }
+ }
+ }
+ if (ReductionOp.isUsable())
+ ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
+ /*DiscardedValue*/ false);
if (!ReductionOp.isUsable())
continue;
}
@@ -15671,7 +17299,7 @@
} else {
// Build temp array for prefix sum.
auto *Dim = new (S.Context)
- OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_RValue);
+ OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
QualType ArrayTy =
S.Context.getVariableArrayType(PrivateTy, Dim, ArrayType::Normal,
/*IndexTypeQuals=*/0, {ELoc, ELoc});
@@ -15684,7 +17312,7 @@
TempArrayElem =
S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
auto *Idx = new (S.Context)
- OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_RValue);
+ OpaqueValueExpr(ELoc, S.Context.getSizeType(), VK_PRValue);
TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
ELoc, Idx, ELoc);
}
@@ -17239,6 +18867,14 @@
Components.emplace_back(COCE, nullptr, IsNonContiguous);
return true;
}
+ bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
+ Expr *Source = E->getSourceExpr();
+ if (!Source) {
+ emitErrorMsg();
+ return false;
+ }
+ return Visit(Source);
+ }
bool VisitStmt(Stmt *) {
emitErrorMsg();
return false;
@@ -17318,7 +18954,9 @@
ERange, CKind, &EnclosingExpr,
CurComponents](OMPClauseMappableExprCommon::MappableExprComponentListRef
StackComponents,
- OpenMPClauseKind) {
+ OpenMPClauseKind Kind) {
+ if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
+ return false;
assert(!StackComponents.empty() &&
"Map clause expression with no components!");
assert(StackComponents.back().getAssociatedDeclaration() == VD &&
@@ -17844,6 +19482,7 @@
return MC.getAssociatedDeclaration();
});
assert(I != CurComponents.end() && "Null decl on map clause.");
+ (void)I;
QualType Type;
auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens());
@@ -17872,8 +19511,6 @@
DSAS, Type))
continue;
- Type = I->getAssociatedDeclaration()->getType().getNonReferenceType();
-
if (CKind == OMPC_map) {
// target enter data
// OpenMP [2.10.2, Restrictions, p. 99]
@@ -18358,8 +19995,15 @@
Diag(I->second, diag::note_previous_definition);
Invalid = true;
}
- auto *DMD = OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name,
- MapperType, VN, Clauses, PrevDMD);
+ // Build expressions for implicit maps of data members with 'default'
+ // mappers.
+ SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
+ Clauses.end());
+ if (LangOpts.OpenMP >= 50)
+ processImplicitMapsWithDefaultMappers(*this, DSAStack, ClausesWithImplicit);
+ auto *DMD =
+ OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, MapperType, VN,
+ ClausesWithImplicit, PrevDMD);
if (S)
PushOnScopeChains(DMD, S);
else
@@ -18396,8 +20040,13 @@
bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const {
assert(LangOpts.OpenMP && "Expected OpenMP mode.");
const Expr *Ref = DSAStack->getDeclareMapperVarRef();
- if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref))
- return VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl();
+ if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
+ if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
+ return true;
+ if (VD->isUsableInConstantExpressions(Context))
+ return true;
+ return false;
+ }
return true;
}
@@ -18738,7 +20387,8 @@
OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
}
-bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) {
+bool Sema::ActOnStartOpenMPDeclareTargetContext(
+ DeclareTargetContextInfo &DTCI) {
DeclContext *CurLexicalContext = getCurLexicalContext();
if (!CurLexicalContext->isFileContext() &&
!CurLexicalContext->isExternCContext() &&
@@ -18747,23 +20397,30 @@
!isa<ClassTemplateDecl>(CurLexicalContext) &&
!isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
!isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
- Diag(Loc, diag::err_omp_region_not_file_context);
+ Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
return false;
}
- DeclareTargetNesting.push_back(Loc);
+ DeclareTargetNesting.push_back(DTCI);
return true;
}
-void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
+const Sema::DeclareTargetContextInfo
+Sema::ActOnOpenMPEndDeclareTargetDirective() {
assert(!DeclareTargetNesting.empty() &&
- "Unexpected ActOnFinishOpenMPDeclareTargetDirective");
- DeclareTargetNesting.pop_back();
+ "check isInOpenMPDeclareTargetContext() first!");
+ return DeclareTargetNesting.pop_back_val();
}
-NamedDecl *
-Sema::lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec,
- const DeclarationNameInfo &Id,
- NamedDeclSetType &SameDirectiveDecls) {
+void Sema::ActOnFinishedOpenMPDeclareTargetContext(
+ DeclareTargetContextInfo &DTCI) {
+ for (auto &It : DTCI.ExplicitlyMapped)
+ ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT,
+ DTCI.DT);
+}
+
+NamedDecl *Sema::lookupOpenMPDeclareTargetName(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id) {
LookupResult Lookup(*this, Id, LookupOrdinaryName);
LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
@@ -18792,8 +20449,6 @@
Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
return nullptr;
}
- if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl())))
- Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName();
return ND;
}
@@ -18810,32 +20465,35 @@
(ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
Diag(Loc, diag::warn_omp_declare_target_after_first_use);
+ // Explicit declare target lists have precedence.
+ const unsigned Level = -1;
+
auto *VD = cast<ValueDecl>(ND);
- Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
- OMPDeclareTargetDeclAttr::getDeviceType(VD);
- Optional<SourceLocation> AttrLoc = OMPDeclareTargetDeclAttr::getLocation(VD);
- if (DevTy.hasValue() && *DevTy != DT &&
- (DeclareTargetNesting.empty() ||
- *AttrLoc != DeclareTargetNesting.back())) {
+ llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
+ OMPDeclareTargetDeclAttr::getActiveAttr(VD);
+ if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getDevType() != DT &&
+ ActiveAttr.getValue()->getLevel() == Level) {
Diag(Loc, diag::err_omp_device_type_mismatch)
<< OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DT)
- << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(*DevTy);
+ << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
+ ActiveAttr.getValue()->getDevType());
return;
}
- Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
- OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
- if (!Res || (!DeclareTargetNesting.empty() &&
- *AttrLoc == DeclareTargetNesting.back())) {
- auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- Context, MT, DT, DeclareTargetNesting.size() + 1,
- SourceRange(Loc, Loc));
- ND->addAttr(A);
- if (ASTMutationListener *ML = Context.getASTMutationListener())
- ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
- checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
- } else if (*Res != MT) {
+ if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getMapType() != MT &&
+ ActiveAttr.getValue()->getLevel() == Level) {
Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
+ return;
}
+
+ if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getLevel() == Level)
+ return;
+
+ auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT, DT, Level,
+ SourceRange(Loc, Loc));
+ ND->addAttr(A);
+ if (ASTMutationListener *ML = Context.getASTMutationListener())
+ ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
+ checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
}
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
@@ -18849,8 +20507,6 @@
(SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
VD->hasGlobalStorage()) {
- llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
- OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
if (!MapTy || *MapTy != OMPDeclareTargetDeclAttr::MT_To) {
// OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
// If a lambda declaration and definition appears between a
@@ -18914,15 +20570,19 @@
if ((E || !VD->getType()->isIncompleteType()) &&
!checkValueDeclInTarget(SL, SR, *this, DSAStack, VD))
return;
- if (!E && !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
+ if (!E && isInOpenMPDeclareTargetContext()) {
// Checking declaration inside declare target region.
if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
isa<FunctionTemplateDecl>(D)) {
+ llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
+ OMPDeclareTargetDeclAttr::getActiveAttr(VD);
+ unsigned Level = DeclareTargetNesting.size();
+ if (ActiveAttr.hasValue() && ActiveAttr.getValue()->getLevel() >= Level)
+ return;
+ DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
- Context, OMPDeclareTargetDeclAttr::MT_To,
- OMPDeclareTargetDeclAttr::DT_Any, DeclareTargetNesting.size(),
- SourceRange(DeclareTargetNesting.back(),
- DeclareTargetNesting.back()));
+ Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, Level,
+ SourceRange(DTCI.Loc, DTCI.Loc));
D->addAttr(A);
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
diff --git a/src/llvm-project/clang/lib/Sema/SemaOverload.cpp b/src/llvm-project/clang/lib/Sema/SemaOverload.cpp
index 7fe7466..0758fbb 100644
--- a/src/llvm-project/clang/lib/Sema/SemaOverload.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaOverload.cpp
@@ -3346,10 +3346,7 @@
bool Usable = !Info.Constructor->isInvalidDecl() &&
S.isInitListConstructor(Info.Constructor);
if (Usable) {
- // If the first argument is (a reference to) the target type,
- // suppress conversions.
- bool SuppressUserConversions = isFirstArgumentCompatibleWithType(
- S.Context, Info.Constructor, ToType);
+ bool SuppressUserConversions = false;
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr, From,
@@ -3473,14 +3470,18 @@
/*AllowExplicit*/ true);
if (Usable) {
bool SuppressUserConversions = !ConstructorsOnly;
+ // C++20 [over.best.ics.general]/4.5:
+ // if the target is the first parameter of a constructor [of class
+ // X] and the constructor [...] is a candidate by [...] the second
+ // phase of [over.match.list] when the initializer list has exactly
+ // one element that is itself an initializer list, [...] and the
+ // conversion is to X or reference to cv X, user-defined conversion
+ // sequences are not cnosidered.
if (SuppressUserConversions && ListInitializing) {
- SuppressUserConversions = false;
- if (NumArgs == 1) {
- // If the first argument is (a reference to) the target type,
- // suppress conversions.
- SuppressUserConversions = isFirstArgumentCompatibleWithType(
- S.Context, Info.Constructor, ToType);
- }
+ SuppressUserConversions =
+ NumArgs == 1 && isa<InitListExpr>(Args[0]) &&
+ isFirstArgumentCompatibleWithType(S.Context, Info.Constructor,
+ ToType);
}
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(
@@ -3706,7 +3707,7 @@
CallOp->getType()->getAs<FunctionProtoType>();
CallingConv CallOpCC =
- CallOp->getType()->getAs<FunctionType>()->getCallConv();
+ CallOp->getType()->castAs<FunctionType>()->getCallConv();
CallingConv DefaultFree = S.Context.getDefaultCallingConvention(
CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
CallingConv DefaultMember = S.Context.getDefaultCallingConvention(
@@ -3927,7 +3928,7 @@
if (!FromType->isEnumeralType())
return FixedEnumPromotion::None;
- EnumDecl *Enum = FromType->getAs<EnumType>()->getDecl();
+ EnumDecl *Enum = FromType->castAs<EnumType>()->getDecl();
if (!Enum->isFixed())
return FixedEnumPromotion::None;
@@ -4106,7 +4107,7 @@
}
}
- // In Microsoft mode, prefer an integral conversion to a
+ // In Microsoft mode (below 19.28), prefer an integral conversion to a
// floating-to-integral conversion if the integral conversion
// is between types of the same size.
// For example:
@@ -4118,7 +4119,9 @@
// }
// Here, MSVC will call f(int) instead of generating a compile error
// as clang will do in standard mode.
- if (S.getLangOpts().MSVCCompat && SCS1.Second == ICK_Integral_Conversion &&
+ if (S.getLangOpts().MSVCCompat &&
+ !S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2019_8) &&
+ SCS1.Second == ICK_Integral_Conversion &&
SCS2.Second == ICK_Floating_Integral &&
S.Context.getTypeSize(SCS1.getFromType()) ==
S.Context.getTypeSize(SCS1.getToType(2)))
@@ -5431,8 +5434,8 @@
DestType = ImplicitParamRecordType;
FromClassification = From->Classify(Context);
- // When performing member access on an rvalue, materialize a temporary.
- if (From->isRValue()) {
+ // When performing member access on a prvalue, materialize a temporary.
+ if (From->isPRValue()) {
From = CreateMaterializeTemporaryExpr(FromRecordType, From,
Method->getRefQualifier() !=
RefQualifierKind::RQ_RValue);
@@ -5631,12 +5634,8 @@
// implicitly converted to type T, where the converted
// expression is a constant expression and the implicit conversion
// sequence contains only [... list of conversions ...].
- // C++1z [stmt.if]p2:
- // If the if statement is of the form if constexpr, the value of the
- // condition shall be a contextually converted constant expression of type
- // bool.
ImplicitConversionSequence ICS =
- CCE == Sema::CCEK_ConstexprIf || CCE == Sema::CCEK_ExplicitBool
+ CCE == Sema::CCEK_ExplicitBool
? TryContextuallyConvertToBool(S, From)
: TryCopyInitialization(S, From, T,
/*SuppressUserConversions=*/false,
@@ -6479,12 +6478,6 @@
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
-
- if (LangOpts.OpenCL && isOpenCLDisabledDecl(Function)) {
- Candidate.Viable = false;
- Candidate.FailureKind = ovl_fail_ext_disabled;
- return;
- }
}
ObjCMethodDecl *
@@ -7374,7 +7367,7 @@
ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
Context.getPointerType(Conversion->getType()),
CK_FunctionToPointerDecay, &ConversionRef,
- VK_RValue, FPOptionsOverride());
+ VK_PRValue, FPOptionsOverride());
QualType ConversionType = Conversion->getConversionType();
if (!isCompleteType(From->getBeginLoc(), ConversionType)) {
@@ -8469,7 +8462,7 @@
// bool operator==(T, T);
// bool operator!=(T, T);
// R operator<=>(T, T)
- void addGenericBinaryPointerOrEnumeralOverloads() {
+ void addGenericBinaryPointerOrEnumeralOverloads(bool IsSpaceship) {
// C++ [over.match.oper]p3:
// [...]the built-in candidates include all of the candidate operator
// functions defined in 13.6 that, compared to the given operator, [...]
@@ -8528,6 +8521,8 @@
// Don't add the same builtin candidate twice.
if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
+ if (IsSpaceship && PtrTy->isFunctionPointerType())
+ continue;
QualType ParamTypes[2] = {PtrTy, PtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
@@ -8718,7 +8713,7 @@
//
// where LR is the result of the usual arithmetic conversions
// between types L and R.
- void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) {
+ void addBinaryBitwiseArithmeticOverloads() {
if (!HasArithmeticOrEnumeralCandidateType)
return;
@@ -9224,18 +9219,20 @@
case OO_EqualEqual:
case OO_ExclaimEqual:
OpBuilder.addEqualEqualOrNotEqualMemberPointerOrNullptrOverloads();
- LLVM_FALLTHROUGH;
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/false);
+ OpBuilder.addGenericBinaryArithmeticOverloads();
+ break;
case OO_Less:
case OO_Greater:
case OO_LessEqual:
case OO_GreaterEqual:
- OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/false);
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
case OO_Spaceship:
- OpBuilder.addGenericBinaryPointerOrEnumeralOverloads();
+ OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(/*IsSpaceship=*/true);
OpBuilder.addThreeWayArithmeticOverloads();
break;
@@ -9244,7 +9241,7 @@
case OO_Pipe:
case OO_LessLess:
case OO_GreaterGreater:
- OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+ OpBuilder.addBinaryBitwiseArithmeticOverloads();
break;
case OO_Amp: // '&' is either unary or binary
@@ -9254,7 +9251,7 @@
// operator '->', the built-in candidates set is empty.
break;
- OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+ OpBuilder.addBinaryBitwiseArithmeticOverloads();
break;
case OO_Tilde:
@@ -9870,6 +9867,23 @@
S.IdentifyCUDAPreference(Caller, Cand2.Function);
}
+ // General member function overloading is handled above, so this only handles
+ // constructors with address spaces.
+ // This only handles address spaces since C++ has no other
+ // qualifier that can be used with constructors.
+ const auto *CD1 = dyn_cast_or_null<CXXConstructorDecl>(Cand1.Function);
+ const auto *CD2 = dyn_cast_or_null<CXXConstructorDecl>(Cand2.Function);
+ if (CD1 && CD2) {
+ LangAS AS1 = CD1->getMethodQualifiers().getAddressSpace();
+ LangAS AS2 = CD2->getMethodQualifiers().getAddressSpace();
+ if (AS1 != AS2) {
+ if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+ return true;
+ if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+ return false;
+ }
+ }
+
return false;
}
@@ -10242,10 +10256,10 @@
CXXMethodDecl *CallOp = RD->getLambdaCallOperator();
CallingConv CallOpCC =
- CallOp->getType()->getAs<FunctionType>()->getCallConv();
- QualType ConvRTy = ConvD->getType()->getAs<FunctionType>()->getReturnType();
+ CallOp->getType()->castAs<FunctionType>()->getCallConv();
+ QualType ConvRTy = ConvD->getType()->castAs<FunctionType>()->getReturnType();
CallingConv ConvToCC =
- ConvRTy->getPointeeType()->getAs<FunctionType>()->getCallConv();
+ ConvRTy->getPointeeType()->castAs<FunctionType>()->getCallConv();
return ConvToCC != CallOpCC;
}
@@ -10355,18 +10369,15 @@
const PartialDiagnostic &PDiag) const {
S.Diag(CaretLoc, PDiag)
<< Ambiguous.getFromType() << Ambiguous.getToType();
- // FIXME: The note limiting machinery is borrowed from
- // OverloadCandidateSet::NoteCandidates; there's an opportunity for
- // refactoring here.
- const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
unsigned CandsShown = 0;
AmbiguousConversionSequence::const_iterator I, E;
for (I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) {
- if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
+ if (CandsShown >= S.Diags.getNumOverloadCandidatesToShow())
break;
++CandsShown;
S.NoteOverloadCandidate(I->first, I->second);
}
+ S.Diags.overloadCandidatesShown(CandsShown);
if (I != E)
S.Diag(SourceLocation(), diag::note_ovl_too_many_candidates) << int(E - I);
}
@@ -11092,14 +11103,6 @@
<< (ES.getExpr() ? ES.getExpr()->getSourceRange() : SourceRange());
}
-static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) {
- FunctionDecl *Callee = Cand->Function;
-
- S.Diag(Callee->getLocation(),
- diag::note_ovl_candidate_disabled_by_extension)
- << S.getOpenCLExtensionsFromDeclExtMap(Callee);
-}
-
/// Generates a 'note' diagnostic for an overload candidate. We've
/// already generated a primary error at the call site.
///
@@ -11195,9 +11198,6 @@
case ovl_fail_explicit:
return DiagnoseFailedExplicitSpec(S, Cand);
- case ovl_fail_ext_disabled:
- return DiagnoseOpenCLExtensionDisabled(S, Cand);
-
case ovl_fail_inhctor_slice:
// It's generally not interesting to note copy/move constructors here.
if (cast<CXXConstructorDecl>(Fn)->isCopyOrMoveConstructor())
@@ -11641,10 +11641,11 @@
CompleteCandidates(S, OCD_AllCandidates, Args, OpLoc, [](auto &Cand) {
return (Cand.Viable == false &&
Cand.FailureKind == ovl_fail_bad_target) ||
- (Cand.Function->template hasAttr<CUDAHostAttr>() &&
+ (Cand.Function &&
+ Cand.Function->template hasAttr<CUDAHostAttr>() &&
Cand.Function->template hasAttr<CUDADeviceAttr>());
});
- DeferHint = WrongSidedCands.size();
+ DeferHint = !WrongSidedCands.empty();
}
return DeferHint;
}
@@ -11677,10 +11678,8 @@
for (; I != E; ++I) {
OverloadCandidate *Cand = *I;
- // Set an arbitrary limit on the number of candidate functions we'll spam
- // the user with. FIXME: This limit should depend on details of the
- // candidate list.
- if (CandsShown >= 4 && ShowOverloads == Ovl_Best) {
+ if (CandsShown >= S.Diags.getNumOverloadCandidatesToShow() &&
+ ShowOverloads == Ovl_Best) {
break;
}
++CandsShown;
@@ -11709,6 +11708,10 @@
}
}
+ // Inform S.Diags that we've shown an overload set with N elements. This may
+ // inform the future value of S.Diags.getNumOverloadCandidatesToShow().
+ S.Diags.overloadCandidatesShown(CandsShown);
+
if (I != E)
S.Diag(OpLoc, diag::note_ovl_too_many_candidates,
shouldDeferDiags(S, Args, OpLoc))
@@ -12998,7 +13001,7 @@
// lookup to instantiation time to be able to search into type dependent
// base classes.
CallExpr *CE =
- CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_RValue,
+ CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_PRValue,
RParenLoc, CurFPFeatureOverrides());
CE->markDependentForPostponedNameLookup();
*Result = CE;
@@ -13256,7 +13259,7 @@
if (Input->isTypeDependent()) {
if (Fns.empty())
return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
- VK_RValue, OK_Ordinary, OpLoc, false,
+ VK_PRValue, OK_Ordinary, OpLoc, false,
CurFPFeatureOverrides());
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
@@ -13265,7 +13268,7 @@
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray,
- Context.DependentTy, VK_RValue, OpLoc,
+ Context.DependentTy, VK_PRValue, OpLoc,
CurFPFeatureOverrides());
}
@@ -13513,9 +13516,9 @@
Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy,
Context.DependentTy);
- return BinaryOperator::Create(Context, Args[0], Args[1], Opc,
- Context.DependentTy, VK_RValue, OK_Ordinary,
- OpLoc, CurFPFeatureOverrides());
+ return BinaryOperator::Create(
+ Context, Args[0], Args[1], Opc, Context.DependentTy, VK_PRValue,
+ OK_Ordinary, OpLoc, CurFPFeatureOverrides());
}
// FIXME: save results of ADL from here?
@@ -13528,7 +13531,7 @@
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), Args,
- Context.DependentTy, VK_RValue, OpLoc,
+ Context.DependentTy, VK_PRValue, OpLoc,
CurFPFeatureOverrides());
}
@@ -13716,6 +13719,15 @@
if (Op == OO_Equal)
DiagnoseSelfMove(Args[0], Args[1], OpLoc);
+ if (ImplicitThis) {
+ QualType ThisType = Context.getPointerType(ImplicitThis->getType());
+ QualType ThisTypeFromDecl = Context.getPointerType(
+ cast<CXXMethodDecl>(FnDecl)->getThisObjectType());
+
+ CheckArgAlignment(OpLoc, FnDecl, "'this'", ThisType,
+ ThisTypeFromDecl);
+ }
+
checkCall(FnDecl, nullptr, ImplicitThis, ArgsArray,
isa<CXXMethodDecl>(FnDecl), OpLoc, TheCall->getSourceRange(),
VariadicDoesNotApply);
@@ -13809,6 +13821,8 @@
StringRef OpcStr = BinaryOperator::getOpcodeStr(Opc);
auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates,
Args, OpLoc);
+ DeferDiagsRAII DDR(*this,
+ CandidateSet.shouldDeferDiags(*this, Args, OpLoc));
if (Args[0]->getType()->isRecordType() &&
Opc >= BO_Assign && Opc <= BO_OrAssign) {
Diag(OpLoc, diag::err_ovl_no_viable_oper)
@@ -13998,7 +14012,7 @@
// Can't add any actual overloads yet
return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn.get(), Args,
- Context.DependentTy, VK_RValue, RLoc,
+ Context.DependentTy, VK_PRValue, RLoc,
CurFPFeatureOverrides());
}
@@ -14221,7 +14235,7 @@
Type);
};
if (isa<CXXPseudoDestructorExpr>(NakedMemExpr))
- return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue,
+ return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_PRValue,
RParenLoc, CurFPFeatureOverrides());
UnbridgedCastsSet UnbridgedCasts;
@@ -14606,7 +14620,7 @@
// Record usage of conversion in an implicit cast.
Call = ImplicitCastExpr::Create(
Context, Call.get()->getType(), CK_UserDefinedConversion, Call.get(),
- nullptr, VK_RValue, CurFPFeatureOverrides());
+ nullptr, VK_PRValue, CurFPFeatureOverrides());
return BuildCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc);
}
@@ -15074,7 +15088,7 @@
(void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType);
return UnaryOperator::Create(
- Context, SubExpr, UO_AddrOf, MemPtrType, VK_RValue, OK_Ordinary,
+ Context, SubExpr, UO_AddrOf, MemPtrType, VK_PRValue, OK_Ordinary,
UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
}
}
@@ -15083,10 +15097,10 @@
if (SubExpr == UnOp->getSubExpr())
return UnOp;
- return UnaryOperator::Create(Context, SubExpr, UO_AddrOf,
- Context.getPointerType(SubExpr->getType()),
- VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(),
- false, CurFPFeatureOverrides());
+ return UnaryOperator::Create(
+ Context, SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()),
+ VK_PRValue, OK_Ordinary, UnOp->getOperatorLoc(), false,
+ CurFPFeatureOverrides());
}
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
@@ -15141,7 +15155,7 @@
valueKind = VK_LValue;
type = Fn->getType();
} else {
- valueKind = VK_RValue;
+ valueKind = VK_PRValue;
type = Context.BoundMemberTy;
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaPseudoObject.cpp b/src/llvm-project/clang/lib/Sema/SemaPseudoObject.cpp
index d17599a..7fdb349 100644
--- a/src/llvm-project/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaPseudoObject.cpp
@@ -835,7 +835,7 @@
// As a special case, if the method returns 'id', try to get
// a better type from the property.
- if (RefExpr->isExplicitProperty() && result.get()->isRValue()) {
+ if (RefExpr->isExplicitProperty() && result.get()->isPRValue()) {
QualType receiverType = RefExpr->getReceiverType(S.Context);
QualType propType = RefExpr->getExplicitProperty()
->getUsageType(receiverType);
@@ -1554,7 +1554,7 @@
// Do nothing if the operand is dependent.
if (op->isTypeDependent())
return UnaryOperator::Create(Context, op, opcode, Context.DependentTy,
- VK_RValue, OK_Ordinary, opcLoc, false,
+ VK_PRValue, OK_Ordinary, opcLoc, false,
CurFPFeatureOverrides());
assert(UnaryOperator::isIncrementDecrementOp(opcode));
@@ -1585,7 +1585,7 @@
// Do nothing if either argument is dependent.
if (LHS->isTypeDependent() || RHS->isTypeDependent())
return BinaryOperator::Create(Context, LHS, RHS, opcode,
- Context.DependentTy, VK_RValue, OK_Ordinary,
+ Context.DependentTy, VK_PRValue, OK_Ordinary,
opcLoc, CurFPFeatureOverrides());
// Filter out non-overload placeholder types in the RHS.
diff --git a/src/llvm-project/clang/lib/Sema/SemaSYCL.cpp b/src/llvm-project/clang/lib/Sema/SemaSYCL.cpp
index af35052..3b48a53 100644
--- a/src/llvm-project/clang/lib/Sema/SemaSYCL.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaSYCL.cpp
@@ -8,6 +8,7 @@
// This implements Semantic Analysis for SYCL constructs.
//===----------------------------------------------------------------------===//
+#include "clang/AST/Mangle.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
@@ -47,3 +48,35 @@
return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;
}
+
+// The SYCL kernel's 'object type' used for diagnostics and naming/mangling is
+// the first parameter to a sycl_kernel labeled function template. In SYCL1.2.1,
+// this was passed by value, and in SYCL2020, it is passed by reference.
+static QualType GetSYCLKernelObjectType(const FunctionDecl *KernelCaller) {
+ assert(KernelCaller->getNumParams() > 0 && "Insufficient kernel parameters");
+ QualType KernelParamTy = KernelCaller->getParamDecl(0)->getType();
+
+ // SYCL 2020 kernels are passed by reference.
+ if (KernelParamTy->isReferenceType())
+ return KernelParamTy->getPointeeType();
+
+ // SYCL 1.2.1
+ return KernelParamTy;
+}
+
+void Sema::AddSYCLKernelLambda(const FunctionDecl *FD) {
+ auto MangleCallback = [](ASTContext &Ctx,
+ const NamedDecl *ND) -> llvm::Optional<unsigned> {
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(ND))
+ Ctx.AddSYCLKernelNamingDecl(RD);
+ // We always want to go into the lambda mangling (skipping the unnamed
+ // struct version), so make sure we return a value here.
+ return 1;
+ };
+
+ QualType Ty = GetSYCLKernelObjectType(FD);
+ std::unique_ptr<MangleContext> Ctx{ItaniumMangleContext::create(
+ Context, Context.getDiagnostics(), MangleCallback)};
+ llvm::raw_null_ostream Out;
+ Ctx->mangleTypeName(Ty, Out);
+}
diff --git a/src/llvm-project/clang/lib/Sema/SemaStmt.cpp b/src/llvm-project/clang/lib/Sema/SemaStmt.cpp
index b24a8ab..3baccec 100644
--- a/src/llvm-project/clang/lib/Sema/SemaStmt.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaStmt.cpp
@@ -10,17 +10,16 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/Ownership.h"
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTLambda.h"
-#include "clang/AST/CharUnits.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/IgnoreExpr.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
@@ -30,8 +29,10 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Ownership.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
@@ -541,6 +542,12 @@
return SubStmt;
}
+ ReservedIdentifierStatus Status = TheDecl->isReserved(getLangOpts());
+ if (Status != ReservedIdentifierStatus::NotReserved &&
+ !Context.getSourceManager().isInSystemHeader(IdentLoc))
+ Diag(IdentLoc, diag::warn_reserved_extern_symbol)
+ << TheDecl << static_cast<int>(Status);
+
// Otherwise, things are good. Fill in the declaration and return it.
LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
TheDecl->setStmt(LS);
@@ -555,12 +562,286 @@
return LS;
}
-StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
- ArrayRef<const Attr*> Attrs,
+StmtResult Sema::BuildAttributedStmt(SourceLocation AttrsLoc,
+ ArrayRef<const Attr *> Attrs,
Stmt *SubStmt) {
- // Fill in the declaration and return it.
- AttributedStmt *LS = AttributedStmt::Create(Context, AttrLoc, Attrs, SubStmt);
- return LS;
+ // FIXME: this code should move when a planned refactoring around statement
+ // attributes lands.
+ for (const auto *A : Attrs) {
+ if (A->getKind() == attr::MustTail) {
+ if (!checkAndRewriteMustTailAttr(SubStmt, *A)) {
+ return SubStmt;
+ }
+ setFunctionHasMustTail();
+ }
+ }
+
+ return AttributedStmt::Create(Context, AttrsLoc, Attrs, SubStmt);
+}
+
+StmtResult Sema::ActOnAttributedStmt(const ParsedAttributesWithRange &Attrs,
+ Stmt *SubStmt) {
+ SmallVector<const Attr *, 1> SemanticAttrs;
+ ProcessStmtAttributes(SubStmt, Attrs, SemanticAttrs);
+ if (!SemanticAttrs.empty())
+ return BuildAttributedStmt(Attrs.Range.getBegin(), SemanticAttrs, SubStmt);
+ // If none of the attributes applied, that's fine, we can recover by
+ // returning the substatement directly instead of making an AttributedStmt
+ // with no attributes on it.
+ return SubStmt;
+}
+
+bool Sema::checkAndRewriteMustTailAttr(Stmt *St, const Attr &MTA) {
+ ReturnStmt *R = cast<ReturnStmt>(St);
+ Expr *E = R->getRetValue();
+
+ if (CurContext->isDependentContext() || (E && E->isInstantiationDependent()))
+ // We have to suspend our check until template instantiation time.
+ return true;
+
+ if (!checkMustTailAttr(St, MTA))
+ return false;
+
+ // FIXME: Replace Expr::IgnoreImplicitAsWritten() with this function.
+ // Currently it does not skip implicit constructors in an initialization
+ // context.
+ auto IgnoreImplicitAsWritten = [](Expr *E) -> Expr * {
+ return IgnoreExprNodes(E, IgnoreImplicitAsWrittenSingleStep,
+ IgnoreElidableImplicitConstructorSingleStep);
+ };
+
+ // Now that we have verified that 'musttail' is valid here, rewrite the
+ // return value to remove all implicit nodes, but retain parentheses.
+ R->setRetValue(IgnoreImplicitAsWritten(E));
+ return true;
+}
+
+bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) {
+ assert(!CurContext->isDependentContext() &&
+ "musttail cannot be checked from a dependent context");
+
+ // FIXME: Add Expr::IgnoreParenImplicitAsWritten() with this definition.
+ auto IgnoreParenImplicitAsWritten = [](const Expr *E) -> const Expr * {
+ return IgnoreExprNodes(const_cast<Expr *>(E), IgnoreParensSingleStep,
+ IgnoreImplicitAsWrittenSingleStep,
+ IgnoreElidableImplicitConstructorSingleStep);
+ };
+
+ const Expr *E = cast<ReturnStmt>(St)->getRetValue();
+ const auto *CE = dyn_cast_or_null<CallExpr>(IgnoreParenImplicitAsWritten(E));
+
+ if (!CE) {
+ Diag(St->getBeginLoc(), diag::err_musttail_needs_call) << &MTA;
+ return false;
+ }
+
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(E)) {
+ if (EWC->cleanupsHaveSideEffects()) {
+ Diag(St->getBeginLoc(), diag::err_musttail_needs_trivial_args) << &MTA;
+ return false;
+ }
+ }
+
+ // We need to determine the full function type (including "this" type, if any)
+ // for both caller and callee.
+ struct FuncType {
+ enum {
+ ft_non_member,
+ ft_static_member,
+ ft_non_static_member,
+ ft_pointer_to_member,
+ } MemberType = ft_non_member;
+
+ QualType This;
+ const FunctionProtoType *Func;
+ const CXXMethodDecl *Method = nullptr;
+ } CallerType, CalleeType;
+
+ auto GetMethodType = [this, St, MTA](const CXXMethodDecl *CMD, FuncType &Type,
+ bool IsCallee) -> bool {
+ if (isa<CXXConstructorDecl, CXXDestructorDecl>(CMD)) {
+ Diag(St->getBeginLoc(), diag::err_musttail_structors_forbidden)
+ << IsCallee << isa<CXXDestructorDecl>(CMD);
+ if (IsCallee)
+ Diag(CMD->getBeginLoc(), diag::note_musttail_structors_forbidden)
+ << isa<CXXDestructorDecl>(CMD);
+ Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;
+ return false;
+ }
+ if (CMD->isStatic())
+ Type.MemberType = FuncType::ft_static_member;
+ else {
+ Type.This = CMD->getThisType()->getPointeeType();
+ Type.MemberType = FuncType::ft_non_static_member;
+ }
+ Type.Func = CMD->getType()->castAs<FunctionProtoType>();
+ return true;
+ };
+
+ const auto *CallerDecl = dyn_cast<FunctionDecl>(CurContext);
+
+ // Find caller function signature.
+ if (!CallerDecl) {
+ int ContextType;
+ if (isa<BlockDecl>(CurContext))
+ ContextType = 0;
+ else if (isa<ObjCMethodDecl>(CurContext))
+ ContextType = 1;
+ else
+ ContextType = 2;
+ Diag(St->getBeginLoc(), diag::err_musttail_forbidden_from_this_context)
+ << &MTA << ContextType;
+ return false;
+ } else if (const auto *CMD = dyn_cast<CXXMethodDecl>(CurContext)) {
+ // Caller is a class/struct method.
+ if (!GetMethodType(CMD, CallerType, false))
+ return false;
+ } else {
+ // Caller is a non-method function.
+ CallerType.Func = CallerDecl->getType()->getAs<FunctionProtoType>();
+ }
+
+ const Expr *CalleeExpr = CE->getCallee()->IgnoreParens();
+ const auto *CalleeBinOp = dyn_cast<BinaryOperator>(CalleeExpr);
+ SourceLocation CalleeLoc = CE->getCalleeDecl()
+ ? CE->getCalleeDecl()->getBeginLoc()
+ : St->getBeginLoc();
+
+ // Find callee function signature.
+ if (const CXXMethodDecl *CMD =
+ dyn_cast_or_null<CXXMethodDecl>(CE->getCalleeDecl())) {
+ // Call is: obj.method(), obj->method(), functor(), etc.
+ if (!GetMethodType(CMD, CalleeType, true))
+ return false;
+ } else if (CalleeBinOp && CalleeBinOp->isPtrMemOp()) {
+ // Call is: obj->*method_ptr or obj.*method_ptr
+ const auto *MPT =
+ CalleeBinOp->getRHS()->getType()->castAs<MemberPointerType>();
+ CalleeType.This = QualType(MPT->getClass(), 0);
+ CalleeType.Func = MPT->getPointeeType()->castAs<FunctionProtoType>();
+ CalleeType.MemberType = FuncType::ft_pointer_to_member;
+ } else if (isa<CXXPseudoDestructorExpr>(CalleeExpr)) {
+ Diag(St->getBeginLoc(), diag::err_musttail_structors_forbidden)
+ << /* IsCallee = */ 1 << /* IsDestructor = */ 1;
+ Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;
+ return false;
+ } else {
+ // Non-method function.
+ CalleeType.Func =
+ CalleeExpr->getType()->getPointeeType()->getAs<FunctionProtoType>();
+ }
+
+ // Both caller and callee must have a prototype (no K&R declarations).
+ if (!CalleeType.Func || !CallerType.Func) {
+ Diag(St->getBeginLoc(), diag::err_musttail_needs_prototype) << &MTA;
+ if (!CalleeType.Func && CE->getDirectCallee()) {
+ Diag(CE->getDirectCallee()->getBeginLoc(),
+ diag::note_musttail_fix_non_prototype);
+ }
+ if (!CallerType.Func)
+ Diag(CallerDecl->getBeginLoc(), diag::note_musttail_fix_non_prototype);
+ return false;
+ }
+
+ // Caller and callee must have matching calling conventions.
+ //
+ // Some calling conventions are physically capable of supporting tail calls
+ // even if the function types don't perfectly match. LLVM is currently too
+ // strict to allow this, but if LLVM added support for this in the future, we
+ // could exit early here and skip the remaining checks if the functions are
+ // using such a calling convention.
+ if (CallerType.Func->getCallConv() != CalleeType.Func->getCallConv()) {
+ if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl()))
+ Diag(St->getBeginLoc(), diag::err_musttail_callconv_mismatch)
+ << true << ND->getDeclName();
+ else
+ Diag(St->getBeginLoc(), diag::err_musttail_callconv_mismatch) << false;
+ Diag(CalleeLoc, diag::note_musttail_callconv_mismatch)
+ << FunctionType::getNameForCallConv(CallerType.Func->getCallConv())
+ << FunctionType::getNameForCallConv(CalleeType.Func->getCallConv());
+ Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;
+ return false;
+ }
+
+ if (CalleeType.Func->isVariadic() || CallerType.Func->isVariadic()) {
+ Diag(St->getBeginLoc(), diag::err_musttail_no_variadic) << &MTA;
+ return false;
+ }
+
+ // Caller and callee must match in whether they have a "this" parameter.
+ if (CallerType.This.isNull() != CalleeType.This.isNull()) {
+ if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
+ Diag(St->getBeginLoc(), diag::err_musttail_member_mismatch)
+ << CallerType.MemberType << CalleeType.MemberType << true
+ << ND->getDeclName();
+ Diag(CalleeLoc, diag::note_musttail_callee_defined_here)
+ << ND->getDeclName();
+ } else
+ Diag(St->getBeginLoc(), diag::err_musttail_member_mismatch)
+ << CallerType.MemberType << CalleeType.MemberType << false;
+ Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;
+ return false;
+ }
+
+ auto CheckTypesMatch = [this](FuncType CallerType, FuncType CalleeType,
+ PartialDiagnostic &PD) -> bool {
+ enum {
+ ft_different_class,
+ ft_parameter_arity,
+ ft_parameter_mismatch,
+ ft_return_type,
+ };
+
+ auto DoTypesMatch = [this, &PD](QualType A, QualType B,
+ unsigned Select) -> bool {
+ if (!Context.hasSimilarType(A, B)) {
+ PD << Select << A.getUnqualifiedType() << B.getUnqualifiedType();
+ return false;
+ }
+ return true;
+ };
+
+ if (!CallerType.This.isNull() &&
+ !DoTypesMatch(CallerType.This, CalleeType.This, ft_different_class))
+ return false;
+
+ if (!DoTypesMatch(CallerType.Func->getReturnType(),
+ CalleeType.Func->getReturnType(), ft_return_type))
+ return false;
+
+ if (CallerType.Func->getNumParams() != CalleeType.Func->getNumParams()) {
+ PD << ft_parameter_arity << CallerType.Func->getNumParams()
+ << CalleeType.Func->getNumParams();
+ return false;
+ }
+
+ ArrayRef<QualType> CalleeParams = CalleeType.Func->getParamTypes();
+ ArrayRef<QualType> CallerParams = CallerType.Func->getParamTypes();
+ size_t N = CallerType.Func->getNumParams();
+ for (size_t I = 0; I < N; I++) {
+ if (!DoTypesMatch(CalleeParams[I], CallerParams[I],
+ ft_parameter_mismatch)) {
+ PD << static_cast<int>(I) + 1;
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ PartialDiagnostic PD = PDiag(diag::note_musttail_mismatch);
+ if (!CheckTypesMatch(CallerType, CalleeType, PD)) {
+ if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl()))
+ Diag(St->getBeginLoc(), diag::err_musttail_mismatch)
+ << true << ND->getDeclName();
+ else
+ Diag(St->getBeginLoc(), diag::err_musttail_mismatch) << false;
+ Diag(CalleeLoc, PD);
+ Diag(MTA.getLocation(), diag::note_tail_call_required) << &MTA;
+ return false;
+ }
+
+ return true;
}
namespace {
@@ -586,7 +867,7 @@
Cond = ConditionResult(
*this, nullptr,
MakeFullExpr(new (Context) OpaqueValueExpr(SourceLocation(),
- Context.BoolTy, VK_RValue),
+ Context.BoolTy, VK_PRValue),
IfLoc),
false);
@@ -825,8 +1106,8 @@
// type versus "switch expression cannot have this value". Use proper
// IntRange checking rather than just looking at the unpromoted type here.
if (ConvVal != Val)
- S.Diag(Loc, diag::warn_case_value_overflow) << Val.toString(10)
- << ConvVal.toString(10);
+ S.Diag(Loc, diag::warn_case_value_overflow) << toString(Val, 10)
+ << toString(ConvVal, 10);
}
}
@@ -1051,12 +1332,12 @@
if (PrevString == CurrString)
Diag(CaseVals[i].second->getLHS()->getBeginLoc(),
diag::err_duplicate_case)
- << (PrevString.empty() ? StringRef(CaseValStr) : PrevString);
+ << (PrevString.empty() ? CaseValStr.str() : PrevString);
else
Diag(CaseVals[i].second->getLHS()->getBeginLoc(),
diag::err_duplicate_case_differing_expr)
- << (PrevString.empty() ? StringRef(CaseValStr) : PrevString)
- << (CurrString.empty() ? StringRef(CaseValStr) : CurrString)
+ << (PrevString.empty() ? CaseValStr.str() : PrevString)
+ << (CurrString.empty() ? CaseValStr.str() : CurrString)
<< CaseValStr;
Diag(CaseVals[i - 1].second->getLHS()->getBeginLoc(),
@@ -1151,7 +1432,7 @@
if (OverlapStmt) {
// If we have a duplicate, report it.
Diag(CR->getLHS()->getBeginLoc(), diag::err_duplicate_case)
- << OverlapVal.toString(10);
+ << toString(OverlapVal, 10);
Diag(OverlapStmt->getLHS()->getBeginLoc(),
diag::note_duplicate_case_prev);
// FIXME: We really want to remove the bogus case stmt from the
@@ -1167,7 +1448,7 @@
// TODO: it would be nice if we printed enums as enums, chars as
// chars, etc.
Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition)
- << ConstantCondValue.toString(10)
+ << toString(ConstantCondValue, 10)
<< CondExpr->getSourceRange();
}
@@ -1180,7 +1461,8 @@
// If switch has default case, then ignore it.
if (!CaseListIsErroneous && !CaseListIsIncomplete && !HasConstantCond &&
- ET && ET->getDecl()->isCompleteDefinition()) {
+ ET && ET->getDecl()->isCompleteDefinition() &&
+ !empty(ET->getDecl()->enumerators())) {
const EnumDecl *ED = ET->getDecl();
EnumValsTy EnumVals;
@@ -1990,7 +2272,7 @@
// If the type contained 'auto', deduce the 'auto' to 'id'.
if (FirstType->getContainedAutoType()) {
OpaqueValueExpr OpaqueId(D->getLocation(), Context.getObjCIdType(),
- VK_RValue);
+ VK_PRValue);
Expr *DeducedInit = &OpaqueId;
if (DeduceAutoType(D->getTypeSourceInfo(), DeducedInit, FirstType) ==
DAR_Failed)
@@ -3000,6 +3282,12 @@
// C99 6.8.6.2p1: A break shall appear only in or as a loop body.
return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));
}
+ if (S->getFlags() & Scope::ConditionVarScope) {
+ // We cannot 'continue;' from within a statement expression in the
+ // initializer of a condition variable because we would jump past the
+ // initialization of that variable.
+ return StmtError(Diag(ContinueLoc, diag::err_continue_from_cond_var_init));
+ }
CheckJumpOutOfSEHFinally(*this, ContinueLoc, *S);
return new (Context) ContinueStmt(ContinueLoc);
@@ -3020,295 +3308,205 @@
return new (Context) BreakStmt(BreakLoc);
}
-/// Determine whether the given expression is a candidate for
-/// copy elision in either a return statement or a throw expression.
+/// Determine whether the given expression might be move-eligible or
+/// copy-elidable in either a (co_)return statement or throw expression,
+/// without considering function return type, if applicable.
///
-/// \param ReturnType If we're determining the copy elision candidate for
-/// a return statement, this is the return type of the function. If we're
-/// determining the copy elision candidate for a throw expression, this will
-/// be a NULL type.
+/// \param E The expression being returned from the function or block,
+/// being thrown, or being co_returned from a coroutine. This expression
+/// might be modified by the implementation.
///
-/// \param E The expression being returned from the function or block, or
-/// being thrown.
+/// \param ForceCXX2b Overrides detection of current language mode
+/// and uses the rules for C++2b.
///
-/// \param CESK Whether we allow function parameters or
-/// id-expressions that could be moved out of the function to be considered NRVO
-/// candidates. C++ prohibits these for NRVO itself, but we re-use this logic to
-/// determine whether we should try to move as part of a return or throw (which
-/// does allow function parameters).
-///
-/// \returns The NRVO candidate variable, if the return statement may use the
-/// NRVO, or NULL if there is no such candidate.
-VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
- CopyElisionSemanticsKind CESK) {
+/// \returns An aggregate which contains the Candidate and isMoveEligible
+/// and isCopyElidable methods. If Candidate is non-null, it means
+/// isMoveEligible() would be true under the most permissive language standard.
+Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E,
+ SimplerImplicitMoveMode Mode) {
+ if (!E)
+ return NamedReturnInfo();
// - in a return statement in a function [where] ...
// ... the expression is the name of a non-volatile automatic object ...
- DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
+ const auto *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
if (!DR || DR->refersToEnclosingVariableOrCapture())
- return nullptr;
- VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ return NamedReturnInfo();
+ const auto *VD = dyn_cast<VarDecl>(DR->getDecl());
if (!VD)
- return nullptr;
-
- if (isCopyElisionCandidate(ReturnType, VD, CESK))
- return VD;
- return nullptr;
+ return NamedReturnInfo();
+ NamedReturnInfo Res = getNamedReturnInfo(VD);
+ if (Res.Candidate && !E->isXValue() &&
+ (Mode == SimplerImplicitMoveMode::ForceOn ||
+ (Mode != SimplerImplicitMoveMode::ForceOff &&
+ getLangOpts().CPlusPlus2b))) {
+ E = ImplicitCastExpr::Create(Context, VD->getType().getNonReferenceType(),
+ CK_NoOp, E, nullptr, VK_XValue,
+ FPOptionsOverride());
+ }
+ return Res;
}
-bool Sema::isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
- CopyElisionSemanticsKind CESK) {
- QualType VDType = VD->getType();
- // - in a return statement in a function with ...
- // ... a class return type ...
- if (!ReturnType.isNull() && !ReturnType->isDependentType()) {
- if (!ReturnType->isRecordType())
- return false;
- // ... the same cv-unqualified type as the function return type ...
- // When considering moving this expression out, allow dissimilar types.
- if (!(CESK & CES_AllowDifferentTypes) && !VDType->isDependentType() &&
- !Context.hasSameUnqualifiedType(ReturnType, VDType))
- return false;
- }
+/// Determine whether the given NRVO candidate variable is move-eligible or
+/// copy-elidable, without considering function return type.
+///
+/// \param VD The NRVO candidate variable.
+///
+/// \returns An aggregate which contains the Candidate and isMoveEligible
+/// and isCopyElidable methods. If Candidate is non-null, it means
+/// isMoveEligible() would be true under the most permissive language standard.
+Sema::NamedReturnInfo Sema::getNamedReturnInfo(const VarDecl *VD) {
+ NamedReturnInfo Info{VD, NamedReturnInfo::MoveEligibleAndCopyElidable};
- // ...object (other than a function or catch-clause parameter)...
- if (VD->getKind() != Decl::Var &&
- !((CESK & CES_AllowParameters) && VD->getKind() == Decl::ParmVar))
- return false;
- if (!(CESK & CES_AllowExceptionVariables) && VD->isExceptionVariable())
- return false;
+ // C++20 [class.copy.elision]p3:
+ // - in a return statement in a function with ...
+ // (other than a function ... parameter)
+ if (VD->getKind() == Decl::ParmVar)
+ Info.S = NamedReturnInfo::MoveEligible;
+ else if (VD->getKind() != Decl::Var)
+ return NamedReturnInfo();
+
+ // (other than ... a catch-clause parameter)
+ if (VD->isExceptionVariable())
+ Info.S = NamedReturnInfo::MoveEligible;
// ...automatic...
- if (!VD->hasLocalStorage()) return false;
+ if (!VD->hasLocalStorage())
+ return NamedReturnInfo();
- // Return false if VD is a __block variable. We don't want to implicitly move
- // out of a __block variable during a return because we cannot assume the
- // variable will no longer be used.
- if (VD->hasAttr<BlocksAttr>()) return false;
+ // We don't want to implicitly move out of a __block variable during a return
+ // because we cannot assume the variable will no longer be used.
+ if (VD->hasAttr<BlocksAttr>())
+ return NamedReturnInfo();
- // ...non-volatile...
- if (VD->getType().isVolatileQualified())
- return false;
-
- if (CESK & CES_AllowDifferentTypes)
- return true;
+ QualType VDType = VD->getType();
+ if (VDType->isObjectType()) {
+ // C++17 [class.copy.elision]p3:
+ // ...non-volatile automatic object...
+ if (VDType.isVolatileQualified())
+ return NamedReturnInfo();
+ } else if (VDType->isRValueReferenceType()) {
+ // C++20 [class.copy.elision]p3:
+ // ...either a non-volatile object or an rvalue reference to a non-volatile
+ // object type...
+ QualType VDReferencedType = VDType.getNonReferenceType();
+ if (VDReferencedType.isVolatileQualified() ||
+ !VDReferencedType->isObjectType())
+ return NamedReturnInfo();
+ Info.S = NamedReturnInfo::MoveEligible;
+ } else {
+ return NamedReturnInfo();
+ }
// Variables with higher required alignment than their type's ABI
// alignment cannot use NRVO.
- if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() &&
- Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType()))
- return false;
+ if (!VD->hasDependentAlignment() &&
+ Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VDType))
+ Info.S = NamedReturnInfo::MoveEligible;
- return true;
+ return Info;
}
-/// Try to perform the initialization of a potentially-movable value,
-/// which is the operand to a return or throw statement.
+/// Updates given NamedReturnInfo's move-eligible and
+/// copy-elidable statuses, considering the function
+/// return type criteria as applicable to return statements.
///
-/// This routine implements C++14 [class.copy]p32, which attempts to treat
-/// returned lvalues as rvalues in certain cases (to prefer move construction),
-/// then falls back to treating them as lvalues if that failed.
+/// \param Info The NamedReturnInfo object to update.
///
-/// \param ConvertingConstructorsOnly If true, follow [class.copy]p32 and reject
-/// resolutions that find non-constructors, such as derived-to-base conversions
-/// or `operator T()&&` member functions. If false, do consider such
-/// conversion sequences.
-///
-/// \param Res We will fill this in if move-initialization was possible.
-/// If move-initialization is not possible, such that we must fall back to
-/// treating the operand as an lvalue, we will leave Res in its original
-/// invalid state.
-///
-/// \returns Whether we need to do the second overload resolution. If the first
-/// overload resolution fails, or if the first overload resolution succeeds but
-/// the selected constructor/operator doesn't match the additional criteria, we
-/// need to do the second overload resolution.
-static bool TryMoveInitialization(Sema &S, const InitializedEntity &Entity,
- const VarDecl *NRVOCandidate,
- QualType ResultType, Expr *&Value,
- bool ConvertingConstructorsOnly,
- bool IsDiagnosticsCheck, ExprResult &Res) {
- ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
- CK_NoOp, Value, VK_XValue, FPOptionsOverride());
+/// \param ReturnType This is the return type of the function.
+/// \returns The copy elision candidate, in case the initial return expression
+/// was copy elidable, or nullptr otherwise.
+const VarDecl *Sema::getCopyElisionCandidate(NamedReturnInfo &Info,
+ QualType ReturnType) {
+ if (!Info.Candidate)
+ return nullptr;
- Expr *InitExpr = &AsRvalue;
+ auto invalidNRVO = [&] {
+ Info = NamedReturnInfo();
+ return nullptr;
+ };
- InitializationKind Kind = InitializationKind::CreateCopy(
- Value->getBeginLoc(), Value->getBeginLoc());
+ // If we got a non-deduced auto ReturnType, we are in a dependent context and
+ // there is no point in allowing copy elision since we won't have it deduced
+ // by the point the VardDecl is instantiated, which is the last chance we have
+ // of deciding if the candidate is really copy elidable.
+ if ((ReturnType->getTypeClass() == Type::TypeClass::Auto &&
+ ReturnType->isCanonicalUnqualified()) ||
+ ReturnType->isSpecificBuiltinType(BuiltinType::Dependent))
+ return invalidNRVO();
- InitializationSequence Seq(S, Entity, Kind, InitExpr);
+ if (!ReturnType->isDependentType()) {
+ // - in a return statement in a function with ...
+ // ... a class return type ...
+ if (!ReturnType->isRecordType())
+ return invalidNRVO();
- bool NeedSecondOverloadResolution = true;
- if (!Seq &&
- (IsDiagnosticsCheck || Seq.getFailedOverloadResult() != OR_Deleted)) {
- return NeedSecondOverloadResolution;
+ QualType VDType = Info.Candidate->getType();
+ // ... the same cv-unqualified type as the function return type ...
+ // When considering moving this expression out, allow dissimilar types.
+ if (!VDType->isDependentType() &&
+ !Context.hasSameUnqualifiedType(ReturnType, VDType))
+ Info.S = NamedReturnInfo::MoveEligible;
}
+ return Info.isCopyElidable() ? Info.Candidate : nullptr;
+}
- for (const InitializationSequence::Step &Step : Seq.steps()) {
- if (Step.Kind != InitializationSequence::SK_ConstructorInitialization &&
- Step.Kind != InitializationSequence::SK_UserConversion)
- continue;
-
- FunctionDecl *FD = Step.Function.Function;
- if (ConvertingConstructorsOnly) {
- if (isa<CXXConstructorDecl>(FD)) {
- // C++14 [class.copy]p32:
- // [...] If the first overload resolution fails or was not performed,
- // or if the type of the first parameter of the selected constructor
- // is not an rvalue reference to the object's type (possibly
- // cv-qualified), overload resolution is performed again, considering
- // the object as an lvalue.
- const RValueReferenceType *RRefType =
- FD->getParamDecl(0)->getType()->getAs<RValueReferenceType>();
- if (!RRefType)
- break;
- if (!S.Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
- NRVOCandidate->getType()))
- break;
- } else {
- continue;
- }
- } else {
- if (isa<CXXConstructorDecl>(FD)) {
- // Check that overload resolution selected a constructor taking an
- // rvalue reference. If it selected an lvalue reference, then we
- // didn't need to cast this thing to an rvalue in the first place.
- if (!isa<RValueReferenceType>(FD->getParamDecl(0)->getType()))
- break;
- } else if (isa<CXXMethodDecl>(FD)) {
- // Check that overload resolution selected a conversion operator
- // taking an rvalue reference.
- if (cast<CXXMethodDecl>(FD)->getRefQualifier() != RQ_RValue)
- break;
- } else {
- continue;
- }
- }
-
- NeedSecondOverloadResolution = false;
- // Promote "AsRvalue" to the heap, since we now need this
- // expression node to persist.
- Value =
- ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp, Value,
- nullptr, VK_XValue, FPOptionsOverride());
-
- // Complete type-checking the initialization of the return type
- // using the constructor we found.
- Res = Seq.Perform(S, Entity, Kind, Value);
+/// Verify that the initialization sequence that was picked for the
+/// first overload resolution is permissible under C++98.
+///
+/// Reject (possibly converting) contructors not taking an rvalue reference,
+/// or user conversion operators which are not ref-qualified.
+static bool
+VerifyInitializationSequenceCXX98(const Sema &S,
+ const InitializationSequence &Seq) {
+ const auto *Step = llvm::find_if(Seq.steps(), [](const auto &Step) {
+ return Step.Kind == InitializationSequence::SK_ConstructorInitialization ||
+ Step.Kind == InitializationSequence::SK_UserConversion;
+ });
+ if (Step != Seq.step_end()) {
+ const auto *FD = Step->Function.Function;
+ if (isa<CXXConstructorDecl>(FD)
+ ? !FD->getParamDecl(0)->getType()->isRValueReferenceType()
+ : cast<CXXMethodDecl>(FD)->getRefQualifier() == RQ_None)
+ return false;
}
-
- return NeedSecondOverloadResolution;
+ return true;
}
/// Perform the initialization of a potentially-movable value, which
/// is the result of return value.
///
-/// This routine implements C++14 [class.copy]p32, which attempts to treat
-/// returned lvalues as rvalues in certain cases (to prefer move construction),
-/// then falls back to treating them as lvalues if that failed.
-ExprResult
-Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
- const VarDecl *NRVOCandidate,
- QualType ResultType,
- Expr *Value,
- bool AllowNRVO) {
- // C++14 [class.copy]p32:
- // When the criteria for elision of a copy/move operation are met, but not for
- // an exception-declaration, and the object to be copied is designated by an
- // lvalue, or when the expression in a return statement is a (possibly
- // parenthesized) id-expression that names an object with automatic storage
- // duration declared in the body or parameter-declaration-clause of the
- // innermost enclosing function or lambda-expression, overload resolution to
- // select the constructor for the copy is first performed as if the object
- // were designated by an rvalue.
- ExprResult Res = ExprError();
- bool NeedSecondOverloadResolution = true;
-
- if (AllowNRVO) {
- bool AffectedByCWG1579 = false;
-
- if (!NRVOCandidate) {
- NRVOCandidate = getCopyElisionCandidate(ResultType, Value, CES_Default);
- if (NRVOCandidate &&
- !getDiagnostics().isIgnored(diag::warn_return_std_move_in_cxx11,
- Value->getExprLoc())) {
- const VarDecl *NRVOCandidateInCXX11 =
- getCopyElisionCandidate(ResultType, Value, CES_FormerDefault);
- AffectedByCWG1579 = (!NRVOCandidateInCXX11);
- }
- }
-
- if (NRVOCandidate) {
- NeedSecondOverloadResolution = TryMoveInitialization(
- *this, Entity, NRVOCandidate, ResultType, Value, true, false, Res);
- }
-
- if (!NeedSecondOverloadResolution && AffectedByCWG1579) {
- QualType QT = NRVOCandidate->getType();
- if (QT.getNonReferenceType().getUnqualifiedType().isTriviallyCopyableType(
- Context)) {
- // Adding 'std::move' around a trivially copyable variable is probably
- // pointless. Don't suggest it.
- } else {
- // Common cases for this are returning unique_ptr<Derived> from a
- // function of return type unique_ptr<Base>, or returning T from a
- // function of return type Expected<T>. This is totally fine in a
- // post-CWG1579 world, but was not fine before.
- assert(!ResultType.isNull());
- SmallString<32> Str;
- Str += "std::move(";
- Str += NRVOCandidate->getDeclName().getAsString();
- Str += ")";
- Diag(Value->getExprLoc(), diag::warn_return_std_move_in_cxx11)
- << Value->getSourceRange() << NRVOCandidate->getDeclName()
- << ResultType << QT;
- Diag(Value->getExprLoc(), diag::note_add_std_move_in_cxx11)
- << FixItHint::CreateReplacement(Value->getSourceRange(), Str);
- }
- } else if (NeedSecondOverloadResolution &&
- !getDiagnostics().isIgnored(diag::warn_return_std_move,
- Value->getExprLoc())) {
- const VarDecl *FakeNRVOCandidate =
- getCopyElisionCandidate(QualType(), Value, CES_AsIfByStdMove);
- if (FakeNRVOCandidate) {
- QualType QT = FakeNRVOCandidate->getType();
- if (QT->isLValueReferenceType()) {
- // Adding 'std::move' around an lvalue reference variable's name is
- // dangerous. Don't suggest it.
- } else if (QT.getNonReferenceType()
- .getUnqualifiedType()
- .isTriviallyCopyableType(Context)) {
- // Adding 'std::move' around a trivially copyable variable is probably
- // pointless. Don't suggest it.
- } else {
- ExprResult FakeRes = ExprError();
- Expr *FakeValue = Value;
- TryMoveInitialization(*this, Entity, FakeNRVOCandidate, ResultType,
- FakeValue, false, true, FakeRes);
- if (!FakeRes.isInvalid()) {
- bool IsThrow =
- (Entity.getKind() == InitializedEntity::EK_Exception);
- SmallString<32> Str;
- Str += "std::move(";
- Str += FakeNRVOCandidate->getDeclName().getAsString();
- Str += ")";
- Diag(Value->getExprLoc(), diag::warn_return_std_move)
- << Value->getSourceRange()
- << FakeNRVOCandidate->getDeclName() << IsThrow;
- Diag(Value->getExprLoc(), diag::note_add_std_move)
- << FixItHint::CreateReplacement(Value->getSourceRange(), Str);
- }
- }
- }
+/// This routine implements C++20 [class.copy.elision]p3, which attempts to
+/// treat returned lvalues as rvalues in certain cases (to prefer move
+/// construction), then falls back to treating them as lvalues if that failed.
+ExprResult Sema::PerformMoveOrCopyInitialization(
+ const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value,
+ bool SupressSimplerImplicitMoves) {
+ if ((!getLangOpts().CPlusPlus2b || SupressSimplerImplicitMoves) &&
+ NRInfo.isMoveEligible()) {
+ ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
+ CK_NoOp, Value, VK_XValue, FPOptionsOverride());
+ Expr *InitExpr = &AsRvalue;
+ auto Kind = InitializationKind::CreateCopy(Value->getBeginLoc(),
+ Value->getBeginLoc());
+ InitializationSequence Seq(*this, Entity, Kind, InitExpr);
+ auto Res = Seq.getFailedOverloadResult();
+ if ((Res == OR_Success || Res == OR_Deleted) &&
+ (getLangOpts().CPlusPlus11 ||
+ VerifyInitializationSequenceCXX98(*this, Seq))) {
+ // Promote "AsRvalue" to the heap, since we now need this
+ // expression node to persist.
+ Value =
+ ImplicitCastExpr::Create(Context, Value->getType(), CK_NoOp, Value,
+ nullptr, VK_XValue, FPOptionsOverride());
+ // Complete type-checking the initialization of the return type
+ // using the constructor we found.
+ return Seq.Perform(*this, Entity, Kind, Value);
}
}
-
// Either we didn't meet the criteria for treating an lvalue as an rvalue,
// above, or overload resolution failed. Either way, we need to try
// (again) now with the return value expression as written.
- if (NeedSecondOverloadResolution)
- Res = PerformCopyInitialization(Entity, SourceLocation(), Value);
-
- return Res;
+ return PerformCopyInitialization(Entity, SourceLocation(), Value);
}
/// Determine whether the declared return type of the specified function
@@ -3322,8 +3520,10 @@
/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements
/// for capturing scopes.
///
-StmtResult
-Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
+StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
+ Expr *RetValExp,
+ NamedReturnInfo &NRInfo,
+ bool SupressSimplerImplicitMoves) {
// If this is the first return we've seen, infer the return type.
// [expr.prim.lambda]p4 in C++11; block literals follow the same rules.
CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction());
@@ -3402,7 +3602,7 @@
if (CurCap->ReturnType.isNull())
CurCap->ReturnType = FnRetType;
}
- assert(!FnRetType.isNull());
+ const VarDecl *NRVOCandidate = getCopyElisionCandidate(NRInfo, FnRetType);
if (auto *CurBlock = dyn_cast<BlockScopeInfo>(CurCap)) {
if (CurBlock->FunctionType->castAs<FunctionType>()->getNoReturnAttr()) {
@@ -3425,7 +3625,6 @@
// Otherwise, verify that this result type matches the previous one. We are
// pickier with blocks than for normal functions because we don't have GCC
// compatibility to worry about here.
- const VarDecl *NRVOCandidate = nullptr;
if (FnRetType->isDependentType()) {
// Delay processing for now. TODO: there are lots of dependent
// types we can conclusively prove aren't void.
@@ -3453,20 +3652,16 @@
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
- InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
- FnRetType,
- NRVOCandidate != nullptr);
- ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
- FnRetType, RetValExp);
+ InitializedEntity Entity = InitializedEntity::InitializeResult(
+ ReturnLoc, FnRetType, NRVOCandidate != nullptr);
+ ExprResult Res = PerformMoveOrCopyInitialization(
+ Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);
if (Res.isInvalid()) {
// FIXME: Cleanup temporaries here, anyway?
return StmtError();
}
RetValExp = Res.get();
CheckReturnValExpr(RetValExp, FnRetType, ReturnLoc);
- } else {
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
}
if (RetValExp) {
@@ -3670,13 +3865,37 @@
return R;
}
+static bool CheckSimplerImplicitMovesMSVCWorkaround(const Sema &S,
+ const Expr *E) {
+ if (!E || !S.getLangOpts().CPlusPlus2b || !S.getLangOpts().MSVCCompat)
+ return false;
+ const Decl *D = E->getReferencedDeclOfCallee();
+ if (!D || !S.SourceMgr.isInSystemHeader(D->getLocation()))
+ return false;
+ for (const DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) {
+ if (DC->isStdNamespace())
+ return true;
+ }
+ return false;
+}
+
StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// Check for unexpanded parameter packs.
if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
return StmtError();
+ // HACK: We supress simpler implicit move here in msvc compatibility mode
+ // just as a temporary work around, as the MSVC STL has issues with
+ // this change.
+ bool SupressSimplerImplicitMoves =
+ CheckSimplerImplicitMovesMSVCWorkaround(*this, RetValExp);
+ NamedReturnInfo NRInfo = getNamedReturnInfo(
+ RetValExp, SupressSimplerImplicitMoves ? SimplerImplicitMoveMode::ForceOff
+ : SimplerImplicitMoveMode::Normal);
+
if (isa<CapturingScopeInfo>(getCurFunction()))
- return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);
+ return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp, NRInfo,
+ SupressSimplerImplicitMoves);
QualType FnRetType;
QualType RelatedRetType;
@@ -3748,6 +3967,7 @@
}
}
}
+ const VarDecl *NRVOCandidate = getCopyElisionCandidate(NRInfo, FnRetType);
bool HasDependentReturnType = FnRetType->isDependentType();
@@ -3854,8 +4074,6 @@
/* NRVOCandidate=*/nullptr);
} else {
assert(RetValExp || HasDependentReturnType);
- const VarDecl *NRVOCandidate = nullptr;
-
QualType RetType = RelatedRetType.isNull() ? FnRetType : RelatedRetType;
// C99 6.8.6.4p3(136): The return statement is not an assignment. The
@@ -3864,15 +4082,12 @@
// In C++ the return statement is handled via a copy initialization,
// the C version of which boils down to CheckSingleAssignmentConstraints.
- if (RetValExp)
- NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, CES_Strict);
if (!HasDependentReturnType && !RetValExp->isTypeDependent()) {
// we have a non-void function with an expression, continue checking
- InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
- RetType,
- NRVOCandidate != nullptr);
- ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
- RetType, RetValExp);
+ InitializedEntity Entity = InitializedEntity::InitializeResult(
+ ReturnLoc, RetType, NRVOCandidate != nullptr);
+ ExprResult Res = PerformMoveOrCopyInitialization(
+ Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);
if (Res.isInvalid()) {
// FIXME: Clean up temporaries here anyway?
return StmtError();
diff --git a/src/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp b/src/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp
index 3b631bf..243d0b9 100644
--- a/src/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp
@@ -228,7 +228,7 @@
StringRef Clobber = Clobbers[i]->getString();
// We only check registers, therefore we don't check cc and memory
// clobbers
- if (Clobber == "cc" || Clobber == "memory")
+ if (Clobber == "cc" || Clobber == "memory" || Clobber == "unwind")
continue;
Clobber = Target.getNormalizedGCCRegisterName(Clobber, true);
// Go over the output's registers we collected
@@ -405,7 +405,7 @@
if (!Info.isValidAsmImmediate(IntResult))
return StmtError(Diag(InputExpr->getBeginLoc(),
diag::err_invalid_asm_value_for_constraint)
- << IntResult.toString(10)
+ << toString(IntResult, 10)
<< Info.getConstraintStr()
<< InputExpr->getSourceRange());
}
@@ -453,6 +453,8 @@
<< Info.getConstraintStr();
}
+ Optional<SourceLocation> UnwindClobberLoc;
+
// Check that the clobbers are valid.
for (unsigned i = 0; i != NumClobbers; i++) {
StringLiteral *Literal = Clobbers[i];
@@ -468,6 +470,19 @@
NumInputs, Names, Constraints, Exprs.data(), AsmString,
NumClobbers, Clobbers, NumLabels, RParenLoc);
}
+
+ if (Clobber == "unwind") {
+ UnwindClobberLoc = Literal->getBeginLoc();
+ }
+ }
+
+ // Using unwind clobber and asm-goto together is not supported right now.
+ if (UnwindClobberLoc && NumLabels > 0) {
+ targetDiag(*UnwindClobberLoc, diag::err_asm_unwind_and_goto);
+ return new (Context)
+ GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs,
+ Names, Constraints, Exprs.data(), AsmString, NumClobbers,
+ Clobbers, NumLabels, RParenLoc);
}
GCCAsmStmt *NS =
@@ -720,7 +735,7 @@
Expr::EvalResult Eval;
if (T->isFunctionType() || T->isDependentType())
return Info.setLabel(Res);
- if (Res->isRValue()) {
+ if (Res->isPRValue()) {
bool IsEnum = isa<clang::EnumType>(T);
if (DeclRefExpr *DRE = dyn_cast<clang::DeclRefExpr>(Res))
if (DRE->getDecl()->getKind() == Decl::EnumConstant)
diff --git a/src/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp b/src/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp
index 8031aa6..4f2977f 100644
--- a/src/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaStmtAttr.cpp
@@ -26,14 +26,12 @@
static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
FallThroughAttr Attr(S.Context, A);
- if (!isa<NullStmt>(St)) {
+ if (isa<SwitchCase>(St)) {
S.Diag(A.getRange().getBegin(), diag::err_fallthrough_attr_wrong_target)
- << Attr.getSpelling() << St->getBeginLoc();
- if (isa<SwitchCase>(St)) {
- SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
- S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
- << FixItHint::CreateInsertion(L, ";");
- }
+ << A << St->getBeginLoc();
+ SourceLocation L = S.getLocForEndOfToken(Range.getEnd());
+ S.Diag(L, diag::note_fallthrough_insert_semi_fixit)
+ << FixItHint::CreateInsertion(L, ";");
return nullptr;
}
auto *FnScope = S.getCurFunction();
@@ -54,11 +52,6 @@
static Attr *handleSuppressAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
- if (A.getNumArgs() < 1) {
- S.Diag(A.getLoc(), diag::err_attribute_too_few_arguments) << A << 1;
- return nullptr;
- }
-
std::vector<StringRef> DiagnosticIdentifiers;
for (unsigned I = 0, E = A.getNumArgs(); I != E; ++I) {
StringRef RuleName;
@@ -88,10 +81,10 @@
PragmaNameLoc->Ident->getName())
.Default("clang loop");
- if (St->getStmtClass() != Stmt::DoStmtClass &&
- St->getStmtClass() != Stmt::ForStmtClass &&
- St->getStmtClass() != Stmt::CXXForRangeStmtClass &&
- St->getStmtClass() != Stmt::WhileStmtClass) {
+ // This could be handled automatically by adding a Subjects definition in
+ // Attr.td, but that would make the diagnostic behavior worse in this case
+ // because the user spells this attribute as a pragma.
+ if (!isa<DoStmt, ForStmt, CXXForRangeStmt, WhileStmt>(St)) {
std::string Pragma = "#pragma " + std::string(PragmaName);
S.Diag(St->getBeginLoc(), diag::err_pragma_loop_precedes_nonloop) << Pragma;
return nullptr;
@@ -205,9 +198,6 @@
static Attr *handleNoMergeAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
NoMergeAttr NMA(S.Context, A);
- if (S.CheckAttrNoArgs(A))
- return nullptr;
-
CallExprFinder CEF(S, St);
if (!CEF.foundCallExpr()) {
@@ -219,6 +209,12 @@
return ::new (S.Context) NoMergeAttr(S.Context, A);
}
+static Attr *handleMustTailAttr(Sema &S, Stmt *St, const ParsedAttr &A,
+ SourceRange Range) {
+ // Validation is in Sema::ActOnAttributedStmt().
+ return ::new (S.Context) MustTailAttr(S.Context, A);
+}
+
static Attr *handleLikely(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
@@ -237,9 +233,22 @@
return ::new (S.Context) UnlikelyAttr(S.Context, A);
}
+#define WANT_STMT_MERGE_LOGIC
+#include "clang/Sema/AttrParsedAttrImpl.inc"
+#undef WANT_STMT_MERGE_LOGIC
+
static void
CheckForIncompatibleAttributes(Sema &S,
const SmallVectorImpl<const Attr *> &Attrs) {
+ // The vast majority of attributed statements will only have one attribute
+ // on them, so skip all of the checking in the common case.
+ if (Attrs.size() < 2)
+ return;
+
+ // First, check for the easy cases that are table-generated for us.
+ if (!DiagnoseMutualExclusions(S, Attrs))
+ return;
+
// There are 6 categories of loop hints attributes: vectorize, interleave,
// unroll, unroll_and_jam, pipeline and distribute. Except for distribute they
// come in two variants: a state form and a numeric form. The state form
@@ -342,32 +351,6 @@
<< CategoryState.NumericAttr->getDiagnosticName(Policy);
}
}
-
- // C++20 [dcl.attr.likelihood]p1 The attribute-token likely shall not appear
- // in an attribute-specifier-seq that contains the attribute-token unlikely.
- const LikelyAttr *Likely = nullptr;
- const UnlikelyAttr *Unlikely = nullptr;
- for (const auto *I : Attrs) {
- if (const auto *Attr = dyn_cast<LikelyAttr>(I)) {
- if (Unlikely) {
- S.Diag(Attr->getLocation(), diag::err_attributes_are_not_compatible)
- << Attr << Unlikely << Attr->getRange();
- S.Diag(Unlikely->getLocation(), diag::note_conflicting_attribute)
- << Unlikely->getRange();
- return;
- }
- Likely = Attr;
- } else if (const auto *Attr = dyn_cast<UnlikelyAttr>(I)) {
- if (Likely) {
- S.Diag(Attr->getLocation(), diag::err_attributes_are_not_compatible)
- << Attr << Likely << Attr->getRange();
- S.Diag(Likely->getLocation(), diag::note_conflicting_attribute)
- << Likely->getRange();
- return;
- }
- Unlikely = Attr;
- }
- }
}
static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A,
@@ -377,17 +360,8 @@
// opencl_unroll_hint can have 0 arguments (compiler
// determines unrolling factor) or 1 argument (the unroll factor provided
// by the user).
-
- unsigned NumArgs = A.getNumArgs();
-
- if (NumArgs > 1) {
- S.Diag(A.getLoc(), diag::err_attribute_too_many_arguments) << A << 1;
- return nullptr;
- }
-
unsigned UnrollFactor = 0;
-
- if (NumArgs == 1) {
+ if (A.getNumArgs() == 1) {
Expr *E = A.getArgAsExpr(0);
Optional<llvm::APSInt> ArgVal;
@@ -398,28 +372,42 @@
}
int Val = ArgVal->getSExtValue();
-
if (Val <= 0) {
S.Diag(A.getRange().getBegin(),
diag::err_attribute_requires_positive_integer)
<< A << /* positive */ 0;
return nullptr;
}
- UnrollFactor = Val;
+ UnrollFactor = static_cast<unsigned>(Val);
}
- return OpenCLUnrollHintAttr::CreateImplicit(S.Context, UnrollFactor);
+ return ::new (S.Context) OpenCLUnrollHintAttr(S.Context, A, UnrollFactor);
}
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
- switch (A.getKind()) {
- case ParsedAttr::UnknownAttribute:
+ if (A.isInvalid() || A.getKind() == ParsedAttr::IgnoredAttribute)
+ return nullptr;
+
+ // Unknown attributes are automatically warned on. Target-specific attributes
+ // which do not apply to the current target architecture are treated as
+ // though they were unknown attributes.
+ const TargetInfo *Aux = S.Context.getAuxTargetInfo();
+ if (A.getKind() == ParsedAttr::UnknownAttribute ||
+ !(A.existsInTarget(S.Context.getTargetInfo()) ||
+ (S.Context.getLangOpts().SYCLIsDevice && Aux &&
+ A.existsInTarget(*Aux)))) {
S.Diag(A.getLoc(), A.isDeclspecAttribute()
? (unsigned)diag::warn_unhandled_ms_attribute_ignored
: (unsigned)diag::warn_unknown_attribute_ignored)
<< A << A.getRange();
return nullptr;
+ }
+
+ if (S.checkCommonAttributeFeatures(St, A))
+ return nullptr;
+
+ switch (A.getKind()) {
case ParsedAttr::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
case ParsedAttr::AT_LoopHint:
@@ -430,32 +418,29 @@
return handleSuppressAttr(S, St, A, Range);
case ParsedAttr::AT_NoMerge:
return handleNoMergeAttr(S, St, A, Range);
+ case ParsedAttr::AT_MustTail:
+ return handleMustTailAttr(S, St, A, Range);
case ParsedAttr::AT_Likely:
return handleLikely(S, St, A, Range);
case ParsedAttr::AT_Unlikely:
return handleUnlikely(S, St, A, Range);
default:
- // if we're here, then we parsed a known attribute, but didn't recognize
- // it as a statement attribute => it is declaration attribute
+ // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
+ // declaration attribute is not written on a statement, but this code is
+ // needed for attributes in Attr.td that do not list any subjects.
S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt)
<< A << St->getBeginLoc();
return nullptr;
}
}
-StmtResult Sema::ProcessStmtAttributes(Stmt *S,
- const ParsedAttributesView &AttrList,
- SourceRange Range) {
- SmallVector<const Attr*, 8> Attrs;
- for (const ParsedAttr &AL : AttrList) {
- if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range))
- Attrs.push_back(a);
+void Sema::ProcessStmtAttributes(Stmt *S,
+ const ParsedAttributesWithRange &InAttrs,
+ SmallVectorImpl<const Attr *> &OutAttrs) {
+ for (const ParsedAttr &AL : InAttrs) {
+ if (const Attr *A = ProcessStmtAttribute(*this, S, AL, InAttrs.Range))
+ OutAttrs.push_back(A);
}
- CheckForIncompatibleAttributes(*this, Attrs);
-
- if (Attrs.empty())
- return S;
-
- return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
+ CheckForIncompatibleAttributes(*this, OutAttrs);
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaTemplate.cpp b/src/llvm-project/clang/lib/Sema/SemaTemplate.cpp
index 12880b9..5d26f2d 100644
--- a/src/llvm-project/clang/lib/Sema/SemaTemplate.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaTemplate.cpp
@@ -1079,7 +1079,7 @@
return Param;
// Check the template argument itself.
- if (CheckTemplateArgument(Param, DefaultTInfo)) {
+ if (CheckTemplateArgument(DefaultTInfo)) {
Param->setInvalidDecl();
return Param;
}
@@ -1105,8 +1105,17 @@
TemplateIdAnnotation *TypeConstr,
TemplateTypeParmDecl *ConstrainedParameter,
SourceLocation EllipsisLoc) {
- ConceptDecl *CD =
- cast<ConceptDecl>(TypeConstr->Template.get().getAsTemplateDecl());
+ return BuildTypeConstraint(SS, TypeConstr, ConstrainedParameter, EllipsisLoc,
+ false);
+}
+
+bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstr,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc,
+ bool AllowUnexpandedPack) {
+ TemplateName TN = TypeConstr->Template.get();
+ ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl());
// C++2a [temp.param]p4:
// [...] The concept designated by a type-constraint shall be a type
@@ -1126,15 +1135,24 @@
return true;
}
+ DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name),
+ TypeConstr->TemplateNameLoc);
+
TemplateArgumentListInfo TemplateArgs;
if (TypeConstr->LAngleLoc.isValid()) {
TemplateArgs =
makeTemplateArgumentListInfo(*this, *TypeConstr);
+
+ if (EllipsisLoc.isInvalid() && !AllowUnexpandedPack) {
+ for (TemplateArgumentLoc Arg : TemplateArgs.arguments()) {
+ if (DiagnoseUnexpandedParameterPack(Arg, UPPC_TypeConstraint))
+ return true;
+ }
+ }
}
return AttachTypeConstraint(
SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc(),
- DeclarationNameInfo(DeclarationName(TypeConstr->Name),
- TypeConstr->TemplateNameLoc), CD,
+ ConceptName, CD,
TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr,
ConstrainedParameter, EllipsisLoc);
}
@@ -1238,8 +1256,8 @@
}
// FIXME: Concepts: This should be the type of the placeholder, but this is
// unclear in the wording right now.
- DeclRefExpr *Ref = BuildDeclRefExpr(NTTP, NTTP->getType(), VK_RValue,
- NTTP->getLocation());
+ DeclRefExpr *Ref =
+ BuildDeclRefExpr(NTTP, NTTP->getType(), VK_PRValue, NTTP->getLocation());
if (!Ref)
return true;
ExprResult ImmediatelyDeclaredConstraint =
@@ -1677,6 +1695,9 @@
if (ExportLoc.isValid())
Diag(ExportLoc, diag::warn_template_export_unsupported);
+ for (NamedDecl *P : Params)
+ warnOnReservedIdentifier(P);
+
return TemplateParameterList::Create(
Context, TemplateLoc, LAngleLoc,
llvm::makeArrayRef(Params.data(), Params.size()),
@@ -1849,7 +1870,7 @@
Diag(KWLoc, diag::err_using_decl_conflict_reverse);
Diag(Shadow->getTargetDecl()->getLocation(),
diag::note_using_decl_target);
- Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+ Diag(Shadow->getIntroducer()->getLocation(), diag::note_using_decl) << 0;
// Recover by ignoring the old declaration.
PrevDecl = PrevClassTemplate = nullptr;
}
@@ -2196,7 +2217,7 @@
return nullptr;
TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType);
- return buildDeductionGuide(TemplateParams, CD->getExplicitSpecifier(),
+ return buildDeductionGuide(TemplateParams, CD, CD->getExplicitSpecifier(),
NewTInfo, CD->getBeginLoc(), CD->getLocation(),
CD->getEndLoc(), MaterializedTypedefs);
}
@@ -2226,7 +2247,7 @@
Params.push_back(NewParam);
}
- return buildDeductionGuide(Template->getTemplateParameters(),
+ return buildDeductionGuide(Template->getTemplateParameters(), nullptr,
ExplicitSpecifier(), TSI, Loc, Loc, Loc);
}
@@ -2384,9 +2405,9 @@
NewDefArg = new (SemaRef.Context)
OpaqueValueExpr(OldParam->getDefaultArg()->getBeginLoc(),
ParamTy.getNonLValueExprType(SemaRef.Context),
- ParamTy->isLValueReferenceType() ? VK_LValue :
- ParamTy->isRValueReferenceType() ? VK_XValue :
- VK_RValue);
+ ParamTy->isLValueReferenceType() ? VK_LValue
+ : ParamTy->isRValueReferenceType() ? VK_XValue
+ : VK_PRValue);
}
ParmVarDecl *NewParam = ParmVarDecl::Create(SemaRef.Context, DC,
@@ -2404,9 +2425,9 @@
}
FunctionTemplateDecl *buildDeductionGuide(
- TemplateParameterList *TemplateParams, ExplicitSpecifier ES,
- TypeSourceInfo *TInfo, SourceLocation LocStart, SourceLocation Loc,
- SourceLocation LocEnd,
+ TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
+ ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
+ SourceLocation Loc, SourceLocation LocEnd,
llvm::ArrayRef<TypedefNameDecl *> MaterializedTypedefs = {}) {
DeclarationNameInfo Name(DeductionGuideName, Loc);
ArrayRef<ParmVarDecl *> Params =
@@ -2415,7 +2436,7 @@
// Build the implicit deduction guide template.
auto *Guide =
CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
- TInfo->getType(), TInfo, LocEnd);
+ TInfo->getType(), TInfo, LocEnd, Ctor);
Guide->setImplicit();
Guide->setParams(Params);
@@ -2494,6 +2515,12 @@
if (!CD || (!FTD && CD->isFunctionTemplateSpecialization()))
continue;
+ // Cannot make a deduction guide when unparsed arguments are present.
+ if (std::any_of(CD->param_begin(), CD->param_end(), [](ParmVarDecl *P) {
+ return !P || P->hasUnparsedDefaultArg();
+ }))
+ continue;
+
Transform.transformConstructor(FTD, CD);
AddedAny = true;
}
@@ -3561,7 +3588,9 @@
OS << VD->getName();
if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
// This is a template variable, print the expanded template arguments.
- printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy);
+ printTemplateArgumentList(
+ OS, IV->getTemplateArgs().asArray(), Policy,
+ IV->getSpecializedTemplate()->getTemplateParameters());
}
return true;
}
@@ -5013,7 +5042,7 @@
}
}
- if (CheckTemplateArgument(Param, TSI))
+ if (CheckTemplateArgument(TSI))
return true;
// Add the converted template type argument.
@@ -5632,7 +5661,7 @@
TemplateArgumentListInfo NewArgs = TemplateArgs;
// Make sure we get the template parameter list from the most
- // recentdeclaration, since that is the only one that has is guaranteed to
+ // recent declaration, since that is the only one that is guaranteed to
// have all the default template argument information.
TemplateParameterList *Params =
cast<TemplateDecl>(Template->getMostRecentDecl())
@@ -6179,8 +6208,7 @@
///
/// This routine implements the semantics of C++ [temp.arg.type]. It
/// returns true if an error occurred, and false otherwise.
-bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
- TypeSourceInfo *ArgInfo) {
+bool Sema::CheckTemplateArgument(TypeSourceInfo *ArgInfo) {
assert(ArgInfo && "invalid TypeSourceInfo");
QualType Arg = ArgInfo->getType();
SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
@@ -6874,8 +6902,9 @@
Arg = PE->getPattern();
ExprResult E = ImpCastExprToType(
Arg, ParamType.getNonLValueExprType(Context), CK_Dependent,
- ParamType->isLValueReferenceType() ? VK_LValue :
- ParamType->isRValueReferenceType() ? VK_XValue : VK_RValue);
+ ParamType->isLValueReferenceType() ? VK_LValue
+ : ParamType->isRValueReferenceType() ? VK_XValue
+ : VK_PRValue);
if (E.isInvalid())
return ExprError();
if (PE) {
@@ -7172,10 +7201,10 @@
Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
// Complain if an unsigned parameter received a negative value.
- if (IntegerType->isUnsignedIntegerOrEnumerationType()
- && (OldValue.isSigned() && OldValue.isNegative())) {
+ if (IntegerType->isUnsignedIntegerOrEnumerationType() &&
+ (OldValue.isSigned() && OldValue.isNegative())) {
Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative)
- << OldValue.toString(10) << Value.toString(10) << Param->getType()
+ << toString(OldValue, 10) << toString(Value, 10) << Param->getType()
<< Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
}
@@ -7190,7 +7219,7 @@
RequiredBits = OldValue.getMinSignedBits();
if (RequiredBits > AllowedBits) {
Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large)
- << OldValue.toString(10) << Value.toString(10) << Param->getType()
+ << toString(OldValue, 10) << toString(Value, 10) << Param->getType()
<< Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
}
@@ -7603,7 +7632,7 @@
if (OrigT->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
- E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E,
+ E = CStyleCastExpr::Create(Context, OrigT, VK_PRValue, CK_IntegralCast, E,
nullptr, CurFPFeatureOverrides(),
Context.getTrivialTypeSourceInfo(OrigT, Loc),
Loc, Loc);
@@ -10899,7 +10928,9 @@
}
Out << " = ";
- Args[I].print(getPrintingPolicy(), Out);
+ Args[I].print(
+ getPrintingPolicy(), Out,
+ TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
}
Out << ']';
diff --git a/src/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp b/src/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp
index ee4316e..08e7983 100644
--- a/src/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -455,11 +455,13 @@
const NonTypeTemplateParmDecl *NTTP, QualType NullPtrType,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- Expr *Value =
- S.ImpCastExprToType(new (S.Context) CXXNullPtrLiteralExpr(
- S.Context.NullPtrTy, NTTP->getLocation()),
- NullPtrType, CK_NullToPointer)
- .get();
+ Expr *Value = S.ImpCastExprToType(
+ new (S.Context) CXXNullPtrLiteralExpr(S.Context.NullPtrTy,
+ NTTP->getLocation()),
+ NullPtrType,
+ NullPtrType->isMemberPointerType() ? CK_NullToMemberPointer
+ : CK_NullToPointer)
+ .get();
return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
DeducedTemplateArgument(Value),
Value->getType(), Info, Deduced);
@@ -3077,6 +3079,10 @@
*this, Sema::ExpressionEvaluationContext::Unevaluated);
SFINAETrap Trap(*this);
+ // This deduction has no relation to any outer instantiation we might be
+ // performing.
+ LocalInstantiationScope InstantiationScope(*this);
+
SmallVector<DeducedTemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result
@@ -3125,6 +3131,10 @@
*this, Sema::ExpressionEvaluationContext::Unevaluated);
SFINAETrap Trap(*this);
+ // This deduction has no relation to any outer instantiation we might be
+ // performing.
+ LocalInstantiationScope InstantiationScope(*this);
+
SmallVector<DeducedTemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result = ::DeduceTemplateArguments(
@@ -3869,7 +3879,7 @@
// "lvalue reference to A" is used in place of A for type deduction.
if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) &&
Arg->isLValue()) {
- if (S.getLangOpts().OpenCL)
+ if (S.getLangOpts().OpenCL && !ArgType.hasAddressSpace())
ArgType = S.Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
ArgType = S.Context.getLValueReferenceType(ArgType);
}
@@ -3918,7 +3928,7 @@
if (isSimpleTemplateIdType(ParamType) ||
(isa<PointerType>(ParamType) &&
isSimpleTemplateIdType(
- ParamType->getAs<PointerType>()->getPointeeType())))
+ ParamType->castAs<PointerType>()->getPointeeType())))
TDF |= TDF_DerivedClass;
return false;
@@ -4695,10 +4705,9 @@
llvm::raw_string_ostream OS(Buf);
OS << "'" << Concept->getName();
if (TypeLoc.hasExplicitTemplateArgs()) {
- OS << "<";
- for (const auto &Arg : Type.getTypeConstraintArguments())
- Arg.print(S.getPrintingPolicy(), OS);
- OS << ">";
+ printTemplateArgumentList(
+ OS, Type.getTypeConstraintArguments(), S.getPrintingPolicy(),
+ Type.getTypeConstraintConcept()->getTemplateParameters());
}
OS << "'";
OS.flush();
@@ -5464,6 +5473,9 @@
Deduced.end());
Sema::InstantiatingTemplate Inst(S, Info.getLocation(), P2, DeducedArgs,
Info);
+ if (Inst.isInvalid())
+ return false;
+
auto *TST1 = T1->castAs<TemplateSpecializationType>();
bool AtLeastAsSpecialized;
S.runWithSufficientStackSpace(Info.getLocation(), [&] {
diff --git a/src/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp b/src/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 8bd812b..f18f77d 100644
--- a/src/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -805,9 +805,10 @@
SmallString<128> TemplateArgsStr;
llvm::raw_svector_ostream OS(TemplateArgsStr);
cast<NamedDecl>(Active->Entity)->printName(OS);
- if (!isa<FunctionDecl>(Active->Entity))
+ if (!isa<FunctionDecl>(Active->Entity)) {
printTemplateArgumentList(OS, Active->template_arguments(),
getPrintingPolicy());
+ }
Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
<< Active->InstantiationRange;
break;
@@ -1474,8 +1475,8 @@
ExprType.addConst();
return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
- ExprType, TargetType->isReferenceType() ? VK_LValue : VK_RValue, NTTP,
- E->getLocation(), Arg);
+ ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue,
+ NTTP, E->getLocation(), Arg);
}
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
@@ -2385,10 +2386,10 @@
}
if (AttachTypeConstraint(
TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
- TC->getNamedConcept(), &InstArgs, Inst,
+ TC->getNamedConcept(), TemplArgInfo ? &InstArgs : nullptr, Inst,
TTP->isParameterPack()
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
- ->getEllipsisLoc()
+ ->getEllipsisLoc()
: SourceLocation()))
return nullptr;
}
@@ -2816,7 +2817,8 @@
if (!Instantiation->isInvalidDecl()) {
// Perform any dependent diagnostics from the pattern.
- PerformDependentDiagnostics(Pattern, TemplateArgs);
+ if (Pattern->isDependentContext())
+ PerformDependentDiagnostics(Pattern, TemplateArgs);
// Instantiate any out-of-line class template partial
// specializations now.
@@ -3420,7 +3422,8 @@
Instantiation->getTemplateInstantiationPattern();
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());
- FieldDecl *Pattern = cast<FieldDecl>(Lookup.front());
+ FieldDecl *Pattern = Lookup.find_first<FieldDecl>();
+ assert(Pattern);
InstantiateInClassInitializer(PointOfInstantiation, Field, Pattern,
TemplateArgs);
}
diff --git a/src/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/src/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index dc1e0ef..be4c519 100644
--- a/src/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -9,6 +9,7 @@
//
//===----------------------------------------------------------------------===/
+#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
@@ -23,6 +24,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
@@ -474,7 +476,7 @@
SourceLocation(), SubstFD,
/* RefersToEnclosingVariableOrCapture */ false,
/* NameLoc */ SubstFD->getLocation(),
- SubstFD->getType(), ExprValueKind::VK_RValue);
+ SubstFD->getType(), ExprValueKind::VK_PRValue);
}
}
}
@@ -548,6 +550,35 @@
S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr);
}
+// This doesn't take any template parameters, but we have a custom action that
+// needs to happen when the kernel itself is instantiated. We need to run the
+// ItaniumMangler to mark the names required to name this kernel.
+static void instantiateDependentSYCLKernelAttr(
+ Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
+ const SYCLKernelAttr &Attr, Decl *New) {
+ // Functions cannot be partially specialized, so if we are being instantiated,
+ // we are obviously a complete specialization. Since this attribute is only
+ // valid on function template declarations, we know that this is a full
+ // instantiation of a kernel.
+ S.AddSYCLKernelLambda(cast<FunctionDecl>(New));
+
+ // Evaluate whether this would change any of the already evaluated
+ // __builtin_sycl_unique_stable_name values.
+ for (auto &Itr : S.Context.SYCLUniqueStableNameEvaluatedValues) {
+ const std::string &CurName = Itr.first->ComputeName(S.Context);
+ if (Itr.second != CurName) {
+ S.Diag(New->getLocation(),
+ diag::err_kernel_invalidates_sycl_unique_stable_name);
+ S.Diag(Itr.first->getLocation(),
+ diag::note_sycl_unique_stable_name_evaluated_here);
+ // Update this so future diagnostics work correctly.
+ Itr.second = CurName;
+ }
+ }
+
+ New->addAttr(Attr.clone(S.getASTContext()));
+}
+
/// Determine whether the attribute A might be relevent to the declaration D.
/// If not, we can skip instantiating it. The attribute may or may not have
/// been instantiated yet.
@@ -723,6 +754,11 @@
continue;
}
+ if (auto *A = dyn_cast<SYCLKernelAttr>(TmplAttr)) {
+ instantiateDependentSYCLKernelAttr(*this, TemplateArgs, *A, New);
+ continue;
+ }
+
assert(!TmplAttr->isPackExpansion());
if (TmplAttr->isLateParsed() && LateAttrs) {
// Late parsed attributes must be instantiated and attached after the
@@ -856,10 +892,11 @@
SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
}
- // HACK: g++ has a bug where it gets the value kind of ?: wrong.
- // libstdc++ relies upon this bug in its implementation of common_type.
- // If we happen to be processing that implementation, fake up the g++ ?:
- // semantics. See LWG issue 2141 for more information on the bug.
+ // HACK: 2012-10-23 g++ has a bug where it gets the value kind of ?: wrong.
+ // libstdc++ relies upon this bug in its implementation of common_type. If we
+ // happen to be processing that implementation, fake up the g++ ?:
+ // semantics. See LWG issue 2141 for more information on the bug. The bugs
+ // are fixed in g++ and libstdc++ 4.9.0 (2014-04-22).
const DecltypeType *DT = DI->getType()->getAs<DecltypeType>();
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext());
if (DT && RD && isa<ConditionalOperator>(DT->getUnderlyingExpr()) &&
@@ -1050,11 +1087,30 @@
SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner,
StartingScope, InstantiatingVarTemplate);
-
if (D->isNRVOVariable()) {
- QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType();
- if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict))
- Var->setNRVOVariable(true);
+ QualType RT;
+ if (auto *F = dyn_cast<FunctionDecl>(DC))
+ RT = F->getReturnType();
+ else if (isa<BlockDecl>(DC))
+ RT = cast<FunctionType>(SemaRef.getCurBlock()->FunctionType)
+ ->getReturnType();
+ else
+ llvm_unreachable("Unknown context type");
+
+ // This is the last chance we have of checking copy elision eligibility
+ // for functions in dependent contexts. The sema actions for building
+ // the return statement during template instantiation will have no effect
+ // regarding copy elision, since NRVO propagation runs on the scope exit
+ // actions, and these are not run on instantiation.
+ // This might run through some VarDecls which were returned from non-taken
+ // 'if constexpr' branches, and these will end up being constructed on the
+ // return slot even if they will never be returned, as a sort of accidental
+ // 'optimization'. Notably, functions with 'auto' return types won't have it
+ // deduced by this point. Coupled with the limitation described
+ // previously, this makes it very hard to support copy elision for these.
+ Sema::NamedReturnInfo Info = SemaRef.getNamedReturnInfo(Var);
+ bool NRVO = SemaRef.getCopyElisionCandidate(Info, RT) != nullptr;
+ Var->setNRVOVariable(NRVO);
}
Var->setImplicit(D->isImplicit());
@@ -1517,48 +1573,18 @@
return nullptr;
}
- bool AdoptedPreviousTemplateParams = false;
if (PrevClassTemplate) {
- bool Complain = true;
-
- // HACK: libstdc++ 4.2.1 contains an ill-formed friend class
- // template for struct std::tr1::__detail::_Map_base, where the
- // template parameters of the friend declaration don't match the
- // template parameters of the original declaration. In this one
- // case, we don't complain about the ill-formed friend
- // declaration.
- if (isFriend && Pattern->getIdentifier() &&
- Pattern->getIdentifier()->isStr("_Map_base") &&
- DC->isNamespace() &&
- cast<NamespaceDecl>(DC)->getIdentifier() &&
- cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) {
- DeclContext *DCParent = DC->getParent();
- if (DCParent->isNamespace() &&
- cast<NamespaceDecl>(DCParent)->getIdentifier() &&
- cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) {
- if (cast<Decl>(DCParent)->isInStdNamespace())
- Complain = false;
- }
- }
-
TemplateParameterList *PrevParams
= PrevClassTemplate->getMostRecentDecl()->getTemplateParameters();
// Make sure the parameter lists match.
- if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams,
- Complain,
- Sema::TPL_TemplateMatch)) {
- if (Complain)
- return nullptr;
-
- AdoptedPreviousTemplateParams = true;
- InstParams = PrevParams;
- }
+ if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, true,
+ Sema::TPL_TemplateMatch))
+ return nullptr;
// Do some additional validation, then merge default arguments
// from the existing declarations.
- if (!AdoptedPreviousTemplateParams &&
- SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
+ if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
Sema::TPC_ClassTemplate))
return nullptr;
}
@@ -1800,9 +1826,16 @@
PrevDecl = cast<CXXRecordDecl>(Prev);
}
- CXXRecordDecl *Record = CXXRecordDecl::Create(
- SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
- D->getLocation(), D->getIdentifier(), PrevDecl);
+ CXXRecordDecl *Record = nullptr;
+ if (D->isLambda())
+ Record = CXXRecordDecl::CreateLambda(
+ SemaRef.Context, Owner, D->getLambdaTypeInfo(), D->getLocation(),
+ D->isDependentLambda(), D->isGenericLambda(),
+ D->getLambdaCaptureDefault());
+ else
+ Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
+ D->getBeginLoc(), D->getLocation(),
+ D->getIdentifier(), PrevDecl);
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Record))
@@ -2281,6 +2314,20 @@
if (InstantiatedExplicitSpecifier.isInvalid())
return nullptr;
+ // Implicit destructors/constructors created for local classes in
+ // DeclareImplicit* (see SemaDeclCXX.cpp) might not have an associated TSI.
+ // Unfortunately there isn't enough context in those functions to
+ // conditionally populate the TSI without breaking non-template related use
+ // cases. Populate TSIs prior to calling SubstFunctionType to make sure we get
+ // a proper transformation.
+ if (cast<CXXRecordDecl>(D->getParent())->isLambda() &&
+ !D->getTypeSourceInfo() &&
+ isa<CXXConstructorDecl, CXXDestructorDecl>(D)) {
+ TypeSourceInfo *TSI =
+ SemaRef.Context.getTrivialTypeSourceInfo(D->getType());
+ D->setTypeSourceInfo(TSI);
+ }
+
SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
if (!TInfo)
@@ -2370,6 +2417,9 @@
Destructor->isInlineSpecified(), false, Destructor->getConstexprKind(),
TrailingRequiresClause);
Method->setRangeEnd(Destructor->getEndLoc());
+ Method->setDeclName(SemaRef.Context.DeclarationNames.getCXXDestructorName(
+ SemaRef.Context.getCanonicalType(
+ SemaRef.Context.getTypeDeclType(Record))));
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
Method = CXXConversionDecl::Create(
SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo,
@@ -2610,7 +2660,6 @@
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
TemplateTypeParmDecl *D) {
- // TODO: don't always clone when decls are refcounted.
assert(D->getTypeForDecl()->isTemplateTypeParmType());
Optional<unsigned> NumExpanded;
@@ -3009,6 +3058,53 @@
return Inst;
}
+Decl *TemplateDeclInstantiator::VisitBaseUsingDecls(BaseUsingDecl *D,
+ BaseUsingDecl *Inst,
+ LookupResult *Lookup) {
+
+ bool isFunctionScope = Owner->isFunctionOrMethod();
+
+ for (auto *Shadow : D->shadows()) {
+ // FIXME: UsingShadowDecl doesn't preserve its immediate target, so
+ // reconstruct it in the case where it matters. Hm, can we extract it from
+ // the DeclSpec when parsing and save it in the UsingDecl itself?
+ NamedDecl *OldTarget = Shadow->getTargetDecl();
+ if (auto *CUSD = dyn_cast<ConstructorUsingShadowDecl>(Shadow))
+ if (auto *BaseShadow = CUSD->getNominatedBaseClassShadowDecl())
+ OldTarget = BaseShadow;
+
+ NamedDecl *InstTarget = nullptr;
+ if (auto *EmptyD =
+ dyn_cast<UnresolvedUsingIfExistsDecl>(Shadow->getTargetDecl())) {
+ InstTarget = UnresolvedUsingIfExistsDecl::Create(
+ SemaRef.Context, Owner, EmptyD->getLocation(), EmptyD->getDeclName());
+ } else {
+ InstTarget = cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
+ Shadow->getLocation(), OldTarget, TemplateArgs));
+ }
+ if (!InstTarget)
+ return nullptr;
+
+ UsingShadowDecl *PrevDecl = nullptr;
+ if (Lookup &&
+ SemaRef.CheckUsingShadowDecl(Inst, InstTarget, *Lookup, PrevDecl))
+ continue;
+
+ if (UsingShadowDecl *OldPrev = getPreviousDeclForInstantiation(Shadow))
+ PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl(
+ Shadow->getLocation(), OldPrev, TemplateArgs));
+
+ UsingShadowDecl *InstShadow = SemaRef.BuildUsingShadowDecl(
+ /*Scope*/ nullptr, Inst, InstTarget, PrevDecl);
+ SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
+
+ if (isFunctionScope)
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow);
+ }
+
+ return Inst;
+}
+
Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
// The nested name specifier may be dependent, for example
@@ -3034,11 +3130,9 @@
NameInfo.setName(SemaRef.Context.DeclarationNames.getCXXConstructorName(
SemaRef.Context.getCanonicalType(SemaRef.Context.getRecordType(RD))));
- // We only need to do redeclaration lookups if we're in a class
- // scope (in fact, it's not really even possible in non-class
- // scopes).
+ // We only need to do redeclaration lookups if we're in a class scope (in
+ // fact, it's not really even possible in non-class scopes).
bool CheckRedeclaration = Owner->isRecord();
-
LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName,
Sema::ForVisibleRedeclaration);
@@ -3059,12 +3153,11 @@
D->hasTypename(), SS,
D->getLocation(), Prev))
NewUD->setInvalidDecl();
-
}
if (!NewUD->isInvalidDecl() &&
- SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(),
- SS, NameInfo, D->getLocation()))
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(), SS,
+ NameInfo, D->getLocation(), nullptr, D))
NewUD->setInvalidDecl();
SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
@@ -3075,46 +3168,39 @@
if (NewUD->isInvalidDecl())
return NewUD;
+ // If the using scope was dependent, or we had dependent bases, we need to
+ // recheck the inheritance
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName)
SemaRef.CheckInheritingConstructorUsingDecl(NewUD);
- bool isFunctionScope = Owner->isFunctionOrMethod();
+ return VisitBaseUsingDecls(D, NewUD, CheckRedeclaration ? &Prev : nullptr);
+}
- // Process the shadow decls.
- for (auto *Shadow : D->shadows()) {
- // FIXME: UsingShadowDecl doesn't preserve its immediate target, so
- // reconstruct it in the case where it matters.
- NamedDecl *OldTarget = Shadow->getTargetDecl();
- if (auto *CUSD = dyn_cast<ConstructorUsingShadowDecl>(Shadow))
- if (auto *BaseShadow = CUSD->getNominatedBaseClassShadowDecl())
- OldTarget = BaseShadow;
+Decl *TemplateDeclInstantiator::VisitUsingEnumDecl(UsingEnumDecl *D) {
+ // Cannot be a dependent type, but still could be an instantiation
+ EnumDecl *EnumD = cast_or_null<EnumDecl>(SemaRef.FindInstantiatedDecl(
+ D->getLocation(), D->getEnumDecl(), TemplateArgs));
- NamedDecl *InstTarget =
- cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
- Shadow->getLocation(), OldTarget, TemplateArgs));
- if (!InstTarget)
- return nullptr;
+ if (SemaRef.RequireCompleteEnumDecl(EnumD, EnumD->getLocation()))
+ return nullptr;
- UsingShadowDecl *PrevDecl = nullptr;
- if (CheckRedeclaration) {
- if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl))
- continue;
- } else if (UsingShadowDecl *OldPrev =
- getPreviousDeclForInstantiation(Shadow)) {
- PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl(
- Shadow->getLocation(), OldPrev, TemplateArgs));
- }
+ UsingEnumDecl *NewUD =
+ UsingEnumDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(),
+ D->getEnumLoc(), D->getLocation(), EnumD);
- UsingShadowDecl *InstShadow =
- SemaRef.BuildUsingShadowDecl(/*Scope*/nullptr, NewUD, InstTarget,
- PrevDecl);
- SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
+ SemaRef.Context.setInstantiatedFromUsingEnumDecl(NewUD, D);
+ NewUD->setAccess(D->getAccess());
+ Owner->addDecl(NewUD);
- if (isFunctionScope)
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow);
- }
+ // Don't process the shadow decls for an invalid decl.
+ if (NewUD->isInvalidDecl())
+ return NewUD;
- return NewUD;
+ // We don't have to recheck for duplication of the UsingEnumDecl itself, as it
+ // cannot be dependent, and will therefore have been checked during template
+ // definition.
+
+ return VisitBaseUsingDecls(D, NewUD, nullptr);
}
Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
@@ -3214,13 +3300,16 @@
SourceLocation EllipsisLoc =
InstantiatingSlice ? SourceLocation() : D->getEllipsisLoc();
+ bool IsUsingIfExists = D->template hasAttr<UsingIfExistsAttr>();
NamedDecl *UD = SemaRef.BuildUsingDeclaration(
/*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(),
/*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc,
ParsedAttributesView(),
- /*IsInstantiation*/ true);
- if (UD)
+ /*IsInstantiation*/ true, IsUsingIfExists);
+ if (UD) {
+ SemaRef.InstantiateAttrs(TemplateArgs, D, UD);
SemaRef.Context.setInstantiatedFromUsingDecl(UD, D);
+ }
return UD;
}
@@ -3235,6 +3324,11 @@
return instantiateUnresolvedUsingDecl(D);
}
+Decl *TemplateDeclInstantiator::VisitUnresolvedUsingIfExistsDecl(
+ UnresolvedUsingIfExistsDecl *D) {
+ llvm_unreachable("referring to unresolved decl out of UsingShadowDecl");
+}
+
Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) {
SmallVector<NamedDecl*, 8> Expansions;
for (auto *UD : D->expansions()) {
@@ -4841,16 +4935,85 @@
// Introduce a new scope where local variable instantiations will be
// recorded, unless we're actually a member function within a local
// class, in which case we need to merge our results with the parent
- // scope (of the enclosing function).
+ // scope (of the enclosing function). The exception is instantiating
+ // a function template specialization, since the template to be
+ // instantiated already has references to locals properly substituted.
bool MergeWithParentScope = false;
if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
- MergeWithParentScope = Rec->isLocalClass();
+ MergeWithParentScope =
+ Rec->isLocalClass() && !Function->isFunctionTemplateSpecialization();
LocalInstantiationScope Scope(*this, MergeWithParentScope);
+ auto RebuildTypeSourceInfoForDefaultSpecialMembers = [&]() {
+ // Special members might get their TypeSourceInfo set up w.r.t the
+ // PatternDecl context, in which case parameters could still be pointing
+ // back to the original class, make sure arguments are bound to the
+ // instantiated record instead.
+ assert(PatternDecl->isDefaulted() &&
+ "Special member needs to be defaulted");
+ auto PatternSM = getDefaultedFunctionKind(PatternDecl).asSpecialMember();
+ if (!(PatternSM == Sema::CXXCopyConstructor ||
+ PatternSM == Sema::CXXCopyAssignment ||
+ PatternSM == Sema::CXXMoveConstructor ||
+ PatternSM == Sema::CXXMoveAssignment))
+ return;
- if (PatternDecl->isDefaulted())
+ auto *NewRec = dyn_cast<CXXRecordDecl>(Function->getDeclContext());
+ const auto *PatternRec =
+ dyn_cast<CXXRecordDecl>(PatternDecl->getDeclContext());
+ if (!NewRec || !PatternRec)
+ return;
+ if (!PatternRec->isLambda())
+ return;
+
+ struct SpecialMemberTypeInfoRebuilder
+ : TreeTransform<SpecialMemberTypeInfoRebuilder> {
+ using Base = TreeTransform<SpecialMemberTypeInfoRebuilder>;
+ const CXXRecordDecl *OldDecl;
+ CXXRecordDecl *NewDecl;
+
+ SpecialMemberTypeInfoRebuilder(Sema &SemaRef, const CXXRecordDecl *O,
+ CXXRecordDecl *N)
+ : TreeTransform(SemaRef), OldDecl(O), NewDecl(N) {}
+
+ bool TransformExceptionSpec(SourceLocation Loc,
+ FunctionProtoType::ExceptionSpecInfo &ESI,
+ SmallVectorImpl<QualType> &Exceptions,
+ bool &Changed) {
+ return false;
+ }
+
+ QualType TransformRecordType(TypeLocBuilder &TLB, RecordTypeLoc TL) {
+ const RecordType *T = TL.getTypePtr();
+ RecordDecl *Record = cast_or_null<RecordDecl>(
+ getDerived().TransformDecl(TL.getNameLoc(), T->getDecl()));
+ if (Record != OldDecl)
+ return Base::TransformRecordType(TLB, TL);
+
+ QualType Result = getDerived().RebuildRecordType(NewDecl);
+ if (Result.isNull())
+ return QualType();
+
+ RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+ }
+ } IR{*this, PatternRec, NewRec};
+
+ TypeSourceInfo *NewSI = IR.TransformType(Function->getTypeSourceInfo());
+ Function->setType(NewSI->getType());
+ Function->setTypeSourceInfo(NewSI);
+
+ ParmVarDecl *Parm = Function->getParamDecl(0);
+ TypeSourceInfo *NewParmSI = IR.TransformType(Parm->getTypeSourceInfo());
+ Parm->setType(NewParmSI->getType());
+ Parm->setTypeSourceInfo(NewParmSI);
+ };
+
+ if (PatternDecl->isDefaulted()) {
+ RebuildTypeSourceInfoForDefaultSpecialMembers();
SetDeclDefaulted(Function, PatternDecl->getLocation());
- else {
+ } else {
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
@@ -5030,7 +5193,6 @@
NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl());
NewVar->setObjCForDecl(OldVar->isObjCForDecl());
NewVar->setConstexpr(OldVar->isConstexpr());
- MaybeAddCUDAConstantAttr(NewVar);
NewVar->setInitCapture(OldVar->isInitCapture());
NewVar->setPreviousDeclInSameBlockScope(
OldVar->isPreviousDeclInSameBlockScope());
diff --git a/src/llvm-project/clang/lib/Sema/SemaType.cpp b/src/llvm-project/clang/lib/Sema/SemaType.cpp
index 4178024..bca21b3 100644
--- a/src/llvm-project/clang/lib/Sema/SemaType.cpp
+++ b/src/llvm-project/clang/lib/Sema/SemaType.cpp
@@ -117,6 +117,7 @@
case ParsedAttr::AT_RegCall: \
case ParsedAttr::AT_Pascal: \
case ParsedAttr::AT_SwiftCall: \
+ case ParsedAttr::AT_SwiftAsyncCall: \
case ParsedAttr::AT_VectorCall: \
case ParsedAttr::AT_AArch64VectorPcs: \
case ParsedAttr::AT_MSABI: \
@@ -634,7 +635,7 @@
// C++11 attributes before the decl specifiers actually appertain to
// the declarators. Move them straight there. We don't support the
// 'put them wherever you like' semantics we allow for GNU attributes.
- if (attr.isCXX11Attribute()) {
+ if (attr.isStandardAttributeSyntax()) {
moveAttrFromListToList(attr, state.getCurrentAttributes(),
state.getDeclarator().getAttributes());
return;
@@ -687,9 +688,9 @@
// non-owning copy and iterate over that.
ParsedAttributesView AttrsCopy{state.getDeclarator().getAttributes()};
for (ParsedAttr &attr : AttrsCopy) {
- // Do not distribute C++11 attributes. They have strict rules for what
+ // Do not distribute [[]] attributes. They have strict rules for what
// they appertain to.
- if (attr.isCXX11Attribute())
+ if (attr.isStandardAttributeSyntax())
continue;
switch (attr.getKind()) {
@@ -1256,26 +1257,6 @@
return OpenCLAccessAttr::Keyword_read_only;
}
-static QualType ConvertConstrainedAutoDeclSpecToType(Sema &S, DeclSpec &DS,
- AutoTypeKeyword AutoKW) {
- assert(DS.isConstrainedAuto());
- TemplateIdAnnotation *TemplateId = DS.getRepAsTemplateId();
- TemplateArgumentListInfo TemplateArgsInfo;
- TemplateArgsInfo.setLAngleLoc(TemplateId->LAngleLoc);
- TemplateArgsInfo.setRAngleLoc(TemplateId->RAngleLoc);
- ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- S.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo);
- llvm::SmallVector<TemplateArgument, 8> TemplateArgs;
- for (auto &ArgLoc : TemplateArgsInfo.arguments())
- TemplateArgs.push_back(ArgLoc.getArgument());
- return S.Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false,
- /*IsPack=*/false,
- cast<ConceptDecl>(TemplateId->Template.get()
- .getAsTemplateDecl()),
- TemplateArgs);
-}
-
/// Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
@@ -1548,6 +1529,16 @@
Result = Context.LongDoubleTy;
else
Result = Context.DoubleTy;
+ if (S.getLangOpts().OpenCL) {
+ if (!S.getOpenCLOptions().isSupported("cl_khr_fp64", S.getLangOpts()))
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension)
+ << 0 << Result
+ << (S.getLangOpts().OpenCLVersion == 300
+ ? "cl_khr_fp64 and __opencl_c_fp64"
+ : "cl_khr_fp64");
+ else if (!S.getOpenCLOptions().isAvailableOption("cl_khr_fp64", S.getLangOpts()))
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::ext_opencl_double_without_pragma);
+ }
break;
case DeclSpec::TST_float128:
if (!S.Context.getTargetInfo().hasFloat128Type() &&
@@ -1656,29 +1647,39 @@
break;
case DeclSpec::TST_auto:
+ case DeclSpec::TST_decltype_auto: {
+ auto AutoKW = DS.getTypeSpecType() == DeclSpec::TST_decltype_auto
+ ? AutoTypeKeyword::DecltypeAuto
+ : AutoTypeKeyword::Auto;
+
+ ConceptDecl *TypeConstraintConcept = nullptr;
+ llvm::SmallVector<TemplateArgument, 8> TemplateArgs;
if (DS.isConstrainedAuto()) {
- Result = ConvertConstrainedAutoDeclSpecToType(S, DS,
- AutoTypeKeyword::Auto);
- break;
+ if (TemplateIdAnnotation *TemplateId = DS.getRepAsTemplateId()) {
+ TypeConstraintConcept =
+ cast<ConceptDecl>(TemplateId->Template.get().getAsTemplateDecl());
+ TemplateArgumentListInfo TemplateArgsInfo;
+ TemplateArgsInfo.setLAngleLoc(TemplateId->LAngleLoc);
+ TemplateArgsInfo.setRAngleLoc(TemplateId->RAngleLoc);
+ ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+ S.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo);
+ for (const auto &ArgLoc : TemplateArgsInfo.arguments())
+ TemplateArgs.push_back(ArgLoc.getArgument());
+ } else {
+ declarator.setInvalidType(true);
+ }
}
- Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
+ Result = S.Context.getAutoType(QualType(), AutoKW,
+ /*IsDependent*/ false, /*IsPack=*/false,
+ TypeConstraintConcept, TemplateArgs);
break;
+ }
case DeclSpec::TST_auto_type:
Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false);
break;
- case DeclSpec::TST_decltype_auto:
- if (DS.isConstrainedAuto()) {
- Result =
- ConvertConstrainedAutoDeclSpecToType(S, DS,
- AutoTypeKeyword::DecltypeAuto);
- break;
- }
- Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto,
- /*IsDependent*/ false);
- break;
-
case DeclSpec::TST_unknown_anytype:
Result = Context.UnknownAnyTy;
break;
@@ -1723,9 +1724,33 @@
if (Result->containsErrors())
declarator.setInvalidType();
- if (S.getLangOpts().OpenCL &&
- S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
- declarator.setInvalidType(true);
+ if (S.getLangOpts().OpenCL) {
+ const auto &OpenCLOptions = S.getOpenCLOptions();
+ bool IsOpenCLC30 = (S.getLangOpts().OpenCLVersion == 300);
+ // OpenCL C v3.0 s6.3.3 - OpenCL image types require __opencl_c_images
+ // support.
+ // OpenCL C v3.0 s6.2.1 - OpenCL 3d image write types requires support
+ // for OpenCL C 2.0, or OpenCL C 3.0 or newer and the
+ // __opencl_c_3d_image_writes feature. OpenCL C v3.0 API s4.2 - For devices
+ // that support OpenCL 3.0, cl_khr_3d_image_writes must be returned when and
+ // only when the optional feature is supported
+ if ((Result->isImageType() || Result->isSamplerT()) &&
+ (IsOpenCLC30 &&
+ !OpenCLOptions.isSupported("__opencl_c_images", S.getLangOpts()))) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension)
+ << 0 << Result << "__opencl_c_images";
+ declarator.setInvalidType();
+ } else if (Result->isOCLImage3dWOType() &&
+ !OpenCLOptions.isSupported("cl_khr_3d_image_writes",
+ S.getLangOpts())) {
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_opencl_requires_extension)
+ << 0 << Result
+ << (IsOpenCLC30
+ ? "cl_khr_3d_image_writes and __opencl_c_3d_image_writes"
+ : "cl_khr_3d_image_writes");
+ declarator.setInvalidType();
+ }
+ }
bool IsFixedPointType = DS.getTypeSpecType() == DeclSpec::TST_accum ||
DS.getTypeSpecType() == DeclSpec::TST_fract;
@@ -2060,10 +2085,9 @@
!PointeeType->isSamplerT() &&
!PointeeType.hasAddressSpace())
PointeeType = S.getASTContext().getAddrSpaceQualType(
- PointeeType,
- S.getLangOpts().OpenCLCPlusPlus || S.getLangOpts().OpenCLVersion == 200
- ? LangAS::opencl_generic
- : LangAS::opencl_private);
+ PointeeType, S.getLangOpts().OpenCLGenericAddressSpace
+ ? LangAS::opencl_generic
+ : LangAS::opencl_private);
return PointeeType;
}
@@ -2090,8 +2114,9 @@
}
if (T->isFunctionType() && getLangOpts().OpenCL &&
- !getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) {
- Diag(Loc, diag::err_opencl_function_pointer);
+ !getOpenCLOptions().isAvailableOption("__cl_clang_function_pointers",
+ getLangOpts())) {
+ Diag(Loc, diag::err_opencl_function_pointer) << /*pointer*/ 0;
return QualType();
}
@@ -2163,6 +2188,13 @@
if (checkQualifiedFunction(*this, T, Loc, QFK_Reference))
return QualType();
+ if (T->isFunctionType() && getLangOpts().OpenCL &&
+ !getOpenCLOptions().isAvailableOption("__cl_clang_function_pointers",
+ getLangOpts())) {
+ Diag(Loc, diag::err_opencl_function_pointer) << /*reference*/ 1;
+ return QualType();
+ }
+
// In ARC, it is forbidden to build references to unqualified pointers.
if (getLangOpts().ObjCAutoRefCount)
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
@@ -2389,7 +2421,7 @@
}
// Do lvalue-to-rvalue conversions on the array size expression.
- if (ArraySize && !ArraySize->isRValue()) {
+ if (ArraySize && !ArraySize->isPRValue()) {
ExprResult Result = DefaultLvalueConversion(ArraySize);
if (Result.isInvalid())
return QualType();
@@ -2490,7 +2522,7 @@
: ConstVal.getActiveBits();
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
- << ConstVal.toString(10) << ArraySize->getSourceRange();
+ << toString(ConstVal, 10) << ArraySize->getSourceRange();
return QualType();
}
@@ -2758,16 +2790,21 @@
llvm::function_ref<SourceLocation(unsigned)> getParamLoc) {
assert(EPI.ExtParameterInfos && "shouldn't get here without param infos");
- bool hasCheckedSwiftCall = false;
- auto checkForSwiftCC = [&](unsigned paramIndex) {
- // Only do this once.
- if (hasCheckedSwiftCall) return;
- hasCheckedSwiftCall = true;
- if (EPI.ExtInfo.getCC() == CC_Swift) return;
+ bool emittedError = false;
+ auto actualCC = EPI.ExtInfo.getCC();
+ enum class RequiredCC { OnlySwift, SwiftOrSwiftAsync };
+ auto checkCompatible = [&](unsigned paramIndex, RequiredCC required) {
+ bool isCompatible =
+ (required == RequiredCC::OnlySwift)
+ ? (actualCC == CC_Swift)
+ : (actualCC == CC_Swift || actualCC == CC_SwiftAsync);
+ if (isCompatible || emittedError)
+ return;
S.Diag(getParamLoc(paramIndex), diag::err_swift_param_attr_not_swiftcall)
- << getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI());
+ << getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI())
+ << (required == RequiredCC::OnlySwift);
+ emittedError = true;
};
-
for (size_t paramIndex = 0, numParams = paramTypes.size();
paramIndex != numParams; ++paramIndex) {
switch (EPI.ExtParameterInfos[paramIndex].getABI()) {
@@ -2778,7 +2815,7 @@
// swift_indirect_result parameters must be a prefix of the function
// arguments.
case ParameterABI::SwiftIndirectResult:
- checkForSwiftCC(paramIndex);
+ checkCompatible(paramIndex, RequiredCC::SwiftOrSwiftAsync);
if (paramIndex != 0 &&
EPI.ExtParameterInfos[paramIndex - 1].getABI()
!= ParameterABI::SwiftIndirectResult) {
@@ -2788,12 +2825,16 @@
continue;
case ParameterABI::SwiftContext:
- checkForSwiftCC(paramIndex);
+ checkCompatible(paramIndex, RequiredCC::SwiftOrSwiftAsync);
+ continue;
+
+ // SwiftAsyncContext is not limited to swiftasynccall functions.
+ case ParameterABI::SwiftAsyncContext:
continue;
// swift_error parameters must be preceded by a swift_context parameter.
case ParameterABI::SwiftErrorResult:
- checkForSwiftCC(paramIndex);
+ checkCompatible(paramIndex, RequiredCC::OnlySwift);
if (paramIndex == 0 ||
EPI.ExtParameterInfos[paramIndex - 1].getABI() !=
ParameterABI::SwiftContext) {
@@ -2889,6 +2930,13 @@
return QualType();
}
+ if (T->isFunctionType() && getLangOpts().OpenCL &&
+ !getOpenCLOptions().isAvailableOption("__cl_clang_function_pointers",
+ getLangOpts())) {
+ Diag(Loc, diag::err_opencl_function_pointer) << /*pointer*/ 0;
+ return QualType();
+ }
+
// Adjust the default free function calling convention to the default method
// calling convention.
bool IsCtorOrDtor =
@@ -3205,31 +3253,52 @@
// extract its type constraints to attach to the template parameter.
AutoTypeLoc AutoLoc = TrailingTSI->getTypeLoc().getContainedAutoTypeLoc();
TemplateArgumentListInfo TAL(AutoLoc.getLAngleLoc(), AutoLoc.getRAngleLoc());
- for (unsigned Idx = 0; Idx < AutoLoc.getNumArgs(); ++Idx)
+ bool Invalid = false;
+ for (unsigned Idx = 0; Idx < AutoLoc.getNumArgs(); ++Idx) {
+ if (D.getEllipsisLoc().isInvalid() && !Invalid &&
+ S.DiagnoseUnexpandedParameterPack(AutoLoc.getArgLoc(Idx),
+ Sema::UPPC_TypeConstraint))
+ Invalid = true;
TAL.addArgument(AutoLoc.getArgLoc(Idx));
+ }
- S.AttachTypeConstraint(AutoLoc.getNestedNameSpecifierLoc(),
- AutoLoc.getConceptNameInfo(),
- AutoLoc.getNamedConcept(),
- AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr,
- InventedTemplateParam, D.getEllipsisLoc());
+ if (!Invalid) {
+ S.AttachTypeConstraint(
+ AutoLoc.getNestedNameSpecifierLoc(), AutoLoc.getConceptNameInfo(),
+ AutoLoc.getNamedConcept(),
+ AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr,
+ InventedTemplateParam, D.getEllipsisLoc());
+ }
} else {
// The 'auto' appears in the decl-specifiers; we've not finished forming
// TypeSourceInfo for it yet.
TemplateIdAnnotation *TemplateId = D.getDeclSpec().getRepAsTemplateId();
TemplateArgumentListInfo TemplateArgsInfo;
+ bool Invalid = false;
if (TemplateId->LAngleLoc.isValid()) {
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
S.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo);
+
+ if (D.getEllipsisLoc().isInvalid()) {
+ for (TemplateArgumentLoc Arg : TemplateArgsInfo.arguments()) {
+ if (S.DiagnoseUnexpandedParameterPack(Arg,
+ Sema::UPPC_TypeConstraint)) {
+ Invalid = true;
+ break;
+ }
+ }
+ }
}
- S.AttachTypeConstraint(
- D.getDeclSpec().getTypeSpecScope().getWithLocInContext(S.Context),
- DeclarationNameInfo(DeclarationName(TemplateId->Name),
- TemplateId->TemplateNameLoc),
- cast<ConceptDecl>(TemplateId->Template.get().getAsTemplateDecl()),
- TemplateId->LAngleLoc.isValid() ? &TemplateArgsInfo : nullptr,
- InventedTemplateParam, D.getEllipsisLoc());
+ if (!Invalid) {
+ S.AttachTypeConstraint(
+ D.getDeclSpec().getTypeSpecScope().getWithLocInContext(S.Context),
+ DeclarationNameInfo(DeclarationName(TemplateId->Name),
+ TemplateId->TemplateNameLoc),
+ cast<ConceptDecl>(TemplateId->Template.get().getAsTemplateDecl()),
+ TemplateId->LAngleLoc.isValid() ? &TemplateArgsInfo : nullptr,
+ InventedTemplateParam, D.getEllipsisLoc());
+ }
}
}
@@ -4994,7 +5063,8 @@
// FIXME: This really should be in BuildFunctionType.
if (T->isHalfType()) {
if (S.getLangOpts().OpenCL) {
- if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
+ if (!S.getOpenCLOptions().isAvailableOption("cl_khr_fp16",
+ S.getLangOpts())) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
<< T << 0 /*pointer hint*/;
D.setInvalidType(true);
@@ -5019,7 +5089,8 @@
// (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
// We also allow here any toolchain reserved identifiers.
if (FTI.isVariadic &&
- !S.getOpenCLOptions().isEnabled("__cl_clang_variadic_functions") &&
+ !S.getOpenCLOptions().isAvailableOption(
+ "__cl_clang_variadic_functions", S.getLangOpts()) &&
!(D.getIdentifier() &&
((D.getIdentifier()->getName() == "printf" &&
(LangOpts.OpenCLCPlusPlus || LangOpts.OpenCLVersion >= 120)) ||
@@ -5214,7 +5285,8 @@
// Disallow half FP parameters.
// FIXME: This really should be in BuildFunctionType.
if (S.getLangOpts().OpenCL) {
- if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
+ if (!S.getOpenCLOptions().isAvailableOption("cl_khr_fp16",
+ S.getLangOpts())) {
S.Diag(Param->getLocation(), diag::err_opencl_invalid_param)
<< ParamTy << 0;
D.setInvalidType();
@@ -5946,6 +6018,8 @@
if (!DS.isConstrainedAuto())
return;
TemplateIdAnnotation *TemplateId = DS.getRepAsTemplateId();
+ if (!TemplateId)
+ return;
if (DS.getTypeSpecScope().isNotEmpty())
TL.setNestedNameSpecifierLoc(
DS.getTypeSpecScope().getWithLocInContext(Context));
@@ -6369,6 +6443,7 @@
llvm::APSInt max(addrSpace.getBitWidth());
max =
Qualifiers::MaxAddressSpace - (unsigned)LangAS::FirstTargetAddressSpace;
+
if (addrSpace > max) {
S.Diag(AttrLoc, diag::err_attribute_address_space_too_high)
<< (unsigned)max.getZExtValue() << AddrSpace->getSourceRange();
@@ -6484,7 +6559,9 @@
Attr.setInvalid();
} else {
// The keyword-based type attributes imply which address space to use.
- ASIdx = Attr.asOpenCLLangAS();
+ ASIdx = S.getLangOpts().SYCLIsDevice ? Attr.asSYCLLangAS()
+ : Attr.asOpenCLLangAS();
+
if (ASIdx == LangAS::Default)
llvm_unreachable("Invalid address space");
@@ -7299,6 +7376,8 @@
return createSimpleAttr<PascalAttr>(Ctx, Attr);
case ParsedAttr::AT_SwiftCall:
return createSimpleAttr<SwiftCallAttr>(Ctx, Attr);
+ case ParsedAttr::AT_SwiftAsyncCall:
+ return createSimpleAttr<SwiftAsyncCallAttr>(Ctx, Attr);
case ParsedAttr::AT_VectorCall:
return createSimpleAttr<VectorCallAttr>(Ctx, Attr);
case ParsedAttr::AT_AArch64VectorPcs:
@@ -7959,8 +8038,6 @@
CurType = State.getAttributedType(
createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
CurType, CurType);
- } else {
- Attr.diagnoseAppertainsTo(State.getSema(), nullptr);
}
}
@@ -7998,7 +8075,7 @@
if (attr.isInvalid())
continue;
- if (attr.isCXX11Attribute()) {
+ if (attr.isStandardAttributeSyntax()) {
// [[gnu::...]] attributes are treated as declaration attributes, so may
// not appertain to a DeclaratorChunk. If we handle them as type
// attributes, accept them in that position and diagnose the GCC
@@ -8027,8 +8104,8 @@
// otherwise, add it to the FnAttrs list for rechaining.
switch (attr.getKind()) {
default:
- // A C++11 attribute on a declarator chunk must appertain to a type.
- if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) {
+ // A [[]] attribute on a declarator chunk must appertain to a type.
+ if (attr.isStandardAttributeSyntax() && TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr)
<< attr;
attr.setUsedAsTypeAttr();
@@ -8036,7 +8113,7 @@
break;
case ParsedAttr::UnknownAttribute:
- if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
+ if (attr.isStandardAttributeSyntax() && TAL == TAL_DeclChunk)
state.getSema().Diag(attr.getLoc(),
diag::warn_unknown_attribute_ignored)
<< attr << attr.getRange();
@@ -8823,6 +8900,29 @@
return Context.getTypeOfExprType(E);
}
+/// getDecltypeForParenthesizedExpr - Given an expr, will return the type for
+/// that expression, as in [dcl.type.simple]p4 but without taking id-expressions
+/// and class member access into account.
+QualType Sema::getDecltypeForParenthesizedExpr(Expr *E) {
+ // C++11 [dcl.type.simple]p4:
+ // [...]
+ QualType T = E->getType();
+ switch (E->getValueKind()) {
+ // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the
+ // type of e;
+ case VK_XValue:
+ return Context.getRValueReferenceType(T);
+ // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the
+ // type of e;
+ case VK_LValue:
+ return Context.getLValueReferenceType(T);
+ // - otherwise, decltype(e) is the type of e.
+ case VK_PRValue:
+ return T;
+ }
+ llvm_unreachable("Unknown value kind");
+}
+
/// getDecltypeForExpr - Given an expr, will return the decltype for
/// that expression, according to the rules in C++11
/// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18.
@@ -8830,6 +8930,10 @@
if (E->isTypeDependent())
return S.Context.DependentTy;
+ Expr *IDExpr = E;
+ if (auto *ImplCastExpr = dyn_cast<ImplicitCastExpr>(E))
+ IDExpr = ImplCastExpr->getSubExpr();
+
// C++11 [dcl.type.simple]p4:
// The type denoted by decltype(e) is defined as follows:
@@ -8840,7 +8944,7 @@
// Note that this does not pick up the implicit 'const' for a template
// parameter object. This rule makes no difference before C++20 so we apply
// it unconditionally.
- if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
+ if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(IDExpr))
return SNTTPE->getParameterType(S.Context);
// - if e is an unparenthesized id-expression or an unparenthesized class
@@ -8849,21 +8953,22 @@
// functions, the program is ill-formed;
//
// We apply the same rules for Objective-C ivar and property references.
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr)) {
const ValueDecl *VD = DRE->getDecl();
if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD))
return TPO->getType().getUnqualifiedType();
return VD->getType();
- } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+ } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(IDExpr)) {
if (const ValueDecl *VD = ME->getMemberDecl())
if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
return VD->getType();
- } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
+ } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(IDExpr)) {
return IR->getDecl()->getType();
- } else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
+ } else if (const ObjCPropertyRefExpr *PR =
+ dyn_cast<ObjCPropertyRefExpr>(IDExpr)) {
if (PR->isExplicitProperty())
return PR->getExplicitProperty()->getType();
- } else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
+ } else if (auto *PE = dyn_cast<PredefinedExpr>(IDExpr)) {
return PE->getType();
}
@@ -8876,8 +8981,8 @@
// entity.
using namespace sema;
if (S.getCurLambda()) {
- if (isa<ParenExpr>(E)) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+ if (isa<ParenExpr>(IDExpr)) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
if (!T.isNull())
@@ -8887,22 +8992,7 @@
}
}
-
- // C++11 [dcl.type.simple]p4:
- // [...]
- QualType T = E->getType();
- switch (E->getValueKind()) {
- // - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the
- // type of e;
- case VK_XValue: T = S.Context.getRValueReferenceType(T); break;
- // - otherwise, if e is an lvalue, decltype(e) is T&, where T is the
- // type of e;
- case VK_LValue: T = S.Context.getLValueReferenceType(T); break;
- // - otherwise, decltype(e) is the type of e.
- case VK_RValue: break;
- }
-
- return T;
+ return S.getDecltypeForParenthesizedExpr(E);
}
QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
diff --git a/src/llvm-project/clang/lib/Sema/TreeTransform.h b/src/llvm-project/clang/lib/Sema/TreeTransform.h
index 3c68f94..70ba631 100644
--- a/src/llvm-project/clang/lib/Sema/TreeTransform.h
+++ b/src/llvm-project/clang/lib/Sema/TreeTransform.h
@@ -1311,9 +1311,9 @@
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildAttributedStmt(SourceLocation AttrLoc,
- ArrayRef<const Attr*> Attrs,
+ ArrayRef<const Attr *> Attrs,
Stmt *SubStmt) {
- return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
+ return SemaRef.BuildAttributedStmt(AttrLoc, Attrs, SubStmt);
}
/// Build a new "if" statement.
@@ -1546,6 +1546,14 @@
return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
}
+ /// Build a new OpenMP Canonical loop.
+ ///
+ /// Ensures that the outermost loop in @p LoopStmt is wrapped by a
+ /// OMPCanonicalLoop.
+ StmtResult RebuildOMPCanonicalLoop(Stmt *LoopStmt) {
+ return getSema().ActOnOpenMPCanonicalLoop(LoopStmt);
+ }
+
/// Build a new OpenMP executable directive.
///
/// By default, performs semantic analysis to build the new statement.
@@ -1618,6 +1626,27 @@
return getSema().ActOnOpenMPSimdlenClause(Len, StartLoc, LParenLoc, EndLoc);
}
+ OMPClause *RebuildOMPSizesClause(ArrayRef<Expr *> Sizes,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPSizesClause(Sizes, StartLoc, LParenLoc, EndLoc);
+ }
+
+ /// Build a new OpenMP 'full' clause.
+ OMPClause *RebuildOMPFullClause(SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPFullClause(StartLoc, EndLoc);
+ }
+
+ /// Build a new OpenMP 'partial' clause.
+ OMPClause *RebuildOMPPartialClause(Expr *Factor, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPPartialClause(Factor, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// Build a new OpenMP 'allocator' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -2155,6 +2184,78 @@
LParenLoc, EndLoc);
}
+ /// Build a new OpenMP 'init' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs,
+ bool IsTarget, bool IsTargetSync,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation VarLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPInitClause(InteropVar, PrefExprs, IsTarget,
+ IsTargetSync, StartLoc, LParenLoc,
+ VarLoc, EndLoc);
+ }
+
+ /// Build a new OpenMP 'use' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation VarLoc, SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPUseClause(InteropVar, StartLoc, LParenLoc,
+ VarLoc, EndLoc);
+ }
+
+ /// Build a new OpenMP 'destroy' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation VarLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDestroyClause(InteropVar, StartLoc, LParenLoc,
+ VarLoc, EndLoc);
+ }
+
+ /// Build a new OpenMP 'novariants' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPNovariantsClause(Expr *Condition,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPNovariantsClause(Condition, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// Build a new OpenMP 'nocontext' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPNocontextClause(Expr *Condition, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPNocontextClause(Condition, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
+ /// Build a new OpenMP 'filter' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPFilterClause(Expr *ThreadID, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPFilterClause(ThreadID, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -2312,6 +2413,13 @@
return SEHFinallyStmt::Create(getSema().getASTContext(), Loc, Block);
}
+ ExprResult RebuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+ SourceLocation LParen,
+ SourceLocation RParen,
+ TypeSourceInfo *TSI) {
+ return getSema().BuildSYCLUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
+ }
+
/// Build a new predefined expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -3121,8 +3229,9 @@
if (Constructor->isInheritingConstructor())
FoundCtor = Constructor->getInheritedConstructor().getConstructor();
- SmallVector<Expr*, 8> ConvertedArgs;
- if (getSema().CompleteConstructorCall(FoundCtor, Args, Loc, ConvertedArgs))
+ SmallVector<Expr *, 8> ConvertedArgs;
+ if (getSema().CompleteConstructorCall(FoundCtor, T, Args, Loc,
+ ConvertedArgs))
return ExprError();
return getSema().BuildCXXConstructExpr(Loc, T, Constructor,
@@ -3504,7 +3613,7 @@
FunctionDecl *Builtin = cast<FunctionDecl>(Lookup.front());
Expr *Callee = new (SemaRef.Context)
DeclRefExpr(SemaRef.Context, Builtin, false,
- SemaRef.Context.BuiltinFnTy, VK_RValue, BuiltinLoc);
+ SemaRef.Context.BuiltinFnTy, VK_PRValue, BuiltinLoc);
QualType CalleePtrTy = SemaRef.Context.getPointerType(Builtin->getType());
Callee = SemaRef.ImpCastExprToType(Callee, CalleePtrTy,
CK_BuiltinFnToFnPtr).get();
@@ -3943,12 +4052,10 @@
return Sema::ConditionResult();
}
-template<typename Derived>
-NestedNameSpecifierLoc
-TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
- NestedNameSpecifierLoc NNS,
- QualType ObjectType,
- NamedDecl *FirstQualifierInScope) {
+template <typename Derived>
+NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS, QualType ObjectType,
+ NamedDecl *FirstQualifierInScope) {
SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier;
Qualifier = Qualifier.getPrefix())
@@ -3962,28 +4069,26 @@
switch (QNNS->getKind()) {
case NestedNameSpecifier::Identifier: {
Sema::NestedNameSpecInfo IdInfo(QNNS->getAsIdentifier(),
- Q.getLocalBeginLoc(), Q.getLocalEndLoc(), ObjectType);
+ Q.getLocalBeginLoc(), Q.getLocalEndLoc(),
+ ObjectType);
if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo, false,
SS, FirstQualifierInScope, false))
return NestedNameSpecifierLoc();
- }
break;
+ }
case NestedNameSpecifier::Namespace: {
- NamespaceDecl *NS
- = cast_or_null<NamespaceDecl>(
- getDerived().TransformDecl(
- Q.getLocalBeginLoc(),
- QNNS->getAsNamespace()));
+ NamespaceDecl *NS =
+ cast_or_null<NamespaceDecl>(getDerived().TransformDecl(
+ Q.getLocalBeginLoc(), QNNS->getAsNamespace()));
SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc());
break;
}
case NestedNameSpecifier::NamespaceAlias: {
- NamespaceAliasDecl *Alias
- = cast_or_null<NamespaceAliasDecl>(
- getDerived().TransformDecl(Q.getLocalBeginLoc(),
- QNNS->getAsNamespaceAlias()));
+ NamespaceAliasDecl *Alias =
+ cast_or_null<NamespaceAliasDecl>(getDerived().TransformDecl(
+ Q.getLocalBeginLoc(), QNNS->getAsNamespaceAlias()));
SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(),
Q.getLocalEndLoc());
break;
@@ -4019,7 +4124,7 @@
if (TL.getType()->isEnumeralType())
SemaRef.Diag(TL.getBeginLoc(),
diag::warn_cxx98_compat_enum_nested_name_spec);
- SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL,
+ SS.Extend(SemaRef.Context, /*FIXME:*/ SourceLocation(), TL,
Q.getLocalEndLoc());
break;
}
@@ -4028,7 +4133,7 @@
TypedefTypeLoc TTL = TL.getAs<TypedefTypeLoc>();
if (!TTL || !TTL.getTypedefNameDecl()->isInvalidDecl()) {
SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag)
- << TL.getType() << SS.getRange();
+ << TL.getType() << SS.getRange();
}
return NestedNameSpecifierLoc();
}
@@ -4217,10 +4322,10 @@
Arg, QualType(), getDerived().getBaseLocation());
}
-template<typename Derived>
+template <typename Derived>
bool TreeTransform<Derived>::TransformTemplateArgument(
- const TemplateArgumentLoc &Input,
- TemplateArgumentLoc &Output, bool Uneval) {
+ const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output,
+ bool Uneval) {
const TemplateArgument &Arg = Input.getArgument();
switch (Arg.getKind()) {
case TemplateArgument::Null:
@@ -4269,7 +4374,8 @@
DI = InventTypeSourceInfo(Input.getArgument().getAsType());
DI = getDerived().TransformType(DI);
- if (!DI) return true;
+ if (!DI)
+ return true;
Output = TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
return false;
@@ -4285,9 +4391,8 @@
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
- TemplateName Template
- = getDerived().TransformTemplateName(SS, Arg.getAsTemplate(),
- Input.getTemplateNameLoc());
+ TemplateName Template = getDerived().TransformTemplateName(
+ SS, Arg.getAsTemplate(), Input.getTemplateNameLoc());
if (Template.isNull())
return true;
@@ -4309,11 +4414,13 @@
Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);
Expr *InputExpr = Input.getSourceExpression();
- if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
+ if (!InputExpr)
+ InputExpr = Input.getArgument().getAsExpr();
ExprResult E = getDerived().TransformExpr(InputExpr);
E = SemaRef.ActOnConstantExpression(E);
- if (E.isInvalid()) return true;
+ if (E.isInvalid())
+ return true;
Output = TemplateArgumentLoc(TemplateArgument(E.get()), E.get());
return false;
}
@@ -5723,8 +5830,8 @@
return getDerived().TransformFunctionProtoType(
TLB, TL, nullptr, Qualifiers(),
[&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
- return This->TransformExceptionSpec(TL.getBeginLoc(), ESI,
- ExceptionStorage, Changed);
+ return This->getDerived().TransformExceptionSpec(
+ TL.getBeginLoc(), ESI, ExceptionStorage, Changed);
});
}
@@ -6427,11 +6534,9 @@
ConceptDecl *NewCD = nullptr;
TemplateArgumentListInfo NewTemplateArgs;
NestedNameSpecifierLoc NewNestedNameSpec;
- if (TL.getTypePtr()->isConstrained()) {
- NewCD = cast_or_null<ConceptDecl>(
- getDerived().TransformDecl(
- TL.getConceptNameLoc(),
- TL.getTypePtr()->getTypeConstraintConcept()));
+ if (T->isConstrained()) {
+ NewCD = cast_or_null<ConceptDecl>(getDerived().TransformDecl(
+ TL.getConceptNameLoc(), T->getTypeConstraintConcept()));
NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
@@ -6453,7 +6558,8 @@
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced ||
- T->isDependentType()) {
+ T->isDependentType() || T->isConstrained()) {
+ // FIXME: Maybe don't rebuild if all template arguments are the same.
llvm::SmallVector<TemplateArgument, 4> NewArgList;
NewArgList.reserve(NewArgList.size());
for (const auto &ArgLoc : NewTemplateArgs.arguments())
@@ -7237,7 +7343,8 @@
for (const auto *I : S->getAttrs()) {
const Attr *R = getDerived().TransformAttr(I);
AttrsChanged |= (I != R);
- Attrs.push_back(R);
+ if (R)
+ Attrs.push_back(R);
}
StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK);
@@ -7247,6 +7354,11 @@
if (SubStmt.get() == S->getSubStmt() && !AttrsChanged)
return S;
+ // If transforming the attributes failed for all of the attributes in the
+ // statement, don't make an AttributedStmt without attributes.
+ if (Attrs.empty())
+ return SubStmt;
+
return getDerived().RebuildAttributedStmt(S->getAttrLoc(), Attrs,
SubStmt.get());
}
@@ -8314,6 +8426,16 @@
//===----------------------------------------------------------------------===//
// OpenMP directive transformation
//===----------------------------------------------------------------------===//
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPCanonicalLoop(OMPCanonicalLoop *L) {
+ // OMPCanonicalLoops are eliminated during transformation, since they will be
+ // recomputed by semantic analysis of the associated OMPLoopBasedDirective
+ // after transformation.
+ return getDerived().TransformStmt(L->getLoopStmt());
+}
+
template <typename Derived>
StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
OMPExecutableDirective *D) {
@@ -8348,8 +8470,11 @@
D->getDirectiveKind() == OMPD_master)
CS = D->getAssociatedStmt();
else
- CS = D->getInnermostCapturedStmt()->getCapturedStmt();
+ CS = D->getRawStmt();
Body = getDerived().TransformStmt(CS);
+ if (Body.isUsable() && isOpenMPLoopDirective(D->getDirectiveKind()) &&
+ getSema().getLangOpts().OpenMPIRBuilder)
+ Body = getDerived().RebuildOMPCanonicalLoop(Body.get());
}
AssociatedStmt =
getDerived().getSema().ActOnOpenMPRegionEnd(Body, TClauses);
@@ -8403,6 +8528,28 @@
template <typename Derived>
StmtResult
+TreeTransform<Derived>::TransformOMPTileDirective(OMPTileDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(D->getDirectiveKind(), DirName,
+ nullptr, D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPUnrollDirective(OMPUnrollDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(D->getDirectiveKind(), DirName,
+ nullptr, D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr,
@@ -8980,6 +9127,38 @@
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPInteropDirective(OMPInteropDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_interop, DirName, nullptr,
+ D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPDispatchDirective(OMPDispatchDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_dispatch, DirName, nullptr,
+ D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPMaskedDirective(OMPMaskedDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_masked, DirName, nullptr,
+ D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
@@ -9044,6 +9223,53 @@
}
template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPSizesClause(OMPSizesClause *C) {
+ SmallVector<Expr *, 4> TransformedSizes;
+ TransformedSizes.reserve(C->getNumSizes());
+ bool Changed = false;
+ for (Expr *E : C->getSizesRefs()) {
+ if (!E) {
+ TransformedSizes.push_back(nullptr);
+ continue;
+ }
+
+ ExprResult T = getDerived().TransformExpr(E);
+ if (T.isInvalid())
+ return nullptr;
+ if (E != T.get())
+ Changed = true;
+ TransformedSizes.push_back(T.get());
+ }
+
+ if (!Changed && !getDerived().AlwaysRebuild())
+ return C;
+ return RebuildOMPSizesClause(TransformedSizes, C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPFullClause(OMPFullClause *C) {
+ if (!getDerived().AlwaysRebuild())
+ return C;
+ return RebuildOMPFullClause(C->getBeginLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPPartialClause(OMPPartialClause *C) {
+ ExprResult T = getDerived().TransformExpr(C->getFactor());
+ if (T.isInvalid())
+ return nullptr;
+ Expr *Factor = T.get();
+ bool Changed = Factor != C->getFactor();
+
+ if (!Changed && !getDerived().AlwaysRebuild())
+ return C;
+ return RebuildOMPPartialClause(Factor, C->getBeginLoc(), C->getLParenLoc(),
+ C->getEndLoc());
+}
+
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPCollapseClause(OMPCollapseClause *C) {
ExprResult E = getDerived().TransformExpr(C->getNumForLoops());
@@ -9211,10 +9437,76 @@
}
template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPInitClause(OMPInitClause *C) {
+ ExprResult IVR = getDerived().TransformExpr(C->getInteropVar());
+ if (IVR.isInvalid())
+ return nullptr;
+
+ llvm::SmallVector<Expr *, 8> PrefExprs;
+ PrefExprs.reserve(C->varlist_size() - 1);
+ for (Expr *E : llvm::drop_begin(C->varlists())) {
+ ExprResult ER = getDerived().TransformExpr(cast<Expr>(E));
+ if (ER.isInvalid())
+ return nullptr;
+ PrefExprs.push_back(ER.get());
+ }
+ return getDerived().RebuildOMPInitClause(
+ IVR.get(), PrefExprs, C->getIsTarget(), C->getIsTargetSync(),
+ C->getBeginLoc(), C->getLParenLoc(), C->getVarLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPUseClause(OMPUseClause *C) {
+ ExprResult ER = getDerived().TransformExpr(C->getInteropVar());
+ if (ER.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPUseClause(ER.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getVarLoc(),
+ C->getEndLoc());
+}
+
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDestroyClause(OMPDestroyClause *C) {
- // No need to rebuild this clause, no template-dependent parameters.
- return C;
+ ExprResult ER;
+ if (Expr *IV = C->getInteropVar()) {
+ ER = getDerived().TransformExpr(IV);
+ if (ER.isInvalid())
+ return nullptr;
+ }
+ return getDerived().RebuildOMPDestroyClause(ER.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getVarLoc(),
+ C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNovariantsClause(OMPNovariantsClause *C) {
+ ExprResult Cond = getDerived().TransformExpr(C->getCondition());
+ if (Cond.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPNovariantsClause(
+ Cond.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNocontextClause(OMPNocontextClause *C) {
+ ExprResult Cond = getDerived().TransformExpr(C->getCondition());
+ if (Cond.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPNocontextClause(
+ Cond.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPFilterClause(OMPFilterClause *C) {
+ ExprResult ThreadID = getDerived().TransformExpr(C->getThreadID());
+ if (ThreadID.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPFilterClause(ThreadID.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
}
template <typename Derived>
@@ -9936,6 +10228,24 @@
return TransformExpr(E->getSubExpr());
}
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformSYCLUniqueStableNameExpr(
+ SYCLUniqueStableNameExpr *E) {
+ if (!E->isTypeDependent())
+ return E;
+
+ TypeSourceInfo *NewT = getDerived().TransformType(E->getTypeSourceInfo());
+
+ if (!NewT)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() && E->getTypeSourceInfo() == NewT)
+ return E;
+
+ return getDerived().RebuildSYCLUniqueStableNameExpr(
+ E->getLocation(), E->getLParenLocation(), E->getRParenLocation(), NewT);
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
@@ -11325,15 +11635,20 @@
TInfo, E->getEndLoc());
}
- // We don't know whether the subexpression is potentially evaluated until
- // after we perform semantic analysis. We speculatively assume it is
- // unevaluated; it will get fixed later if the subexpression is in fact
- // potentially evaluated.
- EnterExpressionEvaluationContext Unevaluated(
- SemaRef, Sema::ExpressionEvaluationContext::Unevaluated,
- Sema::ReuseLambdaContextDecl);
+ // Typeid's operand is an unevaluated context, unless it's a polymorphic
+ // type. We must not unilaterally enter unevaluated context here, as then
+ // semantic processing can re-transform an already transformed operand.
+ Expr *Op = E->getExprOperand();
+ auto EvalCtx = Sema::ExpressionEvaluationContext::Unevaluated;
+ if (E->isGLValue())
+ if (auto *RecordT = Op->getType()->getAs<RecordType>())
+ if (cast<CXXRecordDecl>(RecordT->getDecl())->isPolymorphic())
+ EvalCtx = SemaRef.ExprEvalContexts.back().Context;
- ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, EvalCtx,
+ Sema::ReuseLambdaContextDecl);
+
+ ExprResult SubExpr = getDerived().TransformExpr(Op);
if (SubExpr.isInvalid())
return ExprError();
@@ -12184,15 +12499,13 @@
nullptr);
}
-template<typename Derived>
-ExprResult
-TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
- DependentScopeDeclRefExpr *E,
- bool IsAddressOfOperand,
- TypeSourceInfo **RecoveryTSI) {
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
+ DependentScopeDeclRefExpr *E, bool IsAddressOfOperand,
+ TypeSourceInfo **RecoveryTSI) {
assert(E->getQualifierLoc());
- NestedNameSpecifierLoc QualifierLoc
- = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
+ NestedNameSpecifierLoc QualifierLoc =
+ getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
if (!QualifierLoc)
return ExprError();
SourceLocation TemplateKWLoc = E->getTemplateKeywordLoc();
@@ -12201,14 +12514,13 @@
// destination type name (if present) resolves the same way after
// instantiation as it did in the local scope.
- DeclarationNameInfo NameInfo
- = getDerived().TransformDeclarationNameInfo(E->getNameInfo());
+ DeclarationNameInfo NameInfo =
+ getDerived().TransformDeclarationNameInfo(E->getNameInfo());
if (!NameInfo.getName())
return ExprError();
if (!E->hasExplicitTemplateArgs()) {
- if (!getDerived().AlwaysRebuild() &&
- QualifierLoc == E->getQualifierLoc() &&
+ if (!getDerived().AlwaysRebuild() && QualifierLoc == E->getQualifierLoc() &&
// Note: it is sufficient to compare the Name component of NameInfo:
// if name has not changed, DNLoc has not changed either.
NameInfo.getName() == E->getDeclName())
@@ -12220,9 +12532,8 @@
}
TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
- if (getDerived().TransformTemplateArguments(E->getTemplateArgs(),
- E->getNumTemplateArgs(),
- TransArgs))
+ if (getDerived().TransformTemplateArguments(
+ E->getTemplateArgs(), E->getNumTemplateArgs(), TransArgs))
return ExprError();
return getDerived().RebuildDependentScopeDeclRefExpr(
@@ -12241,7 +12552,8 @@
(E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1)))) &&
(!getDerived().DropCallArgument(E->getArg(0))) &&
!E->isListInitialization()))
- return getDerived().TransformExpr(E->getArg(0));
+ return getDerived().TransformInitializer(E->getArg(0),
+ /*DirectInit*/ false);
TemporaryBase Rebase(*this, /*FIXME*/ E->getBeginLoc(), DeclarationName());
@@ -12869,18 +13181,18 @@
&TransArgs);
}
-template<typename Derived>
-ExprResult
-TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) {
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformUnresolvedMemberExpr(
+ UnresolvedMemberExpr *Old) {
// Transform the base of the expression.
- ExprResult Base((Expr*) nullptr);
+ ExprResult Base((Expr *)nullptr);
QualType BaseType;
if (!Old->isImplicitAccess()) {
Base = getDerived().TransformExpr(Old->getBase());
if (Base.isInvalid())
return ExprError();
- Base = getSema().PerformMemberExprBaseConversion(Base.get(),
- Old->isArrow());
+ Base =
+ getSema().PerformMemberExprBaseConversion(Base.get(), Old->isArrow());
if (Base.isInvalid())
return ExprError();
BaseType = Base.get()->getType();
@@ -12890,27 +13202,24 @@
NestedNameSpecifierLoc QualifierLoc;
if (Old->getQualifierLoc()) {
- QualifierLoc
- = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc());
+ QualifierLoc =
+ getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc());
if (!QualifierLoc)
return ExprError();
}
SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc();
- LookupResult R(SemaRef, Old->getMemberNameInfo(),
- Sema::LookupOrdinaryName);
+ LookupResult R(SemaRef, Old->getMemberNameInfo(), Sema::LookupOrdinaryName);
// Transform the declaration set.
- if (TransformOverloadExprDecls(Old, /*RequiresADL*/false, R))
+ if (TransformOverloadExprDecls(Old, /*RequiresADL*/ false, R))
return ExprError();
// Determine the naming class.
if (Old->getNamingClass()) {
- CXXRecordDecl *NamingClass
- = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
- Old->getMemberLoc(),
- Old->getNamingClass()));
+ CXXRecordDecl *NamingClass = cast_or_null<CXXRecordDecl>(
+ getDerived().TransformDecl(Old->getMemberLoc(), Old->getNamingClass()));
if (!NamingClass)
return ExprError();
@@ -12921,9 +13230,8 @@
if (Old->hasExplicitTemplateArgs()) {
TransArgs.setLAngleLoc(Old->getLAngleLoc());
TransArgs.setRAngleLoc(Old->getRAngleLoc());
- if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
- Old->getNumTemplateArgs(),
- TransArgs))
+ if (getDerived().TransformTemplateArguments(
+ Old->getTemplateArgs(), Old->getNumTemplateArgs(), TransArgs))
return ExprError();
}
@@ -12933,16 +13241,10 @@
// nested-name-qualifier (and therefore could do the lookup).
NamedDecl *FirstQualifierInScope = nullptr;
- return getDerived().RebuildUnresolvedMemberExpr(Base.get(),
- BaseType,
- Old->getOperatorLoc(),
- Old->isArrow(),
- QualifierLoc,
- TemplateKWLoc,
- FirstQualifierInScope,
- R,
- (Old->hasExplicitTemplateArgs()
- ? &TransArgs : nullptr));
+ return getDerived().RebuildUnresolvedMemberExpr(
+ Base.get(), BaseType, Old->getOperatorLoc(), Old->isArrow(), QualifierLoc,
+ TemplateKWLoc, FirstQualifierInScope, R,
+ (Old->hasExplicitTemplateArgs() ? &TransArgs : nullptr));
}
template<typename Derived>
@@ -13015,7 +13317,7 @@
auto *VD = cast<ValueDecl>(Pack);
ExprResult DRE = getSema().BuildDeclRefExpr(
VD, VD->getType().getNonLValueExprType(getSema().Context),
- VD->getType()->isReferenceType() ? VK_LValue : VK_RValue,
+ VD->getType()->isReferenceType() ? VK_LValue : VK_PRValue,
E->getPackLoc());
if (DRE.isInvalid())
return ExprError();
@@ -13821,7 +14123,14 @@
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformAsTypeExpr(AsTypeExpr *E) {
- llvm_unreachable("Cannot transform asType expressions yet");
+ ExprResult SrcExpr = getDerived().TransformExpr(E->getSrcExpr());
+ if (SrcExpr.isInvalid())
+ return ExprError();
+
+ QualType Type = getDerived().TransformType(E->getType());
+
+ return SemaRef.BuildAsTypeExpr(SrcExpr.get(), Type, E->getBuiltinLoc(),
+ E->getRParenLoc());
}
template<typename Derived>
@@ -14114,7 +14423,11 @@
// A valid resolved using typename decl points to exactly one type decl.
assert(++Using->shadow_begin() == Using->shadow_end());
- Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
+
+ NamedDecl *Target = Using->shadow_begin()->getTargetDecl();
+ if (SemaRef.DiagnoseUseOfDecl(Target, Loc))
+ return QualType();
+ Ty = cast<TypeDecl>(Target);
} else {
assert(isa<UnresolvedUsingTypenameDecl>(D) &&
"UnresolvedUsingTypenameDecl transformed to non-using decl");
@@ -14335,11 +14648,9 @@
SourceLocation RBrace;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) {
- DeclarationNameLoc NameLoc = DRE->getNameInfo().getInfo();
- LBrace = SourceLocation::getFromRawEncoding(
- NameLoc.CXXOperatorName.BeginOpNameLoc);
- RBrace = SourceLocation::getFromRawEncoding(
- NameLoc.CXXOperatorName.EndOpNameLoc);
+ DeclarationNameLoc NameLoc = DRE->getNameInfo().getInfo();
+ LBrace = NameLoc.getCXXOperatorNameBeginLoc();
+ RBrace = NameLoc.getCXXOperatorNameEndLoc();
} else {
LBrace = Callee->getBeginLoc();
RBrace = OpLoc;
diff --git a/src/llvm-project/clang/lib/Serialization/ASTCommon.cpp b/src/llvm-project/clang/lib/Serialization/ASTCommon.cpp
index fec6dd5..5fe1f96 100644
--- a/src/llvm-project/clang/lib/Serialization/ASTCommon.cpp
+++ b/src/llvm-project/clang/lib/Serialization/ASTCommon.cpp
@@ -242,6 +242,11 @@
ID = PREDEF_TYPE_##Id##_ID; \
break;
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) \
+ case BuiltinType::Id: \
+ ID = PREDEF_TYPE_##Id##_ID; \
+ break;
+#include "clang/Basic/RISCVVTypes.def"
case BuiltinType::BuiltinFn:
ID = PREDEF_TYPE_BUILTIN_FN;
break;
@@ -389,6 +394,7 @@
case Decl::NonTypeTemplateParm:
case Decl::TemplateTemplateParm:
case Decl::Using:
+ case Decl::UsingEnum:
case Decl::UsingPack:
case Decl::ObjCMethod:
case Decl::ObjCCategory:
@@ -422,6 +428,7 @@
case Decl::Concept:
case Decl::LifetimeExtendedTemporary:
case Decl::RequiresExprBody:
+ case Decl::UnresolvedUsingIfExists:
return false;
// These indirectly derive from Redeclarable<T> but are not actually
diff --git a/src/llvm-project/clang/lib/Serialization/ASTReader.cpp b/src/llvm-project/clang/lib/Serialization/ASTReader.cpp
index 1f68f6b..83bade9 100644
--- a/src/llvm-project/clang/lib/Serialization/ASTReader.cpp
+++ b/src/llvm-project/clang/lib/Serialization/ASTReader.cpp
@@ -114,6 +114,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
@@ -782,9 +783,11 @@
StringRef SpecificModuleCachePath,
StringRef ExistingModuleCachePath,
DiagnosticsEngine *Diags,
- const LangOptions &LangOpts) {
+ const LangOptions &LangOpts,
+ const PreprocessorOptions &PPOpts) {
if (LangOpts.Modules) {
- if (SpecificModuleCachePath != ExistingModuleCachePath) {
+ if (SpecificModuleCachePath != ExistingModuleCachePath &&
+ !PPOpts.AllowPCHWithDifferentModulesCachePath) {
if (Diags)
Diags->Report(diag::err_pch_modulecache_mismatch)
<< SpecificModuleCachePath << ExistingModuleCachePath;
@@ -801,7 +804,7 @@
return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
PP.getHeaderSearchInfo().getModuleCachePath(),
Complain ? &Reader.Diags : nullptr,
- PP.getLangOpts());
+ PP.getLangOpts(), PP.getPreprocessorOpts());
}
void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) {
@@ -812,6 +815,31 @@
// AST reader implementation
//===----------------------------------------------------------------------===//
+static uint64_t readULEB(const unsigned char *&P) {
+ unsigned Length = 0;
+ const char *Error = nullptr;
+
+ uint64_t Val = llvm::decodeULEB128(P, &Length, nullptr, &Error);
+ if (Error)
+ llvm::report_fatal_error(Error);
+ P += Length;
+ return Val;
+}
+
+/// Read ULEB-encoded key length and data length.
+static std::pair<unsigned, unsigned>
+readULEBKeyDataLength(const unsigned char *&P) {
+ unsigned KeyLen = readULEB(P);
+ if ((unsigned)KeyLen != KeyLen)
+ llvm::report_fatal_error("key too large");
+
+ unsigned DataLen = readULEB(P);
+ if ((unsigned)DataLen != DataLen)
+ llvm::report_fatal_error("data too large");
+
+ return std::make_pair(KeyLen, DataLen);
+}
+
void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener,
bool TakeOwnership) {
DeserializationListener = Listener;
@@ -824,11 +852,7 @@
std::pair<unsigned, unsigned>
ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
- using namespace llvm::support;
-
- unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
- unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
- return std::make_pair(KeyLen, DataLen);
+ return readULEBKeyDataLength(d);
}
ASTSelectorLookupTrait::internal_key_type
@@ -894,11 +918,7 @@
std::pair<unsigned, unsigned>
ASTIdentifierLookupTraitBase::ReadKeyDataLength(const unsigned char*& d) {
- using namespace llvm::support;
-
- unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
- unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
- return std::make_pair(KeyLen, DataLen);
+ return readULEBKeyDataLength(d);
}
ASTIdentifierLookupTraitBase::internal_key_type
@@ -1086,11 +1106,7 @@
std::pair<unsigned, unsigned>
ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char *&d) {
- using namespace llvm::support;
-
- unsigned KeyLen = endian::readNext<uint16_t, little, unaligned>(d);
- unsigned DataLen = endian::readNext<uint16_t, little, unaligned>(d);
- return std::make_pair(KeyLen, DataLen);
+ return readULEBKeyDataLength(d);
}
ASTDeclContextNameLookupTrait::internal_key_type
@@ -1466,7 +1482,7 @@
}
BitstreamCursor &SLocEntryCursor = F->SLocEntryCursor;
- unsigned BaseOffset = F->SLocEntryBaseOffset;
+ SourceLocation::UIntTy BaseOffset = F->SLocEntryBaseOffset;
++NumSLocEntriesRead;
Expected<llvm::BitstreamEntry> MaybeEntry = SLocEntryCursor.advance();
@@ -1847,11 +1863,7 @@
std::pair<unsigned, unsigned>
HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
- using namespace llvm::support;
-
- unsigned KeyLen = (unsigned) endian::readNext<uint16_t, little, unaligned>(d);
- unsigned DataLen = (unsigned) *d++;
- return std::make_pair(KeyLen, DataLen);
+ return readULEBKeyDataLength(d);
}
HeaderFileInfoTrait::internal_key_type
@@ -1911,11 +1923,9 @@
std::string Filename = std::string(key.Filename);
if (key.Imported)
Reader.ResolveImportedPath(M, Filename);
- // FIXME: This is not always the right filename-as-written, but we're not
- // going to use this information to rebuild the module, so it doesn't make
- // a lot of difference.
- Module::Header H = {std::string(key.Filename),
- *FileMgr.getOptionalFileRef(Filename)};
+ // FIXME: NameAsWritten
+ Module::Header H = {std::string(key.Filename), "",
+ *FileMgr.getFile(Filename)};
ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true);
HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader);
}
@@ -2750,9 +2760,17 @@
}
bool hasErrors = Record[6];
- if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
- Diag(diag::err_pch_with_compiler_errors);
- return HadErrors;
+ if (hasErrors && !DisableValidation) {
+ // If requested by the caller and the module hasn't already been read
+ // or compiled, mark modules on error as out-of-date.
+ if ((ClientLoadCapabilities & ARR_TreatModuleWithErrorsAsOutOfDate) &&
+ canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
+ return OutOfDate;
+
+ if (!AllowASTWithCompilerErrors) {
+ Diag(diag::err_pch_with_compiler_errors);
+ return HadErrors;
+ }
}
if (hasErrors) {
Diags.ErrorOccurred = true;
@@ -2832,9 +2850,14 @@
StoredSignature, Capabilities);
// If we diagnosed a problem, produce a backtrace.
- if (isDiagnosedResult(Result, Capabilities))
+ bool recompilingFinalized =
+ Result == OutOfDate && (Capabilities & ARR_OutOfDate) &&
+ getModuleManager().getModuleCache().isPCMFinal(F.FileName);
+ if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized)
Diag(diag::note_module_file_imported_by)
<< F.FileName << !F.ModuleName.empty() << F.ModuleName;
+ if (recompilingFinalized)
+ Diag(diag::note_module_file_conflict);
switch (Result) {
case Failure: return Failure;
@@ -2900,7 +2923,7 @@
F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) {
auto BuildDir = PP.getFileManager().getDirectory(Blob);
if (!BuildDir || *BuildDir != M->Directory) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Diag(diag::err_imported_module_relocated)
<< F.ModuleName << Blob << M->Directory->getName();
return OutOfDate;
@@ -3181,12 +3204,13 @@
}
case IDENTIFIER_TABLE:
- F.IdentifierTableData = Blob.data();
+ F.IdentifierTableData =
+ reinterpret_cast<const unsigned char *>(Blob.data());
if (Record[0]) {
F.IdentifierLookupTable = ASTIdentifierLookupTable::Create(
- (const unsigned char *)F.IdentifierTableData + Record[0],
- (const unsigned char *)F.IdentifierTableData + sizeof(uint32_t),
- (const unsigned char *)F.IdentifierTableData,
+ F.IdentifierTableData + Record[0],
+ F.IdentifierTableData + sizeof(uint32_t),
+ F.IdentifierTableData,
ASTIdentifierLookupTrait(*this, F));
PP.getIdentifierTable().setExternalIdentifierLookup(this);
@@ -3385,7 +3409,7 @@
case SOURCE_LOCATION_OFFSETS: {
F.SLocEntryOffsets = (const uint32_t *)Blob.data();
F.LocalNumSLocEntries = Record[0];
- unsigned SLocSpaceSize = Record[1];
+ SourceLocation::UIntTy SLocSpaceSize = Record[1];
F.SLocEntryOffsetsBase = Record[2] + F.SourceManagerBlockStartOffset;
std::tie(F.SLocEntryBaseID, F.SLocEntryBaseOffset) =
SourceMgr.AllocateLoadedSLocEntries(F.LocalNumSLocEntries,
@@ -3403,7 +3427,7 @@
F.FirstLoc = SourceLocation::getFromRawEncoding(F.SLocEntryBaseOffset);
// SLocEntryBaseOffset is lower than MaxLoadedOffset and decreasing.
- assert((F.SLocEntryBaseOffset & (1U << 31U)) == 0);
+ assert((F.SLocEntryBaseOffset & SourceLocation::MacroIDBit) == 0);
GlobalSLocOffsetMap.insert(
std::make_pair(SourceManager::MaxLoadedOffset - F.SLocEntryBaseOffset
- SLocSpaceSize,&F));
@@ -3412,8 +3436,8 @@
// Invalid stays invalid.
F.SLocRemap.insertOrReplace(std::make_pair(0U, 0));
// This module. Base was 2 when being compiled.
- F.SLocRemap.insertOrReplace(std::make_pair(2U,
- static_cast<int>(F.SLocEntryBaseOffset - 2)));
+ F.SLocRemap.insertOrReplace(std::make_pair(
+ 2U, static_cast<SourceLocation::IntTy>(F.SLocEntryBaseOffset - 2)));
TotalNumSLocEntries += F.LocalNumSLocEntries;
break;
@@ -3611,36 +3635,13 @@
auto &OptInfo = OpenCLExtensions.OptMap[Name];
OptInfo.Supported = Record[I++] != 0;
OptInfo.Enabled = Record[I++] != 0;
+ OptInfo.WithPragma = Record[I++] != 0;
OptInfo.Avail = Record[I++];
OptInfo.Core = Record[I++];
OptInfo.Opt = Record[I++];
}
break;
- case OPENCL_EXTENSION_TYPES:
- for (unsigned I = 0, E = Record.size(); I != E;) {
- auto TypeID = static_cast<::TypeID>(Record[I++]);
- auto *Type = GetType(TypeID).getTypePtr();
- auto NumExt = static_cast<unsigned>(Record[I++]);
- for (unsigned II = 0; II != NumExt; ++II) {
- auto Ext = ReadString(Record, I);
- OpenCLTypeExtMap[Type].insert(Ext);
- }
- }
- break;
-
- case OPENCL_EXTENSION_DECLS:
- for (unsigned I = 0, E = Record.size(); I != E;) {
- auto DeclID = static_cast<::DeclID>(Record[I++]);
- auto *Decl = GetDecl(DeclID);
- auto NumExt = static_cast<unsigned>(Record[I++]);
- for (unsigned II = 0; II != NumExt; ++II) {
- auto Ext = ReadString(Record, I);
- OpenCLDeclExtMap[Decl].insert(Ext);
- }
- }
- break;
-
case TENTATIVE_DEFINITIONS:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I]));
@@ -3816,7 +3817,7 @@
case DECLS_TO_CHECK_FOR_DEFERRED_DIAGS:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
- DeclsToCheckForDeferredDiags.push_back(getGlobalDeclID(F, Record[I]));
+ DeclsToCheckForDeferredDiags.insert(getGlobalDeclID(F, Record[I]));
break;
}
}
@@ -3837,8 +3838,11 @@
}
// Continuous range maps we may be updating in our module.
+ using SLocRemapBuilder =
+ ContinuousRangeMap<SourceLocation::UIntTy, SourceLocation::IntTy,
+ 2>::Builder;
using RemapBuilder = ContinuousRangeMap<uint32_t, int, 2>::Builder;
- RemapBuilder SLocRemap(F.SLocRemap);
+ SLocRemapBuilder SLocRemap(F.SLocRemap);
RemapBuilder IdentifierRemap(F.IdentifierRemap);
RemapBuilder MacroRemap(F.MacroRemap);
RemapBuilder PreprocessedEntityRemap(F.PreprocessedEntityRemap);
@@ -3869,7 +3873,7 @@
return;
}
- uint32_t SLocOffset =
+ SourceLocation::UIntTy SLocOffset =
endian::readNext<uint32_t, little, unaligned>(Data);
uint32_t IdentifierIDOffset =
endian::readNext<uint32_t, little, unaligned>(Data);
@@ -3886,15 +3890,21 @@
uint32_t TypeIndexOffset =
endian::readNext<uint32_t, little, unaligned>(Data);
- uint32_t None = std::numeric_limits<uint32_t>::max();
-
auto mapOffset = [&](uint32_t Offset, uint32_t BaseOffset,
RemapBuilder &Remap) {
+ constexpr uint32_t None = std::numeric_limits<uint32_t>::max();
if (Offset != None)
Remap.insert(std::make_pair(Offset,
static_cast<int>(BaseOffset - Offset)));
};
- mapOffset(SLocOffset, OM->SLocEntryBaseOffset, SLocRemap);
+
+ constexpr SourceLocation::UIntTy SLocNone =
+ std::numeric_limits<SourceLocation::UIntTy>::max();
+ if (SLocOffset != SLocNone)
+ SLocRemap.insert(std::make_pair(
+ SLocOffset, static_cast<SourceLocation::IntTy>(
+ OM->SLocEntryBaseOffset - SLocOffset)));
+
mapOffset(IdentifierIDOffset, OM->BaseIdentifierID, IdentifierRemap);
mapOffset(MacroIDOffset, OM->BaseMacroID, MacroRemap);
mapOffset(PreprocessedEntityIDOffset, OM->BasePreprocessedEntityID,
@@ -3932,7 +3942,7 @@
if (!bool(PP.getPreprocessorOpts().DisablePCHOrModuleValidation &
DisableValidationForModuleKind::Module) &&
!ModMap) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) {
+ if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities)) {
if (auto ASTFE = M ? M->getASTFile() : None) {
// This module was defined by an imported (explicit) module.
Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName
@@ -3963,7 +3973,7 @@
assert((ImportedBy || F.Kind == MK_ImplicitModule) &&
"top-level import should be verified");
bool NotImported = F.Kind == MK_ImplicitModule && !ImportedBy;
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Diag(diag::err_imported_module_modmap_changed)
<< F.ModuleName << (NotImported ? F.FileName : ImportedBy->FileName)
<< ModMap->getName() << F.ModuleMapPath << NotImported;
@@ -3974,13 +3984,13 @@
for (unsigned I = 0, N = Record[Idx++]; I < N; ++I) {
// FIXME: we should use input files rather than storing names.
std::string Filename = ReadPath(F, Record, Idx);
- auto F = FileMgr.getFile(Filename, false, false);
- if (!F) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ auto SF = FileMgr.getFile(Filename, false, false);
+ if (!SF) {
+ if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Error("could not find file '" + Filename +"' referenced by AST file");
return OutOfDate;
}
- AdditionalStoredMaps.insert(*F);
+ AdditionalStoredMaps.insert(*SF);
}
// Check any additional module map files (e.g. module.private.modulemap)
@@ -3990,7 +4000,7 @@
// Remove files that match
// Note: SmallPtrSet::erase is really remove
if (!AdditionalStoredMaps.erase(ModMap)) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Diag(diag::err_module_different_modmap)
<< F.ModuleName << /*new*/0 << ModMap->getName();
return OutOfDate;
@@ -4001,7 +4011,7 @@
// Check any additional module map files that are in the pcm, but not
// found in header search. Cases that match are already removed.
for (const FileEntry *ModMap : AdditionalStoredMaps) {
- if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ if (!canRecoverFromOutOfDate(F.FileName, ClientLoadCapabilities))
Diag(diag::err_module_different_modmap)
<< F.ModuleName << /*not new*/1 << ModMap->getName();
return OutOfDate;
@@ -4154,7 +4164,8 @@
// 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_Text);
+ llvm::raw_fd_ostream OS(TimestampFilename, EC,
+ llvm::sys::fs::OF_TextWithCRLF);
if (EC)
return;
OS << "Timestamp file\n";
@@ -4313,8 +4324,7 @@
// Preload all the pending interesting identifiers by marking them out of
// date.
for (auto Offset : F.PreloadIdentifierOffsets) {
- const unsigned char *Data = reinterpret_cast<const unsigned char *>(
- F.IdentifierTableData + Offset);
+ const unsigned char *Data = F.IdentifierTableData + Offset;
ASTIdentifierLookupTrait Trait(*this, F);
auto KeyDataLen = Trait.ReadKeyDataLength(Data);
@@ -5148,8 +5158,8 @@
StringRef SpecificModuleCachePath,
bool Complain) override {
return checkHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
- ExistingModuleCachePath,
- nullptr, ExistingLangOpts);
+ ExistingModuleCachePath, nullptr,
+ ExistingLangOpts, ExistingPPOpts);
}
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
@@ -5597,9 +5607,10 @@
case SUBMODULE_UMBRELLA_HEADER: {
std::string Filename = std::string(Blob);
ResolveImportedPath(F, Filename);
- if (auto Umbrella = PP.getFileManager().getOptionalFileRef(Filename)) {
+ if (auto Umbrella = PP.getFileManager().getFile(Filename)) {
if (!CurrentModule->getUmbrellaHeader())
- ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob);
+ // FIXME: NameAsWritten
+ ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob, "");
else if (CurrentModule->getUmbrellaHeader().Entry != *Umbrella) {
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Error("mismatched umbrella headers in submodule");
@@ -5630,10 +5641,10 @@
case SUBMODULE_UMBRELLA_DIR: {
std::string Dirname = std::string(Blob);
ResolveImportedPath(F, Dirname);
- if (auto Umbrella =
- PP.getFileManager().getOptionalDirectoryRef(Dirname)) {
+ if (auto Umbrella = PP.getFileManager().getDirectory(Dirname)) {
if (!CurrentModule->getUmbrellaDir())
- ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob);
+ // FIXME: NameAsWritten
+ ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob, "");
else if (CurrentModule->getUmbrellaDir().Entry != *Umbrella) {
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Error("mismatched umbrella directories in submodule");
@@ -5927,6 +5938,12 @@
PreprocessingRecord::iterator());
}
+bool ASTReader::canRecoverFromOutOfDate(StringRef ModuleFileName,
+ unsigned int ClientLoadCapabilities) {
+ return ClientLoadCapabilities & ARR_OutOfDate &&
+ !getModuleManager().getModuleCache().isPCMFinal(ModuleFileName);
+}
+
llvm::iterator_range<ASTReader::ModuleDeclIterator>
ASTReader::getModuleFileLevelDecls(ModuleFile &Mod) {
return llvm::make_range(
@@ -7062,6 +7079,11 @@
T = Context.Id##Ty; \
break;
#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) \
+ case PREDEF_TYPE_##Id##_ID: \
+ T = Context.SingletonId; \
+ break;
+#include "clang/Basic/RISCVVTypes.def"
}
assert(!T.isNull() && "Unknown predefined type");
@@ -7174,6 +7196,11 @@
return;
}
+ if (!D->getDeclContext()) {
+ assert(isa<TranslationUnitDecl>(D) && "Not a TU?");
+ return;
+ }
+
const DeclContext *DC = D->getDeclContext()->getRedeclContext();
// If this is a named declaration, complete it by looking it up
@@ -7628,9 +7655,10 @@
// Load the list of declarations.
SmallVector<NamedDecl *, 64> Decls;
+ llvm::SmallPtrSet<NamedDecl *, 8> Found;
for (DeclID ID : It->second.Table.find(Name)) {
NamedDecl *ND = cast<NamedDecl>(GetDecl(ID));
- if (ND->getDeclName() == Name)
+ if (ND->getDeclName() == Name && Found.insert(ND).second)
Decls.push_back(ND);
}
@@ -7869,8 +7897,6 @@
}
SemaObj->OpenCLFeatures = OpenCLExtensions;
- SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap;
- SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap;
UpdateSema();
}
@@ -8334,18 +8360,15 @@
}
void ASTReader::ReadDeclsToCheckForDeferredDiags(
- llvm::SmallVector<Decl *, 4> &Decls) {
- for (unsigned I = 0, N = DeclsToCheckForDeferredDiags.size(); I != N;
- ++I) {
- auto *D = dyn_cast_or_null<Decl>(
- GetDecl(DeclsToCheckForDeferredDiags[I]));
+ llvm::SmallSetVector<Decl *, 4> &Decls) {
+ for (auto I : DeclsToCheckForDeferredDiags) {
+ auto *D = dyn_cast_or_null<Decl>(GetDecl(I));
if (D)
- Decls.push_back(D);
+ Decls.insert(D);
}
DeclsToCheckForDeferredDiags.clear();
}
-
void ASTReader::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation>> &Sels) {
if (ReferencedSelectorsData.empty())
@@ -8512,17 +8535,13 @@
assert(I != GlobalIdentifierMap.end() && "Corrupted global identifier map");
ModuleFile *M = I->second;
unsigned Index = ID - M->BaseIdentifierID;
- const char *Str = M->IdentifierTableData + M->IdentifierOffsets[Index];
+ const unsigned char *Data =
+ M->IdentifierTableData + M->IdentifierOffsets[Index];
- // All of the strings in the AST file are preceded by a 16-bit length.
- // Extract that 16-bit length to avoid having to execute strlen().
- // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
- // unsigned integers. This is important to avoid integer overflow when
- // we cast them to 'unsigned'.
- const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
- unsigned StrLen = (((unsigned) StrLenPtr[0])
- | (((unsigned) StrLenPtr[1]) << 8)) - 1;
- auto &II = PP.getIdentifierTable().get(StringRef(Str, StrLen));
+ ASTIdentifierLookupTrait Trait(*this, *M);
+ auto KeyDataLen = Trait.ReadKeyDataLength(Data);
+ auto Key = Trait.ReadKey(Data, KeyDataLen.first);
+ auto &II = PP.getIdentifierTable().get(Key);
IdentifiersLoaded[ID] = &II;
markIdentifierFromAST(*this, II);
if (DeserializationListener)
@@ -8737,25 +8756,18 @@
DeclarationNameLoc
ASTRecordReader::readDeclarationNameLoc(DeclarationName Name) {
- DeclarationNameLoc DNLoc;
switch (Name.getNameKind()) {
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
- DNLoc.NamedType.TInfo = readTypeSourceInfo();
- break;
+ return DeclarationNameLoc::makeNamedTypeLoc(readTypeSourceInfo());
case DeclarationName::CXXOperatorName:
- DNLoc.CXXOperatorName.BeginOpNameLoc
- = readSourceLocation().getRawEncoding();
- DNLoc.CXXOperatorName.EndOpNameLoc
- = readSourceLocation().getRawEncoding();
- break;
+ return DeclarationNameLoc::makeCXXOperatorNameLoc(readSourceRange());
case DeclarationName::CXXLiteralOperatorName:
- DNLoc.CXXLiteralOperatorName.OpNameLoc
- = readSourceLocation().getRawEncoding();
- break;
+ return DeclarationNameLoc::makeCXXLiteralOperatorNameLoc(
+ readSourceLocation());
case DeclarationName::Identifier:
case DeclarationName::ObjCZeroArgSelector:
@@ -8765,7 +8777,7 @@
case DeclarationName::CXXDeductionGuideName:
break;
}
- return DNLoc;
+ return DeclarationNameLoc();
}
DeclarationNameInfo ASTRecordReader::readDeclarationNameInfo() {
@@ -11730,6 +11742,17 @@
case llvm::omp::OMPC_simdlen:
C = new (Context) OMPSimdlenClause();
break;
+ case llvm::omp::OMPC_sizes: {
+ unsigned NumSizes = Record.readInt();
+ C = OMPSizesClause::CreateEmpty(Context, NumSizes);
+ break;
+ }
+ case llvm::omp::OMPC_full:
+ C = OMPFullClause::CreateEmpty(Context);
+ break;
+ case llvm::omp::OMPC_partial:
+ C = OMPPartialClause::CreateEmpty(Context);
+ break;
case llvm::omp::OMPC_allocator:
C = new (Context) OMPAllocatorClause();
break;
@@ -11952,9 +11975,21 @@
case llvm::omp::OMPC_order:
C = new (Context) OMPOrderClause();
break;
+ case llvm::omp::OMPC_init:
+ C = OMPInitClause::CreateEmpty(Context, Record.readInt());
+ break;
+ case llvm::omp::OMPC_use:
+ C = new (Context) OMPUseClause();
+ break;
case llvm::omp::OMPC_destroy:
C = new (Context) OMPDestroyClause();
break;
+ case llvm::omp::OMPC_novariants:
+ C = new (Context) OMPNovariantsClause();
+ break;
+ case llvm::omp::OMPC_nocontext:
+ C = new (Context) OMPNocontextClause();
+ break;
case llvm::omp::OMPC_detach:
C = new (Context) OMPDetachClause();
break;
@@ -11964,6 +11999,9 @@
case llvm::omp::OMPC_affinity:
C = OMPAffinityClause::CreateEmpty(Context, Record.readInt());
break;
+ case llvm::omp::OMPC_filter:
+ C = new (Context) OMPFilterClause();
+ break;
#define OMP_CLAUSE_NO_CLASS(Enum, Str) \
case llvm::omp::Enum: \
break;
@@ -12021,6 +12059,19 @@
C->setLParenLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPSizesClause(OMPSizesClause *C) {
+ for (Expr *&E : C->getSizesRefs())
+ E = Record.readSubExpr();
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPFullClause(OMPFullClause *C) {}
+
+void OMPClauseReader::VisitOMPPartialClause(OMPPartialClause *C) {
+ C->setFactor(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
void OMPClauseReader::VisitOMPAllocatorClause(OMPAllocatorClause *C) {
C->setAllocator(Record.readExpr());
C->setLParenLoc(Record.readSourceLocation());
@@ -12109,7 +12160,42 @@
void OMPClauseReader::VisitOMPNogroupClause(OMPNogroupClause *) {}
-void OMPClauseReader::VisitOMPDestroyClause(OMPDestroyClause *) {}
+void OMPClauseReader::VisitOMPInitClause(OMPInitClause *C) {
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned I = 0; I != NumVars; ++I)
+ Vars.push_back(Record.readSubExpr());
+ C->setVarRefs(Vars);
+ C->setIsTarget(Record.readBool());
+ C->setIsTargetSync(Record.readBool());
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setVarLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPUseClause(OMPUseClause *C) {
+ C->setInteropVar(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setVarLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPDestroyClause(OMPDestroyClause *C) {
+ C->setInteropVar(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+ C->setVarLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPNovariantsClause(OMPNovariantsClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setCondition(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
+void OMPClauseReader::VisitOMPNocontextClause(OMPNocontextClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setCondition(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
void OMPClauseReader::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {}
@@ -12894,6 +12980,12 @@
C->setKindKwLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPFilterClause(OMPFilterClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ C->setThreadID(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() {
OMPTraitInfo &TI = getContext().getNewOMPTraitInfo();
TI.Sets.resize(readUInt32());
diff --git a/src/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/src/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
index 18ab466..ff79f91 100644
--- a/src/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/src/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -328,6 +328,7 @@
void VisitTypedefDecl(TypedefDecl *TD);
void VisitTypeAliasDecl(TypeAliasDecl *TD);
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+ void VisitUnresolvedUsingIfExistsDecl(UnresolvedUsingIfExistsDecl *D);
RedeclarableResult VisitTagDecl(TagDecl *TD);
void VisitEnumDecl(EnumDecl *ED);
RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD);
@@ -389,6 +390,7 @@
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingEnumDecl(UsingEnumDecl *D);
void VisitUsingPackDecl(UsingPackDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
@@ -1651,6 +1653,17 @@
mergeMergeable(D);
}
+void ASTDeclReader::VisitUsingEnumDecl(UsingEnumDecl *D) {
+ VisitNamedDecl(D);
+ D->setUsingLoc(readSourceLocation());
+ D->setEnumLoc(readSourceLocation());
+ D->Enum = readDeclAs<EnumDecl>();
+ D->FirstUsingShadow.setPointer(readDeclAs<UsingShadowDecl>());
+ if (auto *Pattern = readDeclAs<UsingEnumDecl>())
+ Reader.getContext().setInstantiatedFromUsingEnumDecl(D, Pattern);
+ mergeMergeable(D);
+}
+
void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) {
VisitNamedDecl(D);
D->InstantiatedFrom = readDeclAs<NamedDecl>();
@@ -1707,6 +1720,11 @@
mergeMergeable(D);
}
+void ASTDeclReader::VisitUnresolvedUsingIfExistsDecl(
+ UnresolvedUsingIfExistsDecl *D) {
+ VisitNamedDecl(D);
+}
+
void ASTDeclReader::ReadCXXDefinitionData(
struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) {
#define FIELD(Name, Width, Merge) \
@@ -1954,6 +1972,7 @@
void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
D->setExplicitSpecifier(Record.readExplicitSpec());
+ D->Ctor = readDeclAs<CXXConstructorDecl>();
VisitFunctionDecl(D);
D->setIsCopyDeductionCandidate(Record.readInt());
}
@@ -3048,7 +3067,7 @@
return true;
}
-/// Determine whether the two declarations refer to the same entity.pr
+/// Determine whether the two declarations refer to the same entity.
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
@@ -3242,10 +3261,19 @@
return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
UX->isAccessDeclaration() == UY->isAccessDeclaration();
}
- if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X))
+ if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X)) {
return isSameQualifier(
UX->getQualifier(),
cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier());
+ }
+
+ // Using-pack declarations are only created by instantiation, and match if
+ // they're instantiated from matching UnresolvedUsing...Decls.
+ if (const auto *UX = dyn_cast<UsingPackDecl>(X)) {
+ return declaresSameEntity(
+ UX->getInstantiatedFromUsingDecl(),
+ cast<UsingPackDecl>(Y)->getInstantiatedFromUsingDecl());
+ }
// Namespace alias definitions with the same target match.
if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
@@ -3837,6 +3865,9 @@
case DECL_USING_SHADOW:
D = UsingShadowDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_USING_ENUM:
+ D = UsingEnumDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_CONSTRUCTOR_USING_SHADOW:
D = ConstructorUsingShadowDecl::CreateDeserialized(Context, ID);
break;
@@ -3849,6 +3880,9 @@
case DECL_UNRESOLVED_USING_TYPENAME:
D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_UNRESOLVED_USING_IF_EXISTS:
+ D = UnresolvedUsingIfExistsDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_CXX_RECORD:
D = CXXRecordDecl::CreateDeserialized(Context, ID);
break;
diff --git a/src/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp b/src/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp
index 0e1af53..b100f94 100644
--- a/src/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/src/llvm-project/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -185,11 +185,13 @@
void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
VisitStmt(S);
+ bool IsSideEntry = Record.readInt();
auto *LD = readDeclAs<LabelDecl>();
LD->setStmt(S);
S->setDecl(LD);
S->setSubStmt(Record.readSubStmt());
S->setIdentLoc(readSourceLocation());
+ S->setSideEntry(IsSideEntry);
}
void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {
@@ -579,6 +581,16 @@
E->setSubExpr(Record.readSubExpr());
}
+void ASTStmtReader::VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *E) {
+ VisitExpr(E);
+
+ E->setLocation(readSourceLocation());
+ E->setLParenLocation(readSourceLocation());
+ E->setRParenLocation(readSourceLocation());
+
+ E->setTypeSourceInfo(Record.readTypeSourceInfo());
+}
+
void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
bool HasFunctionName = Record.readInt();
@@ -1099,10 +1111,9 @@
void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) {
bool hasFP_Features;
- BinaryOperator::Opcode opc;
VisitExpr(E);
E->setHasStoredFPFeatures(hasFP_Features = Record.readInt());
- E->setOpcode(opc = (BinaryOperator::Opcode)Record.readInt());
+ E->setOpcode((BinaryOperator::Opcode)Record.readInt());
E->setLHS(Record.readSubExpr());
E->setRHS(Record.readSubExpr());
E->setOperatorLoc(readSourceLocation());
@@ -2273,19 +2284,29 @@
// OpenMP Directives.
//===----------------------------------------------------------------------===//
+void ASTStmtReader::VisitOMPCanonicalLoop(OMPCanonicalLoop *S) {
+ VisitStmt(S);
+ for (Stmt *&SubStmt : S->SubStmts)
+ SubStmt = Record.readSubStmt();
+}
+
void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
Record.readOMPChildren(E->Data);
E->setLocStart(readSourceLocation());
E->setLocEnd(readSourceLocation());
}
-void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
+void ASTStmtReader::VisitOMPLoopBasedDirective(OMPLoopBasedDirective *D) {
VisitStmt(D);
// Field CollapsedNum was read in ReadStmtFromStream.
Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
+ VisitOMPLoopBasedDirective(D);
+}
+
void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
@@ -2296,6 +2317,14 @@
VisitOMPLoopDirective(D);
}
+void ASTStmtReader::VisitOMPTileDirective(OMPTileDirective *D) {
+ VisitOMPLoopBasedDirective(D);
+}
+
+void ASTStmtReader::VisitOMPUnrollDirective(OMPUnrollDirective *D) {
+ VisitOMPLoopBasedDirective(D);
+}
+
void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) {
VisitOMPLoopDirective(D);
D->setHasCancel(Record.readBool());
@@ -2574,6 +2603,22 @@
VisitOMPLoopDirective(D);
}
+void ASTStmtReader::VisitOMPInteropDirective(OMPInteropDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPDispatchDirective(OMPDispatchDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ D->setTargetCallLoc(Record.readSourceLocation());
+}
+
+void ASTStmtReader::VisitOMPMaskedDirective(OMPMaskedDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//
@@ -2771,6 +2816,10 @@
/*StorageKind=*/Record[ASTStmtReader::NumExprFields]));
break;
+ case EXPR_SYCL_UNIQUE_STABLE_NAME:
+ S = SYCLUniqueStableNameExpr::CreateEmpty(Context);
+ break;
+
case EXPR_PREDEFINED:
S = PredefinedExpr::CreateEmpty(
Context,
@@ -3130,6 +3179,10 @@
nullptr);
break;
+ case STMT_OMP_CANONICAL_LOOP:
+ S = OMPCanonicalLoop::createEmpty(Context);
+ break;
+
case STMT_OMP_PARALLEL_DIRECTIVE:
S =
OMPParallelDirective::CreateEmpty(Context,
@@ -3145,6 +3198,20 @@
break;
}
+ case STMT_OMP_TILE_DIRECTIVE: {
+ unsigned NumLoops = Record[ASTStmtReader::NumStmtFields];
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTileDirective::CreateEmpty(Context, NumClauses, NumLoops);
+ break;
+ }
+
+ case STMT_OMP_UNROLL_DIRECTIVE: {
+ assert(Record[ASTStmtReader::NumStmtFields] == 1 && "Unroll directive accepts only a single loop");
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPUnrollDirective::CreateEmpty(Context, NumClauses);
+ break;
+ }
+
case STMT_OMP_FOR_DIRECTIVE: {
unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields];
unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
@@ -3478,6 +3545,21 @@
break;
}
+ case STMT_OMP_INTEROP_DIRECTIVE:
+ S = OMPInteropDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
+ case STMT_OMP_DISPATCH_DIRECTIVE:
+ S = OMPDispatchDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
+ case STMT_OMP_MASKED_DIRECTIVE:
+ S = OMPMaskedDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
case EXPR_CXX_OPERATOR_CALL:
S = CXXOperatorCallExpr::CreateEmpty(
Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
diff --git a/src/llvm-project/clang/lib/Serialization/ASTWriter.cpp b/src/llvm-project/clang/lib/Serialization/ASTWriter.cpp
index 40900af..66c207a 100644
--- a/src/llvm-project/clang/lib/Serialization/ASTWriter.cpp
+++ b/src/llvm-project/clang/lib/Serialization/ASTWriter.cpp
@@ -95,6 +95,7 @@
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
@@ -1615,6 +1616,15 @@
return Stream.EmitAbbrev(std::move(Abbrev));
}
+/// Emit key length and data length as ULEB-encoded data, and return them as a
+/// pair.
+static std::pair<unsigned, unsigned>
+emitULEBKeyDataLength(unsigned KeyLen, unsigned DataLen, raw_ostream &Out) {
+ llvm::encodeULEB128(KeyLen, Out);
+ llvm::encodeULEB128(DataLen, Out);
+ return std::make_pair(KeyLen, DataLen);
+}
+
namespace {
// Trait used for the on-disk hash table of header search information.
@@ -1657,19 +1667,14 @@
std::pair<unsigned, unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
- using namespace llvm::support;
-
- endian::Writer LE(Out, little);
unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;
- LE.write<uint16_t>(KeyLen);
unsigned DataLen = 1 + 2 + 4 + 4;
for (auto ModInfo : Data.KnownHeaders)
if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))
DataLen += 4;
if (Data.Unresolved.getPointer())
DataLen += 4;
- LE.write<uint8_t>(DataLen);
- return std::make_pair(KeyLen, DataLen);
+ return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}
void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) {
@@ -2036,7 +2041,7 @@
Record.push_back(Expansion.isExpansionTokenRange());
// Compute the token length for this macro expansion.
- unsigned NextOffset = SourceMgr.getNextLocalOffset();
+ SourceLocation::UIntTy NextOffset = SourceMgr.getNextLocalOffset();
if (I + 1 != N)
NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset();
Record.push_back(NextOffset - SLoc->getOffset() - 1);
@@ -2471,11 +2476,11 @@
}
}
-unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
+unsigned ASTWriter::getLocalOrImportedSubmoduleID(const Module *Mod) {
if (!Mod)
return 0;
- llvm::DenseMap<Module *, unsigned>::iterator Known = SubmoduleIDs.find(Mod);
+ auto Known = SubmoduleIDs.find(Mod);
if (Known != SubmoduleIDs.end())
return Known->second;
@@ -3008,11 +3013,7 @@
std::pair<unsigned, unsigned>
EmitKeyDataLength(raw_ostream& Out, Selector Sel,
data_type_ref Methods) {
- using namespace llvm::support;
-
- endian::Writer LE(Out, little);
unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
- LE.write<uint16_t>(KeyLen);
unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
@@ -3022,8 +3023,7 @@
Method = Method->getNext())
if (Method->getMethod())
DataLen += 4;
- LE.write<uint16_t>(DataLen);
- return std::make_pair(KeyLen, DataLen);
+ return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}
void EmitKey(raw_ostream& Out, Selector Sel, unsigned) {
@@ -3320,6 +3320,15 @@
std::pair<unsigned, unsigned>
EmitKeyDataLength(raw_ostream& Out, IdentifierInfo* II, IdentID ID) {
+ // Record the location of the identifier data. This is used when generating
+ // the mapping from persistent IDs to strings.
+ Writer.SetIdentifierOffset(II, Out.tell());
+
+ // Emit the offset of the key/data length information to the interesting
+ // identifiers table if necessary.
+ if (InterestingIdentifierOffsets && isInterestingIdentifier(II))
+ InterestingIdentifierOffsets->push_back(Out.tell());
+
unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
auto MacroOffset = Writer.getMacroDirectivesOffset(II);
@@ -3336,31 +3345,11 @@
DataLen += 4;
}
}
-
- using namespace llvm::support;
-
- endian::Writer LE(Out, little);
-
- assert((uint16_t)DataLen == DataLen && (uint16_t)KeyLen == KeyLen);
- LE.write<uint16_t>(DataLen);
- // We emit the key length after the data length so that every
- // string is preceded by a 16-bit length. This matches the PTH
- // format for storing identifiers.
- LE.write<uint16_t>(KeyLen);
- return std::make_pair(KeyLen, DataLen);
+ return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}
void EmitKey(raw_ostream& Out, const IdentifierInfo* II,
unsigned KeyLen) {
- // Record the location of the key data. This is used when generating
- // the mapping from persistent IDs to strings.
- Writer.SetIdentifierOffset(II, Out.tell());
-
- // Emit the offset of the key/data length information to the interesting
- // identifiers table if necessary.
- if (InterestingIdentifierOffsets && isInterestingIdentifier(II))
- InterestingIdentifierOffsets->push_back(Out.tell() - 4);
-
Out.write(II->getNameStart(), KeyLen);
}
@@ -3573,9 +3562,6 @@
std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,
DeclarationNameKey Name,
data_type_ref Lookup) {
- using namespace llvm::support;
-
- endian::Writer LE(Out, little);
unsigned KeyLen = 1;
switch (Name.getKind()) {
case DeclarationName::Identifier:
@@ -3595,15 +3581,11 @@
case DeclarationName::CXXUsingDirective:
break;
}
- LE.write<uint16_t>(KeyLen);
// 4 bytes for each DeclID.
unsigned DataLen = 4 * (Lookup.second - Lookup.first);
- assert(uint16_t(DataLen) == DataLen &&
- "too many decls for serialized lookup result");
- LE.write<uint16_t>(DataLen);
- return std::make_pair(KeyLen, DataLen);
+ return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}
void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) {
@@ -3976,78 +3958,13 @@
auto V = I.getValue();
Record.push_back(V.Supported ? 1 : 0);
Record.push_back(V.Enabled ? 1 : 0);
+ Record.push_back(V.WithPragma ? 1 : 0);
Record.push_back(V.Avail);
Record.push_back(V.Core);
Record.push_back(V.Opt);
}
Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
}
-
-void ASTWriter::WriteOpenCLExtensionTypes(Sema &SemaRef) {
- if (!SemaRef.Context.getLangOpts().OpenCL)
- return;
-
- // Sort the elements of the map OpenCLTypeExtMap by TypeIDs,
- // without copying them.
- const llvm::DenseMap<const Type *, std::set<std::string>> &OpenCLTypeExtMap =
- SemaRef.OpenCLTypeExtMap;
- using ElementTy = std::pair<TypeID, const std::set<std::string> *>;
- llvm::SmallVector<ElementTy, 8> StableOpenCLTypeExtMap;
- StableOpenCLTypeExtMap.reserve(OpenCLTypeExtMap.size());
-
- for (const auto &I : OpenCLTypeExtMap)
- StableOpenCLTypeExtMap.emplace_back(
- getTypeID(I.first->getCanonicalTypeInternal()), &I.second);
-
- auto CompareByTypeID = [](const ElementTy &E1, const ElementTy &E2) -> bool {
- return E1.first < E2.first;
- };
- llvm::sort(StableOpenCLTypeExtMap, CompareByTypeID);
-
- RecordData Record;
- for (const ElementTy &E : StableOpenCLTypeExtMap) {
- Record.push_back(E.first); // TypeID
- const std::set<std::string> *ExtSet = E.second;
- Record.push_back(static_cast<unsigned>(ExtSet->size()));
- for (const std::string &Ext : *ExtSet)
- AddString(Ext, Record);
- }
-
- Stream.EmitRecord(OPENCL_EXTENSION_TYPES, Record);
-}
-
-void ASTWriter::WriteOpenCLExtensionDecls(Sema &SemaRef) {
- if (!SemaRef.Context.getLangOpts().OpenCL)
- return;
-
- // Sort the elements of the map OpenCLDeclExtMap by DeclIDs,
- // without copying them.
- const llvm::DenseMap<const Decl *, std::set<std::string>> &OpenCLDeclExtMap =
- SemaRef.OpenCLDeclExtMap;
- using ElementTy = std::pair<DeclID, const std::set<std::string> *>;
- llvm::SmallVector<ElementTy, 8> StableOpenCLDeclExtMap;
- StableOpenCLDeclExtMap.reserve(OpenCLDeclExtMap.size());
-
- for (const auto &I : OpenCLDeclExtMap)
- StableOpenCLDeclExtMap.emplace_back(getDeclID(I.first), &I.second);
-
- auto CompareByDeclID = [](const ElementTy &E1, const ElementTy &E2) -> bool {
- return E1.first < E2.first;
- };
- llvm::sort(StableOpenCLDeclExtMap, CompareByDeclID);
-
- RecordData Record;
- for (const ElementTy &E : StableOpenCLDeclExtMap) {
- Record.push_back(E.first); // DeclID
- const std::set<std::string> *ExtSet = E.second;
- Record.push_back(static_cast<unsigned>(ExtSet->size()));
- for (const std::string &Ext : *ExtSet)
- AddString(Ext, Record);
- }
-
- Stream.EmitRecord(OPENCL_EXTENSION_DECLS, Record);
-}
-
void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {
if (SemaRef.ForceCUDAHostDeviceDepth > 0) {
RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth};
@@ -4723,7 +4640,7 @@
// another module after it or have more than one entity inside it.
uint32_t None = std::numeric_limits<uint32_t>::max();
- auto writeBaseIDOrNone = [&](uint32_t BaseID, bool ShouldWrite) {
+ auto writeBaseIDOrNone = [&](auto BaseID, bool ShouldWrite) {
assert(BaseID < std::numeric_limits<uint32_t>::max() && "base id too high");
if (ShouldWrite)
LE.write<uint32_t>(BaseID);
@@ -4750,9 +4667,9 @@
}
// Build a record containing all of the DeclsToCheckForDeferredDiags.
- RecordData DeclsToCheckForDeferredDiags;
+ SmallVector<serialization::DeclID, 64> DeclsToCheckForDeferredDiags;
for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)
- AddDeclRef(D, DeclsToCheckForDeferredDiags);
+ DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D));
RecordData DeclUpdatesOffsetsRecord;
@@ -4792,17 +4709,12 @@
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
WriteFPPragmaOptions(SemaRef.CurFPFeatureOverrides());
WriteOpenCLExtensions(SemaRef);
- WriteOpenCLExtensionTypes(SemaRef);
WriteCUDAPragmas(SemaRef);
// If we're emitting a module, write out the submodule information.
if (WritingModule)
WriteSubmodules(WritingModule);
- // We need to have information about submodules to correctly deserialize
- // decls from OpenCLExtensionDecls block
- WriteOpenCLExtensionDecls(SemaRef);
-
Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
// Write the record containing external, unnamed definitions.
@@ -5115,8 +5027,8 @@
}
void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) {
- uint32_t Raw = Loc.getRawEncoding();
- Record.push_back((Raw << 1) | (Raw >> 31));
+ SourceLocation::UIntTy Raw = Loc.getRawEncoding();
+ Record.push_back((Raw << 1) | (Raw >> (8 * sizeof(Raw) - 1)));
}
void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) {
@@ -5413,19 +5325,15 @@
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName:
- AddTypeSourceInfo(DNLoc.NamedType.TInfo);
+ AddTypeSourceInfo(DNLoc.getNamedTypeInfo());
break;
case DeclarationName::CXXOperatorName:
- AddSourceLocation(SourceLocation::getFromRawEncoding(
- DNLoc.CXXOperatorName.BeginOpNameLoc));
- AddSourceLocation(
- SourceLocation::getFromRawEncoding(DNLoc.CXXOperatorName.EndOpNameLoc));
+ AddSourceRange(DNLoc.getCXXOperatorNameRange());
break;
case DeclarationName::CXXLiteralOperatorName:
- AddSourceLocation(SourceLocation::getFromRawEncoding(
- DNLoc.CXXLiteralOperatorName.OpNameLoc));
+ AddSourceLocation(DNLoc.getCXXLiteralOperatorNameLoc());
break;
case DeclarationName::Identifier:
@@ -6142,6 +6050,20 @@
Record.AddSourceLocation(C->getLParenLoc());
}
+void OMPClauseWriter::VisitOMPSizesClause(OMPSizesClause *C) {
+ Record.push_back(C->getNumSizes());
+ for (Expr *Size : C->getSizesRefs())
+ Record.AddStmt(Size);
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPFullClause(OMPFullClause *C) {}
+
+void OMPClauseWriter::VisitOMPPartialClause(OMPPartialClause *C) {
+ Record.AddStmt(C->getFactor());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
void OMPClauseWriter::VisitOMPAllocatorClause(OMPAllocatorClause *C) {
Record.AddStmt(C->getAllocator());
Record.AddSourceLocation(C->getLParenLoc());
@@ -6229,7 +6151,45 @@
void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}
-void OMPClauseWriter::VisitOMPDestroyClause(OMPDestroyClause *) {}
+void OMPClauseWriter::VisitOMPInitClause(OMPInitClause *C) {
+ Record.push_back(C->varlist_size());
+ for (Expr *VE : C->varlists())
+ Record.AddStmt(VE);
+ Record.writeBool(C->getIsTarget());
+ Record.writeBool(C->getIsTargetSync());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getVarLoc());
+}
+
+void OMPClauseWriter::VisitOMPUseClause(OMPUseClause *C) {
+ Record.AddStmt(C->getInteropVar());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getVarLoc());
+}
+
+void OMPClauseWriter::VisitOMPDestroyClause(OMPDestroyClause *C) {
+ Record.AddStmt(C->getInteropVar());
+ Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddSourceLocation(C->getVarLoc());
+}
+
+void OMPClauseWriter::VisitOMPNovariantsClause(OMPNovariantsClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getCondition());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPNocontextClause(OMPNocontextClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getCondition());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
+void OMPClauseWriter::VisitOMPFilterClause(OMPFilterClause *C) {
+ VisitOMPClauseWithPreInit(C);
+ Record.AddStmt(C->getThreadID());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
Record.push_back(C->varlist_size());
diff --git a/src/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp b/src/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp
index 2cb44bf..e9315f6 100644
--- a/src/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/src/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -13,7 +13,6 @@
#include "ASTCommon.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
@@ -69,6 +68,7 @@
void VisitTypedefDecl(TypedefDecl *D);
void VisitTypeAliasDecl(TypeAliasDecl *D);
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+ void VisitUnresolvedUsingIfExistsDecl(UnresolvedUsingIfExistsDecl *D);
void VisitTagDecl(TagDecl *D);
void VisitEnumDecl(EnumDecl *D);
void VisitRecordDecl(RecordDecl *D);
@@ -114,6 +114,7 @@
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingEnumDecl(UsingEnumDecl *D);
void VisitUsingPackDecl(UsingPackDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
@@ -673,6 +674,7 @@
void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
addExplicitSpecifier(D->getExplicitSpecifier(), Record);
+ Record.AddDeclRef(D->Ctor);
VisitFunctionDecl(D);
Record.push_back(D->isCopyDeductionCandidate());
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
@@ -1277,6 +1279,16 @@
Code = serialization::DECL_USING;
}
+void ASTDeclWriter::VisitUsingEnumDecl(UsingEnumDecl *D) {
+ VisitNamedDecl(D);
+ Record.AddSourceLocation(D->getUsingLoc());
+ Record.AddSourceLocation(D->getEnumLoc());
+ Record.AddDeclRef(D->getEnumDecl());
+ Record.AddDeclRef(D->FirstUsingShadow.getPointer());
+ Record.AddDeclRef(Context.getInstantiatedFromUsingEnumDecl(D));
+ Code = serialization::DECL_USING_ENUM;
+}
+
void ASTDeclWriter::VisitUsingPackDecl(UsingPackDecl *D) {
Record.push_back(D->NumExpansions);
VisitNamedDecl(D);
@@ -1333,6 +1345,12 @@
Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
}
+void ASTDeclWriter::VisitUnresolvedUsingIfExistsDecl(
+ UnresolvedUsingIfExistsDecl *D) {
+ VisitNamedDecl(D);
+ Code = serialization::DECL_UNRESOLVED_USING_IF_EXISTS;
+}
+
void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
VisitRecordDecl(D);
@@ -1390,7 +1408,7 @@
}
void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
- Record.push_back(D->getTraillingAllocKind());
+ Record.push_back(D->getTrailingAllocKind());
addExplicitSpecifier(D->getExplicitSpecifier(), Record);
if (auto Inherited = D->getInheritedConstructor()) {
Record.AddDeclRef(Inherited.getShadowDecl());
diff --git a/src/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp b/src/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp
index d4f669e..2bb5e4f 100644
--- a/src/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/src/llvm-project/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -115,6 +115,7 @@
void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
VisitStmt(S);
+ Record.push_back(S->isSideEntry());
Record.AddDeclRef(S->getDecl());
Record.AddStmt(S->getSubStmt());
Record.AddSourceLocation(S->getIdentLoc());
@@ -579,6 +580,17 @@
Code = serialization::EXPR_CONSTANT;
}
+void ASTStmtWriter::VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *E) {
+ VisitExpr(E);
+
+ Record.AddSourceLocation(E->getLocation());
+ Record.AddSourceLocation(E->getLParenLocation());
+ Record.AddSourceLocation(E->getRParenLocation());
+ Record.AddTypeSourceInfo(E->getTypeSourceInfo());
+
+ Code = serialization::EXPR_SYCL_UNIQUE_STABLE_NAME;
+}
+
void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
@@ -2170,18 +2182,29 @@
// OpenMP Directives.
//===----------------------------------------------------------------------===//
+void ASTStmtWriter::VisitOMPCanonicalLoop(OMPCanonicalLoop *S) {
+ VisitStmt(S);
+ for (Stmt *SubStmt : S->SubStmts)
+ Record.AddStmt(SubStmt);
+ Code = serialization::STMT_OMP_CANONICAL_LOOP;
+}
+
void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
Record.writeOMPChildren(E->Data);
Record.AddSourceLocation(E->getBeginLoc());
Record.AddSourceLocation(E->getEndLoc());
}
-void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
+void ASTStmtWriter::VisitOMPLoopBasedDirective(OMPLoopBasedDirective *D) {
VisitStmt(D);
- Record.writeUInt32(D->getCollapsedNumber());
+ Record.writeUInt32(D->getLoopsNumber());
VisitOMPExecutableDirective(D);
}
+void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
+ VisitOMPLoopBasedDirective(D);
+}
+
void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
@@ -2194,6 +2217,16 @@
Code = serialization::STMT_OMP_SIMD_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPTileDirective(OMPTileDirective *D) {
+ VisitOMPLoopBasedDirective(D);
+ Code = serialization::STMT_OMP_TILE_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPUnrollDirective(OMPUnrollDirective *D) {
+ VisitOMPLoopBasedDirective(D);
+ Code = serialization::STMT_OMP_UNROLL_DIRECTIVE;
+}
+
void ASTStmtWriter::VisitOMPForDirective(OMPForDirective *D) {
VisitOMPLoopDirective(D);
Record.writeBool(D->hasCancel());
@@ -2525,6 +2558,25 @@
Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPInteropDirective(OMPInteropDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_INTEROP_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPDispatchDirective(OMPDispatchDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Record.AddSourceLocation(D->getTargetCallLoc());
+ Code = serialization::STMT_OMP_DISPATCH_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPMaskedDirective(OMPMaskedDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_MASKED_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/src/llvm-project/clang/lib/Serialization/ModuleFileExtension.cpp b/src/llvm-project/clang/lib/Serialization/ModuleFileExtension.cpp
index e1ae8a4..6b7fd1d 100644
--- a/src/llvm-project/clang/lib/Serialization/ModuleFileExtension.cpp
+++ b/src/llvm-project/clang/lib/Serialization/ModuleFileExtension.cpp
@@ -9,6 +9,8 @@
#include "llvm/ADT/Hashing.h"
using namespace clang;
+char ModuleFileExtension::ID = 0;
+
ModuleFileExtension::~ModuleFileExtension() { }
llvm::hash_code ModuleFileExtension::hashExtension(llvm::hash_code Code) const {
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
index 59163c1..605b118 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -16,7 +16,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index 7c264bb..2a5fe9d 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -19,7 +19,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
@@ -179,7 +179,7 @@
// CHECK UPPER BOUND: Is byteOffset >= size(baseRegion)? If so,
// we are doing a load/store after the last valid offset.
const MemRegion *MR = rawOffset.getRegion();
- DefinedOrUnknownSVal Size = getDynamicSize(state, MR, svalBuilder);
+ DefinedOrUnknownSVal Size = getDynamicExtent(state, MR, svalBuilder);
if (!Size.getAs<NonLoc>())
break;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
index 233ce57..13781b3 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -16,7 +16,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
using namespace clang;
using namespace ento;
@@ -92,12 +92,8 @@
if (Size.isUndef())
return true; // Return true to model purity.
- SValBuilder& svalBuilder = C.getSValBuilder();
- DefinedOrUnknownSVal DynSize = getDynamicSize(state, R, svalBuilder);
- DefinedOrUnknownSVal DynSizeMatchesSizeArg =
- svalBuilder.evalEQ(state, DynSize, Size.castAs<DefinedOrUnknownSVal>());
- state = state->assume(DynSizeMatchesSizeArg, true);
- assert(state && "The region should not have any previous constraints");
+ state = setDynamicExtent(state, R, Size.castAs<DefinedOrUnknownSVal>(),
+ C.getSValBuilder());
C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
return true;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 30fd62f..69b90be 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -19,7 +19,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
@@ -346,7 +346,7 @@
// Get the size of the array.
const auto *superReg = cast<SubRegion>(ER->getSuperRegion());
DefinedOrUnknownSVal Size =
- getDynamicSize(state, superReg, C.getSValBuilder());
+ getDynamicExtent(state, superReg, C.getSValBuilder());
// Get the index of the accessed element.
DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
@@ -923,7 +923,7 @@
// Get the size of the array.
const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
- DefinedOrUnknownSVal SizeDV = getDynamicSize(state, superReg, svalBuilder);
+ DefinedOrUnknownSVal SizeDV = getDynamicExtent(state, superReg, svalBuilder);
// Get the index of the accessed element.
DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
@@ -1060,7 +1060,7 @@
if (Offset.isValid() && !Offset.hasSymbolicOffset() &&
Offset.getOffset() == 0) {
// Get the base region's size.
- DefinedOrUnknownSVal SizeDV = getDynamicSize(State, BR, svalBuilder);
+ DefinedOrUnknownSVal SizeDV = getDynamicExtent(State, BR, svalBuilder);
ProgramStateRef StateWholeReg, StateNotWholeReg;
std::tie(StateWholeReg, StateNotWholeReg) =
@@ -2039,7 +2039,7 @@
RightStrRef = RightStrRef.substr(0, s2Term);
// Use StringRef's comparison methods to compute the actual result.
- int compareRes = IgnoreCase ? LeftStrRef.compare_lower(RightStrRef)
+ int compareRes = IgnoreCase ? LeftStrRef.compare_insensitive(RightStrRef)
: LeftStrRef.compare(RightStrRef);
// The strcmp function returns an integer greater than, equal to, or less
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index a498f25..2d2e14d 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -17,7 +17,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
using namespace clang;
using namespace ento;
@@ -112,7 +112,7 @@
SValBuilder &svalBuilder = C.getSValBuilder();
- DefinedOrUnknownSVal Size = getDynamicSize(state, SR, svalBuilder);
+ DefinedOrUnknownSVal Size = getDynamicExtent(state, SR, svalBuilder);
const llvm::APSInt *SizeInt = svalBuilder.getKnownValue(state, Size);
if (!SizeInt)
return;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
index dc9cd71..99e11a1 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp
@@ -13,7 +13,7 @@
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "llvm/Support/FormatVariadic.h"
using namespace clang;
@@ -64,7 +64,7 @@
SVal PlacementNewChecker::getExtentSizeOfPlace(const CXXNewExpr *NE,
CheckerContext &C) const {
const Expr *Place = NE->getPlacementArg(0);
- return getDynamicSizeWithOffset(C.getState(), C.getSVal(Place));
+ return getDynamicExtentWithOffset(C.getState(), C.getSVal(Place));
}
SVal PlacementNewChecker::getExtentSizeOfNewTarget(const CXXNewExpr *NE,
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
index 73c6517..1a7f0d5 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp
@@ -763,14 +763,14 @@
const auto *IdInfo = Func->getIdentifier();
if (!IdInfo)
return false;
- return IdInfo->getName().endswith_lower("begin");
+ return IdInfo->getName().endswith_insensitive("begin");
}
bool isEndCall(const FunctionDecl *Func) {
const auto *IdInfo = Func->getIdentifier();
if (!IdInfo)
return false;
- return IdInfo->getName().endswith_lower("end");
+ return IdInfo->getName().endswith_insensitive("end");
}
const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State,
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
index 6bc186a..8070d86 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp
@@ -11,17 +11,18 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Lex/Lexer.h"
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/SaveAndRestore.h"
@@ -260,8 +261,8 @@
break;
}
- BR.EmitBasicReport(AC->getDecl(), Checker, BugType, "Dead store", os.str(),
- L, R, Fixits);
+ BR.EmitBasicReport(AC->getDecl(), Checker, BugType, categories::UnusedCode,
+ os.str(), L, R, Fixits);
}
void CheckVarDecl(const VarDecl *VD, const Expr *Ex, const Expr *Val,
@@ -408,15 +409,17 @@
// Special case: check for initializations with constants.
//
// e.g. : int x = 0;
+ // struct A = {0, 1};
+ // struct B = {{0}, {1, 2}};
//
// If x is EVER assigned a new value later, don't issue
// a warning. This is because such initialization can be
// due to defensive programming.
- if (E->isEvaluatable(Ctx))
+ if (isConstant(E))
return;
if (const DeclRefExpr *DRE =
- dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
+ dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
// Special case: check for initialization from constant
// variables.
@@ -444,6 +447,29 @@
}
}
}
+
+private:
+ /// Return true if the given init list can be interpreted as constant
+ bool isConstant(const InitListExpr *Candidate) const {
+ // We consider init list to be constant if each member of the list can be
+ // interpreted as constant.
+ return llvm::all_of(Candidate->inits(),
+ [this](const Expr *Init) { return isConstant(Init); });
+ }
+
+ /// Return true if the given expression can be interpreted as constant
+ bool isConstant(const Expr *E) const {
+ // It looks like E itself is a constant
+ if (E->isEvaluatable(Ctx))
+ return true;
+
+ // We should also allow defensive initialization of structs, i.e. { 0 }
+ if (const auto *ILE = dyn_cast<InitListExpr>(E->IgnoreParenCasts())) {
+ return isConstant(ILE);
+ }
+
+ return false;
+ }
};
} // end anonymous namespace
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index adfc2f8..4a9c7ce 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -193,7 +193,7 @@
}
auto report = std::make_unique<PathSensitiveBugReport>(
- *BT, buf.empty() ? BT->getDescription() : StringRef(buf), N);
+ *BT, buf.empty() ? BT->getDescription() : buf.str(), N);
bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report);
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index c0167b5..2ce1bef 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -14,7 +14,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -22,8 +22,8 @@
using namespace ento;
namespace {
-class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols,
- check::EndAnalysis> {
+class ExprInspectionChecker
+ : public Checker<eval::Call, check::DeadSymbols, check::EndAnalysis> {
mutable std::unique_ptr<BugType> BT;
// These stats are per-analysis, not per-branch, hence they shouldn't
@@ -44,6 +44,8 @@
void analyzerExplain(const CallExpr *CE, CheckerContext &C) const;
void analyzerPrintState(const CallExpr *CE, CheckerContext &C) const;
void analyzerGetExtent(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerDumpExtent(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerDumpElementCount(const CallExpr *CE, CheckerContext &C) const;
void analyzerHashDump(const CallExpr *CE, CheckerContext &C) const;
void analyzerDenote(const CallExpr *CE, CheckerContext &C) const;
void analyzerExpress(const CallExpr *CE, CheckerContext &C) const;
@@ -55,17 +57,19 @@
// Optional parameter `ExprVal` for expression value to be marked interesting.
ExplodedNode *reportBug(llvm::StringRef Msg, CheckerContext &C,
Optional<SVal> ExprVal = None) const;
- ExplodedNode *reportBug(llvm::StringRef Msg, BugReporter &BR,
- ExplodedNode *N,
+ ExplodedNode *reportBug(llvm::StringRef Msg, BugReporter &BR, ExplodedNode *N,
Optional<SVal> ExprVal = None) const;
+ const Expr *getArgExpr(const CallExpr *CE, CheckerContext &C) const;
+ const MemRegion *getArgRegion(const CallExpr *CE, CheckerContext &C) const;
+
public:
bool evalCall(const CallEvent &Call, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
ExprEngine &Eng) const;
};
-}
+} // namespace
REGISTER_SET_WITH_PROGRAMSTATE(MarkedSymbols, SymbolRef)
REGISTER_MAP_WITH_PROGRAMSTATE(DenotedSymbols, SymbolRef, const StringLiteral *)
@@ -90,6 +94,10 @@
&ExprInspectionChecker::analyzerWarnOnDeadSymbol)
.StartsWith("clang_analyzer_explain",
&ExprInspectionChecker::analyzerExplain)
+ .Case("clang_analyzer_dumpExtent",
+ &ExprInspectionChecker::analyzerDumpExtent)
+ .Case("clang_analyzer_dumpElementCount",
+ &ExprInspectionChecker::analyzerDumpElementCount)
.StartsWith("clang_analyzer_dump",
&ExprInspectionChecker::analyzerDump)
.Case("clang_analyzer_getExtent",
@@ -131,7 +139,7 @@
ProgramStateRef StTrue, StFalse;
std::tie(StTrue, StFalse) =
- State->assume(AssertionVal.castAs<DefinedOrUnknownSVal>());
+ State->assume(AssertionVal.castAs<DefinedOrUnknownSVal>());
if (StTrue) {
if (StFalse)
@@ -155,8 +163,7 @@
}
ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
- BugReporter &BR,
- ExplodedNode *N,
+ BugReporter &BR, ExplodedNode *N,
Optional<SVal> ExprVal) const {
if (!N)
return nullptr;
@@ -172,6 +179,30 @@
return N;
}
+const Expr *ExprInspectionChecker::getArgExpr(const CallExpr *CE,
+ CheckerContext &C) const {
+ if (CE->getNumArgs() == 0) {
+ reportBug("Missing argument", C);
+ return nullptr;
+ }
+ return CE->getArg(0);
+}
+
+const MemRegion *ExprInspectionChecker::getArgRegion(const CallExpr *CE,
+ CheckerContext &C) const {
+ const Expr *Arg = getArgExpr(CE, C);
+ if (!Arg)
+ return nullptr;
+
+ const MemRegion *MR = C.getSVal(Arg).getAsRegion();
+ if (!MR) {
+ reportBug("Cannot obtain the region", C);
+ return nullptr;
+ }
+
+ return MR;
+}
+
void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
CheckerContext &C) const {
const LocationContext *LC = C.getPredecessor()->getLocationContext();
@@ -215,24 +246,22 @@
void ExprInspectionChecker::analyzerExplain(const CallExpr *CE,
CheckerContext &C) const {
- if (CE->getNumArgs() == 0) {
- reportBug("Missing argument for explaining", C);
+ const Expr *Arg = getArgExpr(CE, C);
+ if (!Arg)
return;
- }
- SVal V = C.getSVal(CE->getArg(0));
+ SVal V = C.getSVal(Arg);
SValExplainer Ex(C.getASTContext());
reportBug(Ex.Visit(V), C);
}
void ExprInspectionChecker::analyzerDump(const CallExpr *CE,
CheckerContext &C) const {
- if (CE->getNumArgs() == 0) {
- reportBug("Missing argument for dumping", C);
+ const Expr *Arg = getArgExpr(CE, C);
+ if (!Arg)
return;
- }
- SVal V = C.getSVal(CE->getArg(0));
+ SVal V = C.getSVal(Arg);
llvm::SmallString<32> Str;
llvm::raw_svector_ostream OS(Str);
@@ -242,24 +271,57 @@
void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
CheckerContext &C) const {
- if (CE->getNumArgs() == 0) {
- reportBug("Missing region for obtaining extent", C);
+ const MemRegion *MR = getArgRegion(CE, C);
+ if (!MR)
return;
- }
-
- auto MR = dyn_cast_or_null<SubRegion>(C.getSVal(CE->getArg(0)).getAsRegion());
- if (!MR) {
- reportBug("Obtaining extent of a non-region", C);
- return;
- }
ProgramStateRef State = C.getState();
- DefinedOrUnknownSVal Size = getDynamicSize(State, MR, C.getSValBuilder());
+ DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, C.getSValBuilder());
State = State->BindExpr(CE, C.getLocationContext(), Size);
C.addTransition(State);
}
+void ExprInspectionChecker::analyzerDumpExtent(const CallExpr *CE,
+ CheckerContext &C) const {
+ const MemRegion *MR = getArgRegion(CE, C);
+ if (!MR)
+ return;
+
+ DefinedOrUnknownSVal Size =
+ getDynamicExtent(C.getState(), MR, C.getSValBuilder());
+
+ SmallString<64> Msg;
+ llvm::raw_svector_ostream Out(Msg);
+ Out << Size;
+ reportBug(Out.str(), C);
+}
+
+void ExprInspectionChecker::analyzerDumpElementCount(const CallExpr *CE,
+ CheckerContext &C) const {
+ const MemRegion *MR = getArgRegion(CE, C);
+ if (!MR)
+ return;
+
+ QualType ElementTy;
+ if (const auto *TVR = MR->getAs<TypedValueRegion>()) {
+ ElementTy = TVR->getValueType();
+ } else {
+ ElementTy =
+ MR->castAs<SymbolicRegion>()->getSymbol()->getType()->getPointeeType();
+ }
+
+ assert(!ElementTy->isPointerType());
+
+ DefinedOrUnknownSVal ElementCount =
+ getDynamicElementCount(C.getState(), MR, C.getSValBuilder(), ElementTy);
+
+ SmallString<128> Msg;
+ llvm::raw_svector_ostream Out(Msg);
+ Out << ElementCount;
+ reportBug(Out.str(), C);
+}
+
void ExprInspectionChecker::analyzerPrintState(const CallExpr *CE,
CheckerContext &C) const {
C.getState()->dump();
@@ -267,9 +329,11 @@
void ExprInspectionChecker::analyzerWarnOnDeadSymbol(const CallExpr *CE,
CheckerContext &C) const {
- if (CE->getNumArgs() == 0)
+ const Expr *Arg = getArgExpr(CE, C);
+ if (!Arg)
return;
- SVal Val = C.getSVal(CE->getArg(0));
+
+ SVal Val = C.getSVal(Arg);
SymbolRef Sym = Val.getAsSymbol();
if (!Sym)
return;
@@ -306,7 +370,7 @@
void ExprInspectionChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
ExprEngine &Eng) const {
- for (auto Item: ReachedStats) {
+ for (auto Item : ReachedStats) {
unsigned NumTimesReached = Item.second.NumTimesReached;
ExplodedNode *N = Item.second.ExampleNode;
@@ -373,9 +437,7 @@
return None;
}
- Optional<std::string> VisitSymExpr(const SymExpr *S) {
- return lookup(S);
- }
+ Optional<std::string> VisitSymExpr(const SymExpr *S) { return lookup(S); }
Optional<std::string> VisitSymIntExpr(const SymIntExpr *S) {
if (Optional<std::string> Str = lookup(S))
@@ -394,7 +456,8 @@
if (Optional<std::string> Str1 = Visit(S->getLHS()))
if (Optional<std::string> Str2 = Visit(S->getRHS()))
return (*Str1 + " " + BinaryOperator::getOpcodeStr(S->getOpcode()) +
- " " + *Str2).str();
+ " " + *Str2)
+ .str();
return None;
}
@@ -410,10 +473,9 @@
void ExprInspectionChecker::analyzerExpress(const CallExpr *CE,
CheckerContext &C) const {
- if (CE->getNumArgs() == 0) {
- reportBug("clang_analyzer_express() requires a symbol", C);
+ const Expr *Arg = getArgExpr(CE, C);
+ if (!Arg)
return;
- }
SVal ArgVal = C.getSVal(CE->getArg(0));
SymbolRef Sym = ArgVal.getAsSymbol();
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
index 63fbe75..8e02ef7 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp
@@ -80,7 +80,7 @@
if (const auto *CD = dyn_cast<ObjCContainerDecl>(OD->getParent())) {
std::string ContainerName = CD->getNameAsString();
StringRef CN(ContainerName);
- if (CN.contains_lower("test") || CN.contains_lower("mock"))
+ if (CN.contains_insensitive("test") || CN.contains_insensitive("mock"))
return true;
}
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
index 65e52e1..bcae733 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
@@ -34,9 +34,9 @@
class InnerPointerChecker
: public Checker<check::DeadSymbols, check::PostCall> {
- CallDescription AppendFn, AssignFn, ClearFn, CStrFn, DataFn, EraseFn,
- InsertFn, PopBackFn, PushBackFn, ReplaceFn, ReserveFn, ResizeFn,
- ShrinkToFitFn, SwapFn;
+ CallDescription AppendFn, AssignFn, AddressofFn, ClearFn, CStrFn, DataFn,
+ DataMemberFn, EraseFn, InsertFn, PopBackFn, PushBackFn, ReplaceFn,
+ ReserveFn, ResizeFn, ShrinkToFitFn, SwapFn;
public:
class InnerPointerBRVisitor : public BugReporterVisitor {
@@ -73,9 +73,10 @@
InnerPointerChecker()
: AppendFn({"std", "basic_string", "append"}),
AssignFn({"std", "basic_string", "assign"}),
+ AddressofFn({"std", "addressof"}),
ClearFn({"std", "basic_string", "clear"}),
- CStrFn({"std", "basic_string", "c_str"}),
- DataFn({"std", "basic_string", "data"}),
+ CStrFn({"std", "basic_string", "c_str"}), DataFn({"std", "data"}, 1),
+ DataMemberFn({"std", "basic_string", "data"}),
EraseFn({"std", "basic_string", "erase"}),
InsertFn({"std", "basic_string", "insert"}),
PopBackFn({"std", "basic_string", "pop_back"}),
@@ -90,6 +91,9 @@
/// pointers referring to the container object's inner buffer.
bool isInvalidatingMemberFunction(const CallEvent &Call) const;
+ /// Check whether the called function returns a raw inner pointer.
+ bool isInnerPointerAccessFunction(const CallEvent &Call) const;
+
/// Mark pointer symbols associated with the given memory region released
/// in the program state.
void markPtrSymbolsReleased(const CallEvent &Call, ProgramStateRef State,
@@ -130,6 +134,12 @@
Call.isCalled(SwapFn));
}
+bool InnerPointerChecker::isInnerPointerAccessFunction(
+ const CallEvent &Call) const {
+ return (Call.isCalled(CStrFn) || Call.isCalled(DataFn) ||
+ Call.isCalled(DataMemberFn));
+}
+
void InnerPointerChecker::markPtrSymbolsReleased(const CallEvent &Call,
ProgramStateRef State,
const MemRegion *MR,
@@ -172,6 +182,11 @@
if (!ArgRegion)
continue;
+ // std::addressof function accepts a non-const reference as an argument,
+ // but doesn't modify it.
+ if (Call.isCalled(AddressofFn))
+ continue;
+
markPtrSymbolsReleased(Call, State, ArgRegion, C);
}
}
@@ -195,30 +210,12 @@
CheckerContext &C) const {
ProgramStateRef State = C.getState();
+ // TODO: Do we need these to be typed?
+ const TypedValueRegion *ObjRegion = nullptr;
+
if (const auto *ICall = dyn_cast<CXXInstanceCall>(&Call)) {
- // TODO: Do we need these to be typed?
- const auto *ObjRegion = dyn_cast_or_null<TypedValueRegion>(
+ ObjRegion = dyn_cast_or_null<TypedValueRegion>(
ICall->getCXXThisVal().getAsRegion());
- if (!ObjRegion)
- return;
-
- if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) {
- SVal RawPtr = Call.getReturnValue();
- if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) {
- // Start tracking this raw pointer by adding it to the set of symbols
- // associated with this container object in the program state map.
-
- PtrSet::Factory &F = State->getStateManager().get_context<PtrSet>();
- const PtrSet *SetPtr = State->get<RawPtrMap>(ObjRegion);
- PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet();
- assert(C.wasInlined || !Set.contains(Sym));
- Set = F.add(Set, Sym);
-
- State = State->set<RawPtrMap>(ObjRegion, Set);
- C.addTransition(State);
- }
- return;
- }
// Check [string.require] / second point.
if (isInvalidatingMemberFunction(Call)) {
@@ -227,6 +224,37 @@
}
}
+ if (isInnerPointerAccessFunction(Call)) {
+
+ if (isa<SimpleFunctionCall>(Call)) {
+ // NOTE: As of now, we only have one free access function: std::data.
+ // If we add more functions like this in the list, hardcoded
+ // argument index should be changed.
+ ObjRegion =
+ dyn_cast_or_null<TypedValueRegion>(Call.getArgSVal(0).getAsRegion());
+ }
+
+ if (!ObjRegion)
+ return;
+
+ SVal RawPtr = Call.getReturnValue();
+ if (SymbolRef Sym = RawPtr.getAsSymbol(/*IncludeBaseRegions=*/true)) {
+ // Start tracking this raw pointer by adding it to the set of symbols
+ // associated with this container object in the program state map.
+
+ PtrSet::Factory &F = State->getStateManager().get_context<PtrSet>();
+ const PtrSet *SetPtr = State->get<RawPtrMap>(ObjRegion);
+ PtrSet Set = SetPtr ? *SetPtr : F.getEmptySet();
+ assert(C.wasInlined || !Set.contains(Sym));
+ Set = F.add(Set, Sym);
+
+ State = State->set<RawPtrMap>(ObjRegion, Set);
+ C.addTransition(State);
+ }
+
+ return;
+ }
+
// Check [string.require] / first point.
checkFunctionArguments(Call, State, C);
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
index ac0f246..4961901 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/Iterator.cpp
@@ -29,8 +29,8 @@
return false;
const auto Name = CRD->getName();
- if (!(Name.endswith_lower("iterator") || Name.endswith_lower("iter") ||
- Name.endswith_lower("it")))
+ if (!(Name.endswith_insensitive("iterator") ||
+ Name.endswith_insensitive("iter") || Name.endswith_insensitive("it")))
return false;
bool HasCopyCtor = false, HasCopyAssign = true, HasDtor = false,
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
index dd01464..a474844 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/IteratorRangeChecker.cpp
@@ -228,7 +228,7 @@
Value = State->getRawSVal(*ValAsLoc);
}
- if (Value.isUnknown())
+ if (Value.isUnknownOrUndef())
return;
// Incremention or decremention by 0 is never a bug.
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp
index 8372138..b72d725 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp
@@ -284,8 +284,9 @@
N);
R->addRange(RS->getSourceRange());
- bugreporter::trackExpressionValue(N, RS->getRetValue(), *R,
- bugreporter::TrackingKind::Thorough, false);
+ bugreporter::trackExpressionValue(
+ N, RS->getRetValue(), *R,
+ {bugreporter::TrackingKind::Thorough, /*EnableNullFPSuppression=*/false});
C.emitReport(std::move(R));
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
index 7ac7a38..5d6bd38 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -16,7 +16,7 @@
#include "MPIChecker.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
namespace clang {
namespace ento {
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index f117d55..a6470da 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -63,7 +63,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
@@ -509,10 +509,6 @@
ProgramStateRef State,
AllocationFamily Family);
- LLVM_NODISCARD
- static ProgramStateRef addExtentSize(CheckerContext &C, const CXXNewExpr *NE,
- ProgramStateRef State, SVal Target);
-
// Check if this malloc() for special flags. At present that means M_ZERO or
// __GFP_ZERO (in which case, treat it like calloc).
LLVM_NODISCARD
@@ -1424,7 +1420,6 @@
// existing binding.
SVal Target = Call.getObjectUnderConstruction();
State = MallocUpdateRefState(C, NE, State, Family, Target);
- State = addExtentSize(C, NE, State, Target);
State = ProcessZeroAllocCheck(Call, 0, State, Target);
return State;
}
@@ -1439,52 +1434,6 @@
}
}
-// Sets the extent value of the MemRegion allocated by
-// new expression NE to its size in Bytes.
-//
-ProgramStateRef MallocChecker::addExtentSize(CheckerContext &C,
- const CXXNewExpr *NE,
- ProgramStateRef State,
- SVal Target) {
- if (!State)
- return nullptr;
- SValBuilder &svalBuilder = C.getSValBuilder();
- SVal ElementCount;
- const SubRegion *Region;
- if (NE->isArray()) {
- const Expr *SizeExpr = *NE->getArraySize();
- ElementCount = C.getSVal(SizeExpr);
- // Store the extent size for the (symbolic)region
- // containing the elements.
- Region = Target.getAsRegion()
- ->castAs<SubRegion>()
- ->StripCasts()
- ->castAs<SubRegion>();
- } else {
- ElementCount = svalBuilder.makeIntVal(1, true);
- Region = Target.getAsRegion()->castAs<SubRegion>();
- }
-
- // Set the region's extent equal to the Size in Bytes.
- QualType ElementType = NE->getAllocatedType();
- ASTContext &AstContext = C.getASTContext();
- CharUnits TypeSize = AstContext.getTypeSizeInChars(ElementType);
-
- if (ElementCount.getAs<NonLoc>()) {
- DefinedOrUnknownSVal DynSize = getDynamicSize(State, Region, svalBuilder);
-
- // size in Bytes = ElementCount*TypeSize
- SVal SizeInBytes = svalBuilder.evalBinOpNN(
- State, BO_Mul, ElementCount.castAs<NonLoc>(),
- svalBuilder.makeArrayIndex(TypeSize.getQuantity()),
- svalBuilder.getArrayIndexType());
- DefinedOrUnknownSVal DynSizeMatchesSize = svalBuilder.evalEQ(
- State, DynSize, SizeInBytes.castAs<DefinedOrUnknownSVal>());
- State = State->assume(DynSizeMatchesSize, true);
- }
- return State;
-}
-
static bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call) {
// If the first selector piece is one of the names below, assume that the
// object takes ownership of the memory, promising to eventually deallocate it
@@ -1588,21 +1537,9 @@
// Fill the region with the initialization value.
State = State->bindDefaultInitial(RetVal, Init, LCtx);
- // Set the region's extent equal to the Size parameter.
- const SymbolicRegion *R =
- dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion());
- if (!R)
- return nullptr;
- if (Optional<DefinedOrUnknownSVal> DefinedSize =
- Size.getAs<DefinedOrUnknownSVal>()) {
- DefinedOrUnknownSVal DynSize = getDynamicSize(State, R, svalBuilder);
-
- DefinedOrUnknownSVal DynSizeMatchesSize =
- svalBuilder.evalEQ(State, DynSize, *DefinedSize);
-
- State = State->assume(DynSizeMatchesSize, true);
- assert(State);
- }
+ // Set the region's extent.
+ State = setDynamicExtent(State, RetVal.getAsRegion(),
+ Size.castAs<DefinedOrUnknownSVal>(), svalBuilder);
return MallocUpdateRefState(C, CE, State, Family);
}
@@ -2186,7 +2123,7 @@
os.str(), N);
R->markInteresting(Sym);
R->addRange(Range);
- R->addVisitor(std::make_unique<MallocBugVisitor>(Sym));
+ R->addVisitor<MallocBugVisitor>(Sym);
C.emitReport(std::move(R));
}
}
@@ -2279,7 +2216,7 @@
R->markInteresting(Sym);
R->addRange(Range);
- R->addVisitor(std::make_unique<MallocBugVisitor>(Sym));
+ R->addVisitor<MallocBugVisitor>(Sym);
if (AF == AF_InnerBuffer)
R->addVisitor(allocation_state::getInnerPointerBRVisitor(Sym));
@@ -2315,7 +2252,7 @@
R->markInteresting(Sym);
if (PrevSym)
R->markInteresting(PrevSym);
- R->addVisitor(std::make_unique<MallocBugVisitor>(Sym));
+ R->addVisitor<MallocBugVisitor>(Sym);
C.emitReport(std::move(R));
}
}
@@ -2341,7 +2278,7 @@
*BT_DoubleDelete, "Attempt to delete released memory", N);
R->markInteresting(Sym);
- R->addVisitor(std::make_unique<MallocBugVisitor>(Sym));
+ R->addVisitor<MallocBugVisitor>(Sym);
C.emitReport(std::move(R));
}
}
@@ -2371,7 +2308,7 @@
R->addRange(Range);
if (Sym) {
R->markInteresting(Sym);
- R->addVisitor(std::make_unique<MallocBugVisitor>(Sym));
+ R->addVisitor<MallocBugVisitor>(Sym);
}
C.emitReport(std::move(R));
}
@@ -2641,7 +2578,7 @@
*BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
AllocNode->getLocationContext()->getDecl());
R->markInteresting(Sym);
- R->addVisitor(std::make_unique<MallocBugVisitor>(Sym, true));
+ R->addVisitor<MallocBugVisitor>(Sym, true);
C.emitReport(std::move(R));
}
@@ -3208,9 +3145,10 @@
static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD) {
if (const IdentifierInfo *II = DD->getParent()->getIdentifier()) {
StringRef N = II->getName();
- if (N.contains_lower("ptr") || N.contains_lower("pointer")) {
- if (N.contains_lower("ref") || N.contains_lower("cnt") ||
- N.contains_lower("intrusive") || N.contains_lower("shared")) {
+ if (N.contains_insensitive("ptr") || N.contains_insensitive("pointer")) {
+ if (N.contains_insensitive("ref") || N.contains_insensitive("cnt") ||
+ N.contains_insensitive("intrusive") ||
+ N.contains_insensitive("shared")) {
return true;
}
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
index 71f593c..4b5206a 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
@@ -139,6 +139,10 @@
if (B->isVoidPointerType() && A->getAs<PointerType>())
return true;
+ // sizeof(pointer type) is compatible with void*
+ if (A->isVoidPointerType() && B->getAs<PointerType>())
+ return true;
+
while (true) {
A = A.getCanonicalType();
B = B.getCanonicalType();
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
index a38298a..cbe9389 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
@@ -202,7 +202,7 @@
};
private:
- mutable std::unique_ptr<BugType> BT;
+ BugType BT{this, "Use-after-move", categories::CXXMoveSemantics};
// Check if the given form of potential misuse of a given object
// should be reported. If so, get it reported. The callback from which
@@ -393,11 +393,6 @@
MisuseKind MK) const {
if (ExplodedNode *N = misuseCausesCrash(MK) ? C.generateErrorNode()
: C.generateNonFatalErrorNode()) {
-
- if (!BT)
- BT.reset(new BugType(this, "Use-after-move",
- "C++ move semantics"));
-
// Uniqueing report to the same object.
PathDiagnosticLocation LocUsedForUniqueing;
const ExplodedNode *MoveNode = getMoveLocation(N, Region, C);
@@ -431,7 +426,7 @@
}
auto R = std::make_unique<PathSensitiveBugReport>(
- *BT, OS.str(), N, LocUsedForUniqueing,
+ BT, OS.str(), N, LocUsedForUniqueing,
MoveNode->getLocationContext()->getDecl());
R->addVisitor(std::make_unique<MovedBugVisitor>(*this, Region, RD, MK));
C.emitReport(std::move(R));
@@ -477,7 +472,7 @@
const MemRegion *BaseRegion = ArgRegion->getBaseRegion();
// Skip temp objects because of their short lifetime.
if (BaseRegion->getAs<CXXTempObjectRegion>() ||
- AFC->getArgExpr(0)->isRValue())
+ AFC->getArgExpr(0)->isPRValue())
return;
// If it has already been reported do not need to modify the state.
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
index 80b705f..c5437b1 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
@@ -89,7 +89,7 @@
}
/// \param V loaded lvalue.
-/// \return whether {@code val} is a string-like const global.
+/// \return whether @c val is a string-like const global.
bool NonnullGlobalConstantsChecker::isGlobalConstString(SVal V) const {
Optional<loc::MemRegionVal> RegionVal = V.getAs<loc::MemRegionVal>();
if (!RegionVal)
@@ -127,7 +127,7 @@
return false;
}
-/// \return whether {@code type} is extremely unlikely to be null
+/// \return whether @c type is extremely unlikely to be null
bool NonnullGlobalConstantsChecker::isNonnullType(QualType Ty) const {
if (Ty->isPointerType() && Ty->getPointeeType()->isCharType())
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index bc7a8a3..fe8f7e7 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -170,7 +170,7 @@
auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
if (Region) {
R->markInteresting(Region);
- R->addVisitor(std::make_unique<NullabilityBugVisitor>(Region));
+ R->addVisitor<NullabilityBugVisitor>(Region);
}
if (ValueExpr) {
R->addRange(ValueExpr->getSourceRange());
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp
index 270b66d..0a8379d 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp
@@ -32,7 +32,21 @@
void checkASTCodeBody(const Decl *D, AnalysisManager &AM,
BugReporter &BR) const;
};
+} // namespace
+
+namespace clang {
+namespace ast_matchers {
+AST_MATCHER_P(StringLiteral, mentionsBoundType, std::string, BindingID) {
+ return Builder->removeBindings([this, &Node](const BoundNodesMap &Nodes) {
+ const auto &BN = Nodes.getNode(this->BindingID);
+ if (const auto *ND = BN.get<NamedDecl>()) {
+ return ND->getName() != Node.getString();
+ }
+ return true;
+ });
}
+} // end namespace ast_matchers
+} // end namespace clang
static void emitDiagnostics(const BoundNodes &Nodes,
BugReporter &BR,
@@ -63,22 +77,41 @@
return hasType(pointerType(pointee(hasDeclaration(DeclM))));
}
-void OSObjectCStyleCastChecker::checkASTCodeBody(const Decl *D, AnalysisManager &AM,
+void OSObjectCStyleCastChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
BugReporter &BR) const {
AnalysisDeclContext *ADC = AM.getAnalysisDeclContext(D);
auto DynamicCastM = callExpr(callee(functionDecl(hasName("safeMetaCast"))));
+ // 'allocClassWithName' allocates an object with the given type.
+ // The type is actually provided as a string argument (type's name).
+ // This makes the following pattern possible:
+ //
+ // Foo *object = (Foo *)allocClassWithName("Foo");
+ //
+ // While OSRequiredCast can be used here, it is still not a useful warning.
+ auto AllocClassWithNameM = callExpr(
+ callee(functionDecl(hasName("allocClassWithName"))),
+ // Here we want to make sure that the string argument matches the
+ // type in the cast expression.
+ hasArgument(0, stringLiteral(mentionsBoundType(WarnRecordDecl))));
- auto OSObjTypeM = hasTypePointingTo(cxxRecordDecl(isDerivedFrom("OSMetaClassBase")));
+ auto OSObjTypeM =
+ hasTypePointingTo(cxxRecordDecl(isDerivedFrom("OSMetaClassBase")));
auto OSObjSubclassM = hasTypePointingTo(
- cxxRecordDecl(isDerivedFrom("OSObject")).bind(WarnRecordDecl));
+ cxxRecordDecl(isDerivedFrom("OSObject")).bind(WarnRecordDecl));
- auto CastM = cStyleCastExpr(
- allOf(hasSourceExpression(allOf(OSObjTypeM, unless(DynamicCastM))),
- OSObjSubclassM)).bind(WarnAtNode);
+ auto CastM =
+ cStyleCastExpr(
+ allOf(OSObjSubclassM,
+ hasSourceExpression(
+ allOf(OSObjTypeM,
+ unless(anyOf(DynamicCastM, AllocClassWithNameM))))))
+ .bind(WarnAtNode);
- auto Matches = match(stmt(forEachDescendant(CastM)), *D->getBody(), AM.getASTContext());
+ auto Matches =
+ match(stmt(forEachDescendant(CastM)), *D->getBody(), AM.getASTContext());
for (BoundNodes Match : Matches)
emitDiagnostics(Match, BR, ADC, this);
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
index 7fd6e2a..c8eab32 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
@@ -8,7 +8,7 @@
//
// This file defines ObjCAutoreleaseWriteChecker which warns against writes
// into autoreleased out parameters which cause crashes.
-// An example of a problematic write is a write to {@code error} in the example
+// An example of a problematic write is a write to @c error in the example
// below:
//
// - (BOOL) mymethod:(NSError *__autoreleasing *)error list:(NSArray*) list {
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
index 8c2008a..13985af 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
@@ -147,8 +147,9 @@
auto R = std::make_unique<PathSensitiveBugReport>(
*BT, "Index is out of bounds", N);
R->addRange(IdxExpr->getSourceRange());
- bugreporter::trackExpressionValue(
- N, IdxExpr, *R, bugreporter::TrackingKind::Thorough, false);
+ bugreporter::trackExpressionValue(N, IdxExpr, *R,
+ {bugreporter::TrackingKind::Thorough,
+ /*EnableNullFPSuppression=*/false});
C.emitReport(std::move(R));
return;
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index 96f0d9b..40472cc 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -193,6 +193,11 @@
CharUnits PaddingSum;
CharUnits Offset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0));
for (const FieldDecl *FD : RD->fields()) {
+ // Skip field that is a subobject of zero size, marked with
+ // [[no_unique_address]] or an empty bitfield, because its address can be
+ // set the same as the other fields addresses.
+ if (FD->isZeroSize(ASTContext))
+ continue;
// This checker only cares about the padded size of the
// field, and not the data size. If the field is a record
// with tail padding, then we won't put that number in our
@@ -249,7 +254,7 @@
RetVal.Field = FD;
auto &Ctx = FD->getASTContext();
auto Info = Ctx.getTypeInfoInChars(FD->getType());
- RetVal.Size = Info.Width;
+ RetVal.Size = FD->isZeroSize(Ctx) ? CharUnits::Zero() : Info.Width;
RetVal.Align = Info.Align;
assert(llvm::isPowerOf2_64(RetVal.Align.getQuantity()));
if (auto Max = FD->getMaxAlignment())
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index 88e80c4..ee71b55 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -339,7 +339,16 @@
}
}
- // TODO: Dump destroyed mutex symbols?
+ DestroyRetValTy DRV = State->get<DestroyRetVal>();
+ if (!DRV.isEmpty()) {
+ Out << Sep << "Mutexes in unresolved possibly destroyed state:" << NL;
+ for (auto I : DRV) {
+ I.first->dumpToStream(Out);
+ Out << ": ";
+ I.second->dumpToStream(Out);
+ Out << NL;
+ }
+ }
}
void PthreadLockChecker::AcquirePthreadLock(const CallEvent &Call,
@@ -638,8 +647,10 @@
for (auto I : State->get<LockMap>()) {
// Stop tracking dead mutex regions as well.
- if (!SymReaper.isLiveRegion(I.first))
+ if (!SymReaper.isLiveRegion(I.first)) {
State = State->remove<LockMap>(I.first);
+ State = State->remove<DestroyRetVal>(I.first);
+ }
}
// TODO: We probably need to clean up the lock stack as well.
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
index 1d90353..64ac6bc 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
@@ -13,6 +13,8 @@
#include "RetainCountDiagnostics.h"
#include "RetainCountChecker.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
using namespace clang;
using namespace ento;
@@ -89,7 +91,7 @@
return QT.getAsString();
}
-/// Write information about the type state change to {@code os},
+/// Write information about the type state change to @c os,
/// return whether the note should be generated.
static bool shouldGenerateNote(llvm::raw_string_ostream &os,
const RefVal *PrevT,
@@ -164,8 +166,8 @@
return true;
}
-/// Finds argument index of the out paramter in the call {@code S}
-/// corresponding to the symbol {@code Sym}.
+/// Finds argument index of the out paramter in the call @c S
+/// corresponding to the symbol @c Sym.
/// If none found, returns None.
static Optional<unsigned> findArgIdxOfSymbol(ProgramStateRef CurrSt,
const LocationContext *LCtx,
@@ -337,11 +339,15 @@
class RefLeakReportVisitor : public RefCountReportVisitor {
public:
- RefLeakReportVisitor(SymbolRef sym) : RefCountReportVisitor(sym) {}
+ RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)
+ : RefCountReportVisitor(Sym), LastBinding(LastBinding) {}
PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
const ExplodedNode *N,
PathSensitiveBugReport &BR) override;
+
+private:
+ const MemRegion *LastBinding;
};
} // end namespace retaincountchecker
@@ -610,6 +616,41 @@
return None;
}
+using Bindings = llvm::SmallVector<std::pair<const MemRegion *, SVal>, 4>;
+
+class VarBindingsCollector : public StoreManager::BindingsHandler {
+ SymbolRef Sym;
+ Bindings &Result;
+
+public:
+ VarBindingsCollector(SymbolRef Sym, Bindings &ToFill)
+ : Sym(Sym), Result(ToFill) {}
+
+ bool HandleBinding(StoreManager &SMgr, Store Store, const MemRegion *R,
+ SVal Val) override {
+ SymbolRef SymV = Val.getAsLocSymbol();
+ if (!SymV || SymV != Sym)
+ return true;
+
+ if (isa<NonParamVarRegion>(R))
+ Result.emplace_back(R, Val);
+
+ return true;
+ }
+};
+
+Bindings getAllVarBindingsForSymbol(ProgramStateManager &Manager,
+ const ExplodedNode *Node, SymbolRef Sym) {
+ Bindings Result;
+ VarBindingsCollector Collector{Sym, Result};
+ while (Result.empty() && Node) {
+ Manager.iterBindings(Node->getState(), Collector);
+ Node = Node->getFirstPred();
+ }
+
+ return Result;
+}
+
namespace {
// Find the first node in the current function context that referred to the
// tracked symbol and the memory location that value was stored to. Note, the
@@ -729,14 +770,6 @@
// assigned to different variables, etc.
BR.markInteresting(Sym);
- // We are reporting a leak. Walk up the graph to get to the first node where
- // the symbol appeared, and also get the first VarDecl that tracked object
- // is stored to.
- AllocationInfo AllocI = GetAllocationSite(BRC.getStateManager(), EndN, Sym);
-
- const MemRegion* FirstBinding = AllocI.R;
- BR.markInteresting(AllocI.InterestingMethodContext);
-
PathDiagnosticLocation L = cast<RefLeakReport>(BR).getEndOfPath();
std::string sbuf;
@@ -744,7 +777,7 @@
os << "Object leaked: ";
- Optional<std::string> RegionDescription = describeRegion(FirstBinding);
+ Optional<std::string> RegionDescription = describeRegion(LastBinding);
if (RegionDescription) {
os << "object allocated and stored into '" << *RegionDescription << '\'';
} else {
@@ -753,7 +786,7 @@
}
// Get the retain count.
- const RefVal* RV = getRefBinding(EndN->getState(), Sym);
+ const RefVal *RV = getRefBinding(EndN->getState(), Sym);
assert(RV);
if (RV->getKind() == RefVal::ErrorLeakReturned) {
@@ -794,14 +827,15 @@
" Foundation";
} else if (RV->getObjKind() == ObjKind::OS) {
std::string FuncName = FD->getNameAsString();
- os << "whose name ('" << FuncName
- << "') starts with '" << StringRef(FuncName).substr(0, 3) << "'";
+ os << "whose name ('" << FuncName << "') starts with '"
+ << StringRef(FuncName).substr(0, 3) << "'";
}
}
}
} else {
os << " is not referenced later in this execution path and has a retain "
- "count of +" << RV->getCount();
+ "count of +"
+ << RV->getCount();
}
return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
@@ -812,7 +846,7 @@
: PathSensitiveBugReport(D, D.getDescription(), n), Sym(sym),
isLeak(isLeak) {
if (!isLeak)
- addVisitor(std::make_unique<RefCountReportVisitor>(sym));
+ addVisitor<RefCountReportVisitor>(sym);
}
RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts,
@@ -820,19 +854,19 @@
StringRef endText)
: PathSensitiveBugReport(D, D.getDescription(), endText, n) {
- addVisitor(std::make_unique<RefCountReportVisitor>(sym));
+ addVisitor<RefCountReportVisitor>(sym);
}
-void RefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
- const SourceManager& SMgr = Ctx.getSourceManager();
+void RefLeakReport::deriveParamLocation(CheckerContext &Ctx) {
+ const SourceManager &SMgr = Ctx.getSourceManager();
- if (!sym->getOriginRegion())
+ if (!Sym->getOriginRegion())
return;
- auto *Region = dyn_cast<DeclRegion>(sym->getOriginRegion());
+ auto *Region = dyn_cast<DeclRegion>(Sym->getOriginRegion());
if (Region) {
const Decl *PDecl = Region->getDecl();
- if (PDecl && isa<ParmVarDecl>(PDecl)) {
+ if (isa_and_nonnull<ParmVarDecl>(PDecl)) {
PathDiagnosticLocation ParamLocation =
PathDiagnosticLocation::create(PDecl, SMgr);
Location = ParamLocation;
@@ -842,8 +876,7 @@
}
}
-void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx,
- SymbolRef sym) {
+void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx) {
// Most bug reports are cached at the location where they occurred.
// With leaks, we want to unique them by the location where they were
// allocated, and only report a single path. To do this, we need to find
@@ -854,13 +887,13 @@
// same SourceLocation.
const ExplodedNode *AllocNode = nullptr;
- const SourceManager& SMgr = Ctx.getSourceManager();
+ const SourceManager &SMgr = Ctx.getSourceManager();
AllocationInfo AllocI =
- GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
+ GetAllocationSite(Ctx.getStateManager(), getErrorNode(), Sym);
AllocNode = AllocI.N;
- AllocBinding = AllocI.R;
+ AllocFirstBinding = AllocI.R;
markInteresting(AllocI.InterestingMethodContext);
// Get the SourceLocation for the allocation site.
@@ -870,13 +903,12 @@
AllocStmt = AllocNode->getStmtForDiagnostics();
if (!AllocStmt) {
- AllocBinding = nullptr;
+ AllocFirstBinding = nullptr;
return;
}
- PathDiagnosticLocation AllocLocation =
- PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
- AllocNode->getLocationContext());
+ PathDiagnosticLocation AllocLocation = PathDiagnosticLocation::createBegin(
+ AllocStmt, SMgr, AllocNode->getLocationContext());
Location = AllocLocation;
// Set uniqieing info, which will be used for unique the bug reports. The
@@ -891,7 +923,8 @@
llvm::raw_string_ostream os(Description);
os << "Potential leak of an object";
- Optional<std::string> RegionDescription = describeRegion(AllocBinding);
+ Optional<std::string> RegionDescription =
+ describeRegion(AllocBindingToReport);
if (RegionDescription) {
os << " stored into '" << *RegionDescription << '\'';
} else {
@@ -901,16 +934,75 @@
}
}
-RefLeakReport::RefLeakReport(const RefCountBug &D, const LangOptions &LOpts,
- ExplodedNode *n, SymbolRef sym,
- CheckerContext &Ctx)
- : RefCountReport(D, LOpts, n, sym, /*isLeak=*/true) {
+void RefLeakReport::findBindingToReport(CheckerContext &Ctx,
+ ExplodedNode *Node) {
+ if (!AllocFirstBinding)
+ // If we don't have any bindings, we won't be able to find any
+ // better binding to report.
+ return;
- deriveAllocLocation(Ctx, sym);
- if (!AllocBinding)
- deriveParamLocation(Ctx, sym);
+ // If the original region still contains the leaking symbol...
+ if (Node->getState()->getSVal(AllocFirstBinding).getAsSymbol() == Sym) {
+ // ...it is the best binding to report.
+ AllocBindingToReport = AllocFirstBinding;
+ return;
+ }
+
+ // At this point, we know that the original region doesn't contain the leaking
+ // when the actual leak happens. It means that it can be confusing for the
+ // user to see such description in the message.
+ //
+ // Let's consider the following example:
+ // Object *Original = allocate(...);
+ // Object *New = Original;
+ // Original = allocate(...);
+ // Original->release();
+ //
+ // Complaining about a leaking object "stored into Original" might cause a
+ // rightful confusion because 'Original' is actually released.
+ // We should complain about 'New' instead.
+ Bindings AllVarBindings =
+ getAllVarBindingsForSymbol(Ctx.getStateManager(), Node, Sym);
+
+ // While looking for the last var bindings, we can still find
+ // `AllocFirstBinding` to be one of them. In situations like this,
+ // it would still be the easiest case to explain to our users.
+ if (!AllVarBindings.empty() &&
+ llvm::count_if(AllVarBindings,
+ [this](const std::pair<const MemRegion *, SVal> Binding) {
+ return Binding.first == AllocFirstBinding;
+ }) == 0) {
+ // Let's pick one of them at random (if there is something to pick from).
+ AllocBindingToReport = AllVarBindings[0].first;
+
+ // Because 'AllocBindingToReport' is not the the same as
+ // 'AllocFirstBinding', we need to explain how the leaking object
+ // got from one to another.
+ //
+ // NOTE: We use the actual SVal stored in AllocBindingToReport here because
+ // trackStoredValue compares SVal's and it can get trickier for
+ // something like derived regions if we want to construct SVal from
+ // Sym. Instead, we take the value that is definitely stored in that
+ // region, thus guaranteeing that trackStoredValue will work.
+ bugreporter::trackStoredValue(AllVarBindings[0].second.castAs<KnownSVal>(),
+ AllocBindingToReport, *this);
+ } else {
+ AllocBindingToReport = AllocFirstBinding;
+ }
+}
+
+RefLeakReport::RefLeakReport(const RefCountBug &D, const LangOptions &LOpts,
+ ExplodedNode *N, SymbolRef Sym,
+ CheckerContext &Ctx)
+ : RefCountReport(D, LOpts, N, Sym, /*isLeak=*/true) {
+
+ deriveAllocLocation(Ctx);
+ findBindingToReport(Ctx, N);
+
+ if (!AllocFirstBinding)
+ deriveParamLocation(Ctx);
createDescription(Ctx);
- addVisitor(std::make_unique<RefLeakReportVisitor>(sym));
+ addVisitor<RefLeakReportVisitor>(Sym, AllocBindingToReport);
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
index 286a8ae..d059008 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
@@ -68,17 +68,20 @@
};
class RefLeakReport : public RefCountReport {
- const MemRegion* AllocBinding;
- const Stmt *AllocStmt;
+ const MemRegion *AllocFirstBinding = nullptr;
+ const MemRegion *AllocBindingToReport = nullptr;
+ const Stmt *AllocStmt = nullptr;
PathDiagnosticLocation Location;
// Finds the function declaration where a leak warning for the parameter
// 'sym' should be raised.
- void deriveParamLocation(CheckerContext &Ctx, SymbolRef sym);
- // Finds the location where a leak warning for 'sym' should be raised.
- void deriveAllocLocation(CheckerContext &Ctx, SymbolRef sym);
+ void deriveParamLocation(CheckerContext &Ctx);
+ // Finds the location where the leaking object is allocated.
+ void deriveAllocLocation(CheckerContext &Ctx);
// Produces description of a leak warning which is printed on the console.
void createDescription(CheckerContext &Ctx);
+ // Finds the binding that we should use in a leak warning.
+ void findBindingToReport(CheckerContext &Ctx, ExplodedNode *Node);
public:
RefLeakReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n,
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index 1a94ccd..8857502 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -16,7 +16,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
using namespace clang;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
index d9dc72d..2cf6c6f 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp
@@ -57,8 +57,8 @@
} // end anonymous namespace
-/// \return Whether {@code A} occurs before {@code B} in traversal of
-/// {@code Parent}.
+/// \return Whether @c A occurs before @c B in traversal of
+/// @c Parent.
/// Conceptually a very incomplete/unsound approximation of happens-before
/// relationship (A is likely to be evaluated before B),
/// but useful enough in this case.
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
index 92c386b..6a40f8e 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h
@@ -22,6 +22,10 @@
/// Returns true if the event call is on smart pointer.
bool isStdSmartPtrCall(const CallEvent &Call);
+bool isStdSmartPtr(const CXXRecordDecl *RD);
+bool isStdSmartPtr(const Expr *E);
+
+bool isStdSmartPtr(const CXXRecordDecl *RD);
/// Returns whether the smart pointer is null or not.
bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion);
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
index 6ee7bd9..09e885e 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -25,16 +25,20 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
#include <string>
using namespace clang;
using namespace ento;
namespace {
+
class SmartPtrModeling
: public Checker<eval::Call, check::DeadSymbols, check::RegionChanges,
check::LiveSymbols> {
@@ -60,7 +64,7 @@
private:
void handleReset(const CallEvent &Call, CheckerContext &C) const;
void handleRelease(const CallEvent &Call, CheckerContext &C) const;
- void handleSwap(const CallEvent &Call, CheckerContext &C) const;
+ void handleSwapMethod(const CallEvent &Call, CheckerContext &C) const;
void handleGet(const CallEvent &Call, CheckerContext &C) const;
bool handleAssignOp(const CallEvent &Call, CheckerContext &C) const;
bool handleMoveCtr(const CallEvent &Call, CheckerContext &C,
@@ -68,19 +72,56 @@
bool updateMovedSmartPointers(CheckerContext &C, const MemRegion *ThisRegion,
const MemRegion *OtherSmartPtrRegion) const;
void handleBoolConversion(const CallEvent &Call, CheckerContext &C) const;
+ bool handleComparisionOp(const CallEvent &Call, CheckerContext &C) const;
+ bool handleOstreamOperator(const CallEvent &Call, CheckerContext &C) const;
+ bool handleSwap(ProgramStateRef State, SVal First, SVal Second,
+ CheckerContext &C) const;
+ std::pair<SVal, ProgramStateRef>
+ retrieveOrConjureInnerPtrVal(ProgramStateRef State,
+ const MemRegion *ThisRegion, const Expr *E,
+ QualType Type, CheckerContext &C) const;
using SmartPtrMethodHandlerFn =
void (SmartPtrModeling::*)(const CallEvent &Call, CheckerContext &) const;
CallDescriptionMap<SmartPtrMethodHandlerFn> SmartPtrMethodHandlers{
{{"reset"}, &SmartPtrModeling::handleReset},
{{"release"}, &SmartPtrModeling::handleRelease},
- {{"swap", 1}, &SmartPtrModeling::handleSwap},
+ {{"swap", 1}, &SmartPtrModeling::handleSwapMethod},
{{"get"}, &SmartPtrModeling::handleGet}};
+ const CallDescription StdSwapCall{{"std", "swap"}, 2};
+ const CallDescription StdMakeUniqueCall{{"std", "make_unique"}};
+ const CallDescription StdMakeUniqueForOverwriteCall{
+ {"std", "make_unique_for_overwrite"}};
};
} // end of anonymous namespace
REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, SVal)
+// Checks if RD has name in Names and is in std namespace
+static bool hasStdClassWithName(const CXXRecordDecl *RD,
+ ArrayRef<llvm::StringLiteral> Names) {
+ if (!RD || !RD->getDeclContext()->isStdNamespace())
+ return false;
+ if (RD->getDeclName().isIdentifier()) {
+ StringRef Name = RD->getName();
+ return llvm::any_of(Names, [&Name](StringRef GivenName) -> bool {
+ return Name == GivenName;
+ });
+ }
+ return false;
+}
+
+constexpr llvm::StringLiteral STD_PTR_NAMES[] = {"shared_ptr", "unique_ptr",
+ "weak_ptr"};
+
+static bool isStdSmartPtr(const CXXRecordDecl *RD) {
+ return hasStdClassWithName(RD, STD_PTR_NAMES);
+}
+
+static bool isStdSmartPtr(const Expr *E) {
+ return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
+}
+
// Define the inter-checker API.
namespace clang {
namespace ento {
@@ -89,18 +130,24 @@
const auto *MethodDecl = dyn_cast_or_null<CXXMethodDecl>(Call.getDecl());
if (!MethodDecl || !MethodDecl->getParent())
return false;
+ return isStdSmartPtr(MethodDecl->getParent());
+}
- const auto *RecordDecl = MethodDecl->getParent();
- if (!RecordDecl || !RecordDecl->getDeclContext()->isStdNamespace())
+bool isStdSmartPtr(const CXXRecordDecl *RD) {
+ if (!RD || !RD->getDeclContext()->isStdNamespace())
return false;
- if (RecordDecl->getDeclName().isIdentifier()) {
- StringRef Name = RecordDecl->getName();
+ if (RD->getDeclName().isIdentifier()) {
+ StringRef Name = RD->getName();
return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr";
}
return false;
}
+bool isStdSmartPtr(const Expr *E) {
+ return isStdSmartPtr(E->getType()->getAsCXXRecordDecl());
+}
+
bool isNullSmartPtr(const ProgramStateRef State, const MemRegion *ThisRegion) {
const auto *InnerPointVal = State->get<TrackedRegionMap>(ThisRegion);
return InnerPointVal &&
@@ -135,6 +182,36 @@
return State;
}
+static QualType getInnerPointerType(CheckerContext C, const CXXRecordDecl *RD) {
+ if (!RD || !RD->isInStdNamespace())
+ return {};
+
+ const auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
+ if (!TSD)
+ return {};
+
+ auto TemplateArgs = TSD->getTemplateArgs().asArray();
+ if (TemplateArgs.empty())
+ return {};
+ auto InnerValueType = TemplateArgs[0].getAsType();
+ return C.getASTContext().getPointerType(InnerValueType.getCanonicalType());
+}
+
+// This is for use with standalone-functions like std::make_unique,
+// std::make_unique_for_overwrite, etc. It reads the template parameter and
+// returns the pointer type corresponding to it,
+static QualType getPointerTypeFromTemplateArg(const CallEvent &Call,
+ CheckerContext &C) {
+ const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
+ if (!FD || !FD->isFunctionTemplateSpecialization())
+ return {};
+ const auto &TemplateArgs = FD->getTemplateSpecializationArgs()->asArray();
+ if (TemplateArgs.size() == 0)
+ return {};
+ auto ValueType = TemplateArgs[0].getAsType();
+ return C.getASTContext().getPointerType(ValueType.getCanonicalType());
+}
+
// Helper method to get the inner pointer type of specialized smart pointer
// Returns empty type if not found valid inner pointer type.
static QualType getInnerPointerType(const CallEvent &Call, CheckerContext &C) {
@@ -143,18 +220,7 @@
return {};
const auto *RecordDecl = MethodDecl->getParent();
- if (!RecordDecl || !RecordDecl->isInStdNamespace())
- return {};
-
- const auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
- if (!TSD)
- return {};
-
- auto TemplateArgs = TSD->getTemplateArgs().asArray();
- if (TemplateArgs.size() == 0)
- return {};
- auto InnerValueType = TemplateArgs[0].getAsType();
- return C.getASTContext().getPointerType(InnerValueType.getCanonicalType());
+ return getInnerPointerType(C, RecordDecl);
}
// Helper method to pretty print region and avoid extra spacing.
@@ -175,9 +241,107 @@
return CD && CD->getConversionType()->isBooleanType();
}
+constexpr llvm::StringLiteral BASIC_OSTREAM_NAMES[] = {"basic_ostream"};
+
+bool isStdBasicOstream(const Expr *E) {
+ const auto *RD = E->getType()->getAsCXXRecordDecl();
+ return hasStdClassWithName(RD, BASIC_OSTREAM_NAMES);
+}
+
+static bool isStdFunctionCall(const CallEvent &Call) {
+ return Call.getDecl() && Call.getDecl()->getDeclContext()->isStdNamespace();
+}
+
+bool isStdOstreamOperatorCall(const CallEvent &Call) {
+ if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+ return false;
+ const auto *FC = dyn_cast<SimpleFunctionCall>(&Call);
+ if (!FC)
+ return false;
+ const FunctionDecl *FD = FC->getDecl();
+ if (!FD->isOverloadedOperator())
+ return false;
+ const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
+ if (OOK != clang::OO_LessLess)
+ return false;
+ return isStdSmartPtr(Call.getArgExpr(1)) &&
+ isStdBasicOstream(Call.getArgExpr(0));
+}
+
+static bool isPotentiallyComparisionOpCall(const CallEvent &Call) {
+ if (Call.getNumArgs() != 2 || !isStdFunctionCall(Call))
+ return false;
+ return smartptr::isStdSmartPtr(Call.getArgExpr(0)) ||
+ smartptr::isStdSmartPtr(Call.getArgExpr(1));
+}
+
bool SmartPtrModeling::evalCall(const CallEvent &Call,
CheckerContext &C) const {
+
ProgramStateRef State = C.getState();
+
+ // If any one of the arg is a unique_ptr, then
+ // we can try this function
+ if (ModelSmartPtrDereference && isPotentiallyComparisionOpCall(Call))
+ if (handleComparisionOp(Call, C))
+ return true;
+
+ if (ModelSmartPtrDereference && isStdOstreamOperatorCall(Call))
+ return handleOstreamOperator(Call, C);
+
+ if (Call.isCalled(StdSwapCall)) {
+ // Check the first arg, if it is of std::unique_ptr type.
+ assert(Call.getNumArgs() == 2 && "std::swap should have two arguments");
+ const Expr *FirstArg = Call.getArgExpr(0);
+ if (!smartptr::isStdSmartPtr(FirstArg->getType()->getAsCXXRecordDecl()))
+ return false;
+ return handleSwap(State, Call.getArgSVal(0), Call.getArgSVal(1), C);
+ }
+
+ if (Call.isCalled(StdMakeUniqueCall) ||
+ Call.isCalled(StdMakeUniqueForOverwriteCall)) {
+ if (!ModelSmartPtrDereference)
+ return false;
+
+ const Optional<SVal> ThisRegionOpt = Call.getReturnValueUnderConstruction();
+ if (!ThisRegionOpt)
+ return false;
+
+ const auto PtrVal = C.getSValBuilder().getConjuredHeapSymbolVal(
+ Call.getOriginExpr(), C.getLocationContext(),
+ getPointerTypeFromTemplateArg(Call, C), C.blockCount());
+
+ const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
+ State = State->set<TrackedRegionMap>(ThisRegion, PtrVal);
+ State = State->assume(PtrVal, true);
+
+ // TODO: ExprEngine should do this for us.
+ // For a bit more context:
+ // 1) Why do we need this? Since we are modelling a "function"
+ // that returns a constructed object we need to store this information in
+ // the program state.
+ //
+ // 2) Why does this work?
+ // `updateObjectsUnderConstruction` does exactly as it sounds.
+ //
+ // 3) How should it look like when moved to the Engine?
+ // It would be nice if we can just
+ // pretend we don't need to know about this - ie, completely automatic work.
+ // However, realistically speaking, I think we would need to "signal" the
+ // ExprEngine evalCall handler that we are constructing an object with this
+ // function call (constructors obviously construct, hence can be
+ // automatically deduced).
+ auto &Engine = State->getStateManager().getOwningEngine();
+ State = Engine.updateObjectsUnderConstruction(
+ *ThisRegionOpt, nullptr, State, C.getLocationContext(),
+ Call.getConstructionContext(), {});
+
+ // We don't leave a note here since it is guaranteed the
+ // unique_ptr from this call is non-null (hence is safe to de-reference).
+ C.addTransition(State);
+ return true;
+ }
+
if (!smartptr::isStdSmartPtrCall(Call))
return false;
@@ -272,6 +436,108 @@
return C.isDifferent();
}
+std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(
+ ProgramStateRef State, const MemRegion *ThisRegion, const Expr *E,
+ QualType Type, CheckerContext &C) const {
+ const auto *Ptr = State->get<TrackedRegionMap>(ThisRegion);
+ if (Ptr)
+ return {*Ptr, State};
+ auto Val = C.getSValBuilder().conjureSymbolVal(E, C.getLocationContext(),
+ Type, C.blockCount());
+ State = State->set<TrackedRegionMap>(ThisRegion, Val);
+ return {Val, State};
+}
+
+bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
+ CheckerContext &C) const {
+ const auto *FC = dyn_cast<SimpleFunctionCall>(&Call);
+ if (!FC)
+ return false;
+ const FunctionDecl *FD = FC->getDecl();
+ if (!FD->isOverloadedOperator())
+ return false;
+ const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
+ if (!(OOK == OO_EqualEqual || OOK == OO_ExclaimEqual || OOK == OO_Less ||
+ OOK == OO_LessEqual || OOK == OO_Greater || OOK == OO_GreaterEqual ||
+ OOK == OO_Spaceship))
+ return false;
+
+ // There are some special cases about which we can infer about
+ // the resulting answer.
+ // For reference, there is a discussion at https://reviews.llvm.org/D104616.
+ // Also, the cppreference page is good to look at
+ // https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_cmp.
+
+ auto makeSValFor = [&C, this](ProgramStateRef State, const Expr *E,
+ SVal S) -> std::pair<SVal, ProgramStateRef> {
+ if (S.isZeroConstant()) {
+ return {S, State};
+ }
+ const MemRegion *Reg = S.getAsRegion();
+ assert(Reg &&
+ "this pointer of std::unique_ptr should be obtainable as MemRegion");
+ QualType Type = getInnerPointerType(C, E->getType()->getAsCXXRecordDecl());
+ return retrieveOrConjureInnerPtrVal(State, Reg, E, Type, C);
+ };
+
+ SVal First = Call.getArgSVal(0);
+ SVal Second = Call.getArgSVal(1);
+ const auto *FirstExpr = Call.getArgExpr(0);
+ const auto *SecondExpr = Call.getArgExpr(1);
+
+ const auto *ResultExpr = Call.getOriginExpr();
+ const auto *LCtx = C.getLocationContext();
+ auto &Bldr = C.getSValBuilder();
+ ProgramStateRef State = C.getState();
+
+ SVal FirstPtrVal, SecondPtrVal;
+ std::tie(FirstPtrVal, State) = makeSValFor(State, FirstExpr, First);
+ std::tie(SecondPtrVal, State) = makeSValFor(State, SecondExpr, Second);
+ BinaryOperatorKind BOK =
+ operationKindFromOverloadedOperator(OOK, true).GetBinaryOpUnsafe();
+ auto RetVal = Bldr.evalBinOp(State, BOK, FirstPtrVal, SecondPtrVal,
+ Call.getResultType());
+
+ if (OOK != OO_Spaceship) {
+ ProgramStateRef TrueState, FalseState;
+ std::tie(TrueState, FalseState) =
+ State->assume(*RetVal.getAs<DefinedOrUnknownSVal>());
+ if (TrueState)
+ C.addTransition(
+ TrueState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(true)));
+ if (FalseState)
+ C.addTransition(
+ FalseState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(false)));
+ } else {
+ C.addTransition(State->BindExpr(ResultExpr, LCtx, RetVal));
+ }
+ return true;
+}
+
+bool SmartPtrModeling::handleOstreamOperator(const CallEvent &Call,
+ CheckerContext &C) const {
+ // operator<< does not modify the smart pointer.
+ // And we don't really have much of modelling of basic_ostream.
+ // So, we are better off:
+ // 1) Invalidating the mem-region of the ostream object at hand.
+ // 2) Setting the SVal of the basic_ostream as the return value.
+ // Not very satisfying, but it gets the job done, and is better
+ // than the default handling. :)
+
+ ProgramStateRef State = C.getState();
+ const auto StreamVal = Call.getArgSVal(0);
+ const MemRegion *StreamThisRegion = StreamVal.getAsRegion();
+ if (!StreamThisRegion)
+ return false;
+ State =
+ State->invalidateRegions({StreamThisRegion}, Call.getOriginExpr(),
+ C.blockCount(), C.getLocationContext(), false);
+ State =
+ State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), StreamVal);
+ C.addTransition(State);
+ return true;
+}
+
void SmartPtrModeling::checkDeadSymbols(SymbolReaper &SymReaper,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
@@ -395,43 +661,52 @@
// pointer.
}
-void SmartPtrModeling::handleSwap(const CallEvent &Call,
- CheckerContext &C) const {
+void SmartPtrModeling::handleSwapMethod(const CallEvent &Call,
+ CheckerContext &C) const {
// To model unique_ptr::swap() method.
const auto *IC = dyn_cast<CXXInstanceCall>(&Call);
if (!IC)
return;
- const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
- if (!ThisRegion)
- return;
-
- const auto *ArgRegion = Call.getArgSVal(0).getAsRegion();
- if (!ArgRegion)
- return;
-
auto State = C.getState();
- const auto *ThisRegionInnerPointerVal =
- State->get<TrackedRegionMap>(ThisRegion);
- const auto *ArgRegionInnerPointerVal =
- State->get<TrackedRegionMap>(ArgRegion);
+ handleSwap(State, IC->getCXXThisVal(), Call.getArgSVal(0), C);
+}
- // Swap the tracked region values.
- State = updateSwappedRegion(State, ThisRegion, ArgRegionInnerPointerVal);
- State = updateSwappedRegion(State, ArgRegion, ThisRegionInnerPointerVal);
+bool SmartPtrModeling::handleSwap(ProgramStateRef State, SVal First,
+ SVal Second, CheckerContext &C) const {
+ const MemRegion *FirstThisRegion = First.getAsRegion();
+ if (!FirstThisRegion)
+ return false;
+ const MemRegion *SecondThisRegion = Second.getAsRegion();
+ if (!SecondThisRegion)
+ return false;
- C.addTransition(
- State, C.getNoteTag([ThisRegion, ArgRegion](PathSensitiveBugReport &BR,
- llvm::raw_ostream &OS) {
- if (&BR.getBugType() != smartptr::getNullDereferenceBugType() ||
- !BR.isInteresting(ThisRegion))
- return;
- BR.markInteresting(ArgRegion);
- OS << "Swapped null smart pointer";
- checkAndPrettyPrintRegion(OS, ArgRegion);
- OS << " with smart pointer";
- checkAndPrettyPrintRegion(OS, ThisRegion);
- }));
+ const auto *FirstInnerPtrVal = State->get<TrackedRegionMap>(FirstThisRegion);
+ const auto *SecondInnerPtrVal =
+ State->get<TrackedRegionMap>(SecondThisRegion);
+
+ State = updateSwappedRegion(State, FirstThisRegion, SecondInnerPtrVal);
+ State = updateSwappedRegion(State, SecondThisRegion, FirstInnerPtrVal);
+
+ C.addTransition(State, C.getNoteTag([FirstThisRegion, SecondThisRegion](
+ PathSensitiveBugReport &BR,
+ llvm::raw_ostream &OS) {
+ if (&BR.getBugType() != smartptr::getNullDereferenceBugType())
+ return;
+ if (BR.isInteresting(FirstThisRegion) &&
+ !BR.isInteresting(SecondThisRegion)) {
+ BR.markInteresting(SecondThisRegion);
+ BR.markNotInteresting(FirstThisRegion);
+ }
+ if (BR.isInteresting(SecondThisRegion) &&
+ !BR.isInteresting(FirstThisRegion)) {
+ BR.markInteresting(FirstThisRegion);
+ BR.markNotInteresting(SecondThisRegion);
+ }
+ // TODO: We need to emit some note here probably!!
+ }));
+
+ return true;
}
void SmartPtrModeling::handleGet(const CallEvent &Call,
@@ -446,15 +721,8 @@
return;
SVal InnerPointerVal;
- if (const auto *InnerValPtr = State->get<TrackedRegionMap>(ThisRegion)) {
- InnerPointerVal = *InnerValPtr;
- } else {
- const auto *CallExpr = Call.getOriginExpr();
- InnerPointerVal = C.getSValBuilder().conjureSymbolVal(
- CallExpr, C.getLocationContext(), Call.getResultType(), C.blockCount());
- State = State->set<TrackedRegionMap>(ThisRegion, InnerPointerVal);
- }
-
+ std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal(
+ State, ThisRegion, Call.getOriginExpr(), Call.getResultType(), C);
State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
InnerPointerVal);
// TODO: Add NoteTag, for how the raw pointer got using 'get' method.
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index d1c366a..e758b46 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -56,7 +56,11 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+
+#include <string>
using namespace clang;
using namespace clang::ento;
@@ -87,6 +91,10 @@
typedef uint32_t ArgNo;
static const ArgNo Ret;
+ /// Returns the string representation of an argument index.
+ /// E.g.: (1) -> '1st arg', (2) - > '2nd arg'
+ static SmallString<8> getArgDesc(ArgNo);
+
class ValueConstraint;
// Pointer to the ValueConstraint. We need a copyable, polymorphic and
@@ -126,8 +134,24 @@
}
ArgNo getArgNo() const { return ArgN; }
+ // Return those arguments that should be tracked when we report a bug. By
+ // default it is the argument that is constrained, however, in some special
+ // cases we need to track other arguments as well. E.g. a buffer size might
+ // be encoded in another argument.
+ virtual std::vector<ArgNo> getArgsToTrack() const { return {ArgN}; }
+
virtual StringRef getName() const = 0;
+ // Give a description that explains the constraint to the user. Used when
+ // the bug is reported.
+ virtual std::string describe(ProgramStateRef State,
+ const Summary &Summary) const {
+ // There are some descendant classes that are not used as argument
+ // constraints, e.g. ComparisonConstraint. In that case we can safely
+ // ignore the implementation of this function.
+ llvm_unreachable("Not implemented");
+ }
+
protected:
ArgNo ArgN; // Argument to which we apply the constraint.
@@ -158,6 +182,9 @@
RangeConstraint(ArgNo ArgN, RangeKind Kind, const IntRangeVector &Ranges)
: ValueConstraint(ArgN), Kind(Kind), Ranges(Ranges) {}
+ std::string describe(ProgramStateRef State,
+ const Summary &Summary) const override;
+
const IntRangeVector &getRanges() const { return Ranges; }
private:
@@ -225,6 +252,8 @@
bool CannotBeNull = true;
public:
+ std::string describe(ProgramStateRef State,
+ const Summary &Summary) const override;
StringRef getName() const override { return "NonNull"; }
ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
const Summary &Summary,
@@ -286,6 +315,18 @@
: ValueConstraint(Buffer), SizeArgN(BufSize),
SizeMultiplierArgN(BufSizeMultiplier) {}
+ std::vector<ArgNo> getArgsToTrack() const override {
+ std::vector<ArgNo> Result{ArgN};
+ if (SizeArgN)
+ Result.push_back(*SizeArgN);
+ if (SizeMultiplierArgN)
+ Result.push_back(*SizeMultiplierArgN);
+ return Result;
+ }
+
+ std::string describe(ProgramStateRef State,
+ const Summary &Summary) const override;
+
ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
const Summary &Summary,
CheckerContext &C) const override {
@@ -297,24 +338,22 @@
const SVal SizeV = [this, &State, &Call, &Summary, &SvalBuilder]() {
if (ConcreteSize) {
return SVal(SvalBuilder.makeIntVal(*ConcreteSize));
- } else if (SizeArgN) {
- // The size argument.
- SVal SizeV = getArgSVal(Call, *SizeArgN);
- // Multiply with another argument if given.
- if (SizeMultiplierArgN) {
- SVal SizeMulV = getArgSVal(Call, *SizeMultiplierArgN);
- SizeV = SvalBuilder.evalBinOp(State, BO_Mul, SizeV, SizeMulV,
- Summary.getArgType(*SizeArgN));
- }
- return SizeV;
- } else {
- llvm_unreachable("The constraint must be either a concrete value or "
- "encoded in an arguement.");
}
+ assert(SizeArgN && "The constraint must be either a concrete value or "
+ "encoded in an argument.");
+ // The size argument.
+ SVal SizeV = getArgSVal(Call, *SizeArgN);
+ // Multiply with another argument if given.
+ if (SizeMultiplierArgN) {
+ SVal SizeMulV = getArgSVal(Call, *SizeMultiplierArgN);
+ SizeV = SvalBuilder.evalBinOp(State, BO_Mul, SizeV, SizeMulV,
+ Summary.getArgType(*SizeArgN));
+ }
+ return SizeV;
}();
// The dynamic size of the buffer argument, got from the analyzer engine.
- SVal BufDynSize = getDynamicSizeWithOffset(State, BufV);
+ SVal BufDynSize = getDynamicExtentWithOffset(State, BufV);
SVal Feasible = SvalBuilder.evalBinOp(State, Op, SizeV, BufDynSize,
SvalBuilder.getContext().BoolTy);
@@ -508,6 +547,7 @@
mutable FunctionSummaryMapType FunctionSummaryMap;
mutable std::unique_ptr<BugType> BT_InvalidArg;
+ mutable bool SummariesInitialized = false;
static SVal getArgSVal(const CallEvent &Call, ArgNo ArgN) {
return ArgN == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgN);
@@ -538,24 +578,30 @@
void initFunctionSummaries(CheckerContext &C) const;
void reportBug(const CallEvent &Call, ExplodedNode *N,
- const ValueConstraint *VC, CheckerContext &C) const {
+ const ValueConstraint *VC, const Summary &Summary,
+ CheckerContext &C) const {
if (!ChecksEnabled[CK_StdCLibraryFunctionArgsChecker])
return;
- // TODO Add more detailed diagnostic.
std::string Msg =
(Twine("Function argument constraint is not satisfied, constraint: ") +
- VC->getName().data() + ", ArgN: " + Twine(VC->getArgNo()))
+ VC->getName().data())
.str();
if (!BT_InvalidArg)
BT_InvalidArg = std::make_unique<BugType>(
CheckNames[CK_StdCLibraryFunctionArgsChecker],
"Unsatisfied argument constraints", categories::LogicError);
auto R = std::make_unique<PathSensitiveBugReport>(*BT_InvalidArg, Msg, N);
- bugreporter::trackExpressionValue(N, Call.getArgExpr(VC->getArgNo()), *R);
+
+ for (ArgNo ArgN : VC->getArgsToTrack())
+ bugreporter::trackExpressionValue(N, Call.getArgExpr(ArgN), *R);
// Highlight the range of the argument that was violated.
R->addRange(Call.getArgSourceRange(VC->getArgNo()));
+ // Describe the argument constraint in a note.
+ R->addNote(VC->describe(C.getState(), Summary), R->getLocation(),
+ Call.getArgSourceRange(VC->getArgNo()));
+
C.emitReport(std::move(R));
}
};
@@ -565,6 +611,85 @@
} // end of anonymous namespace
+static BasicValueFactory &getBVF(ProgramStateRef State) {
+ ProgramStateManager &Mgr = State->getStateManager();
+ SValBuilder &SVB = Mgr.getSValBuilder();
+ return SVB.getBasicValueFactory();
+}
+
+std::string StdLibraryFunctionsChecker::NotNullConstraint::describe(
+ ProgramStateRef State, const Summary &Summary) const {
+ SmallString<48> Result;
+ Result += "The ";
+ Result += getArgDesc(ArgN);
+ Result += " should not be NULL";
+ return Result.c_str();
+}
+
+std::string StdLibraryFunctionsChecker::RangeConstraint::describe(
+ ProgramStateRef State, const Summary &Summary) const {
+
+ BasicValueFactory &BVF = getBVF(State);
+
+ QualType T = Summary.getArgType(getArgNo());
+ SmallString<48> Result;
+ Result += "The ";
+ Result += getArgDesc(ArgN);
+ Result += " should be ";
+
+ // Range kind as a string.
+ Kind == OutOfRange ? Result += "out of" : Result += "within";
+
+ // Get the range values as a string.
+ Result += " the range ";
+ if (Ranges.size() > 1)
+ Result += "[";
+ unsigned I = Ranges.size();
+ for (const std::pair<RangeInt, RangeInt> &R : Ranges) {
+ Result += "[";
+ const llvm::APSInt &Min = BVF.getValue(R.first, T);
+ const llvm::APSInt &Max = BVF.getValue(R.second, T);
+ Min.toString(Result);
+ Result += ", ";
+ Max.toString(Result);
+ Result += "]";
+ if (--I > 0)
+ Result += ", ";
+ }
+ if (Ranges.size() > 1)
+ Result += "]";
+
+ return Result.c_str();
+}
+
+SmallString<8>
+StdLibraryFunctionsChecker::getArgDesc(StdLibraryFunctionsChecker::ArgNo ArgN) {
+ SmallString<8> Result;
+ Result += std::to_string(ArgN + 1);
+ Result += llvm::getOrdinalSuffix(ArgN + 1);
+ Result += " arg";
+ return Result;
+}
+
+std::string StdLibraryFunctionsChecker::BufferSizeConstraint::describe(
+ ProgramStateRef State, const Summary &Summary) const {
+ SmallString<96> Result;
+ Result += "The size of the ";
+ Result += getArgDesc(ArgN);
+ Result += " should be equal to or less than the value of ";
+ if (ConcreteSize) {
+ ConcreteSize->toString(Result);
+ } else if (SizeArgN) {
+ Result += "the ";
+ Result += getArgDesc(*SizeArgN);
+ if (SizeMultiplierArgN) {
+ Result += " times the ";
+ Result += getArgDesc(*SizeMultiplierArgN);
+ }
+ }
+ return Result.c_str();
+}
+
ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsOutOfRange(
ProgramStateRef State, const CallEvent &Call,
const Summary &Summary) const {
@@ -692,7 +817,7 @@
// The argument constraint is not satisfied.
if (FailureSt && !SuccessSt) {
if (ExplodedNode *N = C.generateErrorNode(NewState))
- reportBug(Call, N, Constraint.get(), C);
+ reportBug(Call, N, Constraint.get(), Summary, C);
break;
} else {
// We will apply the constraint even if we cannot reason about the
@@ -823,7 +948,7 @@
void StdLibraryFunctionsChecker::initFunctionSummaries(
CheckerContext &C) const {
- if (!FunctionSummaryMap.empty())
+ if (SummariesInitialized)
return;
SValBuilder &SVB = C.getSValBuilder();
@@ -841,7 +966,7 @@
llvm::Optional<QualType> operator()(StringRef Name) {
IdentifierInfo &II = ACtx.Idents.get(Name);
auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
- if (LookupRes.size() == 0)
+ if (LookupRes.empty())
return None;
// Prioritze typedef declarations.
@@ -993,7 +1118,7 @@
return false;
IdentifierInfo &II = ACtx.Idents.get(Name);
auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
- if (LookupRes.size() == 0)
+ if (LookupRes.empty())
return false;
for (Decl *D : LookupRes) {
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
@@ -2441,6 +2566,35 @@
// Functions for testing.
if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) {
addToFunctionSummaryMap(
+ "__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
+ Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
+
+ // Test range values.
+ addToFunctionSummaryMap(
+ "__single_val_1", Signature(ArgTypes{IntTy}, RetType{IntTy}),
+ Summary(EvalCallAsPure)
+ .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
+ addToFunctionSummaryMap(
+ "__range_1_2", Signature(ArgTypes{IntTy}, RetType{IntTy}),
+ Summary(EvalCallAsPure)
+ .ArgConstraint(ArgumentCondition(0U, WithinRange, Range(1, 2))));
+ addToFunctionSummaryMap("__range_1_2__4_5",
+ Signature(ArgTypes{IntTy}, RetType{IntTy}),
+ Summary(EvalCallAsPure)
+ .ArgConstraint(ArgumentCondition(
+ 0U, WithinRange, Range({1, 2}, {4, 5}))));
+
+ // Test range kind.
+ addToFunctionSummaryMap(
+ "__within", Signature(ArgTypes{IntTy}, RetType{IntTy}),
+ Summary(EvalCallAsPure)
+ .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
+ addToFunctionSummaryMap(
+ "__out_of", Signature(ArgTypes{IntTy}, RetType{IntTy}),
+ Summary(EvalCallAsPure)
+ .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))));
+
+ addToFunctionSummaryMap(
"__two_constrained_args",
Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
Summary(EvalCallAsPure)
@@ -2485,6 +2639,8 @@
Signature(ArgTypes{VoidPtrRestrictTy}, RetType{VoidTy}),
Summary(EvalCallAsPure));
}
+
+ SummariesInitialized = true;
}
void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 6b176b3..dd65f8c 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -25,6 +25,10 @@
using namespace ento;
using namespace std::placeholders;
+//===----------------------------------------------------------------------===//
+// Definition of state data structures.
+//===----------------------------------------------------------------------===//
+
namespace {
struct FnDescription;
@@ -146,6 +150,14 @@
}
};
+} // namespace
+
+//===----------------------------------------------------------------------===//
+// StreamChecker class and utility functions.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
class StreamChecker;
using FnCheck = std::function<void(const StreamChecker *, const FnDescription *,
const CallEvent &, CheckerContext &)>;
@@ -219,6 +231,8 @@
/// If true, evaluate special testing stream functions.
bool TestMode = false;
+ const BugType *getBT_StreamEof() const { return &BT_StreamEof; }
+
private:
CallDescriptionMap<FnDescription> FnDescriptions = {
{{"fopen"}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
@@ -306,7 +320,8 @@
/// If it can only be NULL a fatal error is emitted and nullptr returned.
/// Otherwise the return value is a new state where the stream is constrained
/// to be non-null.
- ProgramStateRef ensureStreamNonNull(SVal StreamVal, CheckerContext &C,
+ ProgramStateRef ensureStreamNonNull(SVal StreamVal, const Expr *StreamE,
+ CheckerContext &C,
ProgramStateRef State) const;
/// Check that the stream is the opened state.
@@ -336,7 +351,8 @@
/// There will be always a state transition into the passed State,
/// by the new non-fatal error node or (if failed) a normal transition,
/// to ensure uniform handling.
- void reportFEofWarning(CheckerContext &C, ProgramStateRef State) const;
+ void reportFEofWarning(SymbolRef StreamSym, CheckerContext &C,
+ ProgramStateRef State) const;
/// Emit resource leak warnings for the given symbols.
/// Createn a non-fatal error node for these, and returns it (if any warnings
@@ -362,14 +378,14 @@
/// Generate a message for BugReporterVisitor if the stored symbol is
/// marked as interesting by the actual bug report.
+ // FIXME: Use lambda instead.
struct NoteFn {
- const CheckerNameRef CheckerName;
+ const BugType *BT_ResourceLeak;
SymbolRef StreamSym;
std::string Message;
std::string operator()(PathSensitiveBugReport &BR) const {
- if (BR.isInteresting(StreamSym) &&
- CheckerName == BR.getBugType().getCheckerName())
+ if (BR.isInteresting(StreamSym) && &BR.getBugType() == BT_ResourceLeak)
return Message;
return "";
@@ -378,7 +394,20 @@
const NoteTag *constructNoteTag(CheckerContext &C, SymbolRef StreamSym,
const std::string &Message) const {
- return C.getNoteTag(NoteFn{getCheckerName(), StreamSym, Message});
+ return C.getNoteTag(NoteFn{&BT_ResourceLeak, StreamSym, Message});
+ }
+
+ const NoteTag *constructSetEofNoteTag(CheckerContext &C,
+ SymbolRef StreamSym) const {
+ return C.getNoteTag([this, StreamSym](PathSensitiveBugReport &BR) {
+ if (!BR.isInteresting(StreamSym) ||
+ &BR.getBugType() != this->getBT_StreamEof())
+ return "";
+
+ BR.markNotInteresting(StreamSym);
+
+ return "Assuming stream reaches end-of-file here";
+ });
}
/// Searches for the ExplodedNode where the file descriptor was acquired for
@@ -390,6 +419,9 @@
} // end anonymous namespace
+// This map holds the state of a stream.
+// The stream is identified with a SymbolRef that is created when a stream
+// opening function is modeled by the checker.
REGISTER_MAP_WITH_PROGRAMSTATE(StreamMap, SymbolRef, StreamState)
inline void assertStreamStateOpened(const StreamState *SS) {
@@ -418,6 +450,10 @@
return nullptr;
}
+//===----------------------------------------------------------------------===//
+// Methods of StreamChecker.
+//===----------------------------------------------------------------------===//
+
void StreamChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const {
const FnDescription *Desc = lookupFn(Call);
@@ -472,7 +508,8 @@
CheckerContext &C) const {
// Do not allow NULL as passed stream pointer but allow a closed stream.
ProgramStateRef State = C.getState();
- State = ensureStreamNonNull(getStreamArg(Desc, Call), C, State);
+ State = ensureStreamNonNull(getStreamArg(Desc, Call),
+ Call.getArgExpr(Desc->StreamArgNo), C, State);
if (!State)
return;
@@ -549,7 +586,8 @@
CheckerContext &C) const {
ProgramStateRef State = C.getState();
SVal StreamVal = getStreamArg(Desc, Call);
- State = ensureStreamNonNull(StreamVal, C, State);
+ State = ensureStreamNonNull(StreamVal, Call.getArgExpr(Desc->StreamArgNo), C,
+ State);
if (!State)
return;
State = ensureStreamOpened(StreamVal, C, State);
@@ -563,7 +601,7 @@
if (Sym && State->get<StreamMap>(Sym)) {
const StreamState *SS = State->get<StreamMap>(Sym);
if (SS->ErrorState & ErrorFEof)
- reportFEofWarning(C, State);
+ reportFEofWarning(Sym, C, State);
} else {
C.addTransition(State);
}
@@ -573,7 +611,8 @@
CheckerContext &C) const {
ProgramStateRef State = C.getState();
SVal StreamVal = getStreamArg(Desc, Call);
- State = ensureStreamNonNull(StreamVal, C, State);
+ State = ensureStreamNonNull(StreamVal, Call.getArgExpr(Desc->StreamArgNo), C,
+ State);
if (!State)
return;
State = ensureStreamOpened(StreamVal, C, State);
@@ -605,11 +644,11 @@
if (!NMembVal)
return;
- const StreamState *SS = State->get<StreamMap>(StreamSym);
- if (!SS)
+ const StreamState *OldSS = State->get<StreamMap>(StreamSym);
+ if (!OldSS)
return;
- assertStreamStateOpened(SS);
+ assertStreamStateOpened(OldSS);
// C'99 standard, §7.19.8.1.3, the return value of fread:
// The fread function returns the number of elements successfully read, which
@@ -628,7 +667,7 @@
// Generate a transition for the success state.
// If we know the state to be FEOF at fread, do not add a success state.
- if (!IsFread || (SS->ErrorState != ErrorFEof)) {
+ if (!IsFread || (OldSS->ErrorState != ErrorFEof)) {
ProgramStateRef StateNotFailed =
State->BindExpr(CE, C.getLocationContext(), *NMembVal);
if (StateNotFailed) {
@@ -657,21 +696,26 @@
StreamErrorState NewES;
if (IsFread)
- NewES = (SS->ErrorState == ErrorFEof) ? ErrorFEof : ErrorFEof | ErrorFError;
+ NewES =
+ (OldSS->ErrorState == ErrorFEof) ? ErrorFEof : ErrorFEof | ErrorFError;
else
NewES = ErrorFError;
// If a (non-EOF) error occurs, the resulting value of the file position
// indicator for the stream is indeterminate.
- StreamState NewState = StreamState::getOpened(Desc, NewES, !NewES.isFEof());
- StateFailed = StateFailed->set<StreamMap>(StreamSym, NewState);
- C.addTransition(StateFailed);
+ StreamState NewSS = StreamState::getOpened(Desc, NewES, !NewES.isFEof());
+ StateFailed = StateFailed->set<StreamMap>(StreamSym, NewSS);
+ if (IsFread && OldSS->ErrorState != ErrorFEof)
+ C.addTransition(StateFailed, constructSetEofNoteTag(C, StreamSym));
+ else
+ C.addTransition(StateFailed);
}
void StreamChecker::preFseek(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
SVal StreamVal = getStreamArg(Desc, Call);
- State = ensureStreamNonNull(StreamVal, C, State);
+ State = ensureStreamNonNull(StreamVal, Call.getArgExpr(Desc->StreamArgNo), C,
+ State);
if (!State)
return;
State = ensureStreamOpened(StreamVal, C, State);
@@ -722,7 +766,7 @@
StreamState::getOpened(Desc, ErrorNone | ErrorFEof | ErrorFError, true));
C.addTransition(StateNotFailed);
- C.addTransition(StateFailed);
+ C.addTransition(StateFailed, constructSetEofNoteTag(C, StreamSym));
}
void StreamChecker::evalClearerr(const FnDescription *Desc,
@@ -790,7 +834,8 @@
CheckerContext &C) const {
ProgramStateRef State = C.getState();
SVal StreamVal = getStreamArg(Desc, Call);
- State = ensureStreamNonNull(StreamVal, C, State);
+ State = ensureStreamNonNull(StreamVal, Call.getArgExpr(Desc->StreamArgNo), C,
+ State);
if (!State)
return;
State = ensureStreamOpened(StreamVal, C, State);
@@ -814,7 +859,8 @@
}
ProgramStateRef
-StreamChecker::ensureStreamNonNull(SVal StreamVal, CheckerContext &C,
+StreamChecker::ensureStreamNonNull(SVal StreamVal, const Expr *StreamE,
+ CheckerContext &C,
ProgramStateRef State) const {
auto Stream = StreamVal.getAs<DefinedSVal>();
if (!Stream)
@@ -827,8 +873,11 @@
if (!StateNotNull && StateNull) {
if (ExplodedNode *N = C.generateErrorNode(StateNull)) {
- C.emitReport(std::make_unique<PathSensitiveBugReport>(
- BT_FileNull, "Stream pointer might be NULL.", N));
+ auto R = std::make_unique<PathSensitiveBugReport>(
+ BT_FileNull, "Stream pointer might be NULL.", N);
+ if (StreamE)
+ bugreporter::trackExpressionValue(N, StreamE, *R);
+ C.emitReport(std::move(R));
}
return nullptr;
}
@@ -950,14 +999,16 @@
return State;
}
-void StreamChecker::reportFEofWarning(CheckerContext &C,
+void StreamChecker::reportFEofWarning(SymbolRef StreamSym, CheckerContext &C,
ProgramStateRef State) const {
if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) {
- C.emitReport(std::make_unique<PathSensitiveBugReport>(
+ auto R = std::make_unique<PathSensitiveBugReport>(
BT_StreamEof,
"Read function called when stream is in EOF state. "
"Function has no effect.",
- N));
+ N);
+ R->markInteresting(StreamSym);
+ C.emitReport(std::move(R));
return;
}
C.addTransition(State);
@@ -1048,6 +1099,10 @@
return State;
}
+//===----------------------------------------------------------------------===//
+// Checker registration.
+//===----------------------------------------------------------------------===//
+
void ento::registerStreamChecker(CheckerManager &Mgr) {
Mgr.registerChecker<StreamChecker>();
}
@@ -1063,4 +1118,4 @@
bool ento::shouldRegisterStreamTesterChecker(const CheckerManager &Mgr) {
return true;
-}
+}
\ No newline at end of file
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index e457513..816a547 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -86,9 +86,9 @@
auto R = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
R->addRange(Ex->getSourceRange());
- R->addVisitor(std::make_unique<FindLastStoreBRVisitor>(
- *V, VR, /*EnableNullFPSuppression*/ false,
- bugreporter::TrackingKind::Thorough));
+ bugreporter::trackStoredValue(*V, VR, *R,
+ {bugreporter::TrackingKind::Thorough,
+ /*EnableNullFPSuppression*/ false});
R->disablePathPruning();
// need location of block
C.emitReport(std::move(R));
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index 392da48..477d910 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -16,7 +16,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index 74eec81..d231be6 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -169,7 +169,7 @@
if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
continue;
- B.EmitBasicReport(D, this, "Unreachable code", "Dead code",
+ B.EmitBasicReport(D, this, "Unreachable code", categories::UnusedCode,
"This statement is never executed", DL, SR);
}
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
index d76b2a0..9650121 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
@@ -20,7 +20,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
@@ -285,21 +285,11 @@
return;
}
- // VLASizeChecker is responsible for defining the extent of the array being
- // declared. We do this by multiplying the array length by the element size,
- // then matching that with the array region's extent symbol.
-
+ // VLASizeChecker is responsible for defining the extent of the array.
if (VD) {
- // Assume that the array's size matches the region size.
- const LocationContext *LC = C.getLocationContext();
- DefinedOrUnknownSVal DynSize =
- getDynamicSize(State, State->getRegion(VD, LC), SVB);
-
- DefinedOrUnknownSVal SizeIsKnown = SVB.evalEQ(State, DynSize, *ArraySizeNL);
- State = State->assume(SizeIsKnown, true);
-
- // Assume should not fail at this point.
- assert(State);
+ State =
+ setDynamicExtent(State, State->getRegion(VD, C.getLocationContext()),
+ ArraySize.castAs<DefinedOrUnknownSVal>(), SVB);
}
// Remember our assumptions!
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index d1f5ac0..40cdaef 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -21,6 +21,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include <cassert>
#include <cstdint>
#include <utility>
@@ -176,28 +177,73 @@
return D;
}
+LLVM_ATTRIBUTE_UNUSED bool hasNoRepeatedElements(
+ llvm::ImmutableList<const CXXBaseSpecifier *> BaseSpecList) {
+ llvm::SmallPtrSet<QualType, 16> BaseSpecSeen;
+ for (const CXXBaseSpecifier *BaseSpec : BaseSpecList) {
+ QualType BaseType = BaseSpec->getType();
+ // Check whether inserted
+ if (!BaseSpecSeen.insert(BaseType).second)
+ return false;
+ }
+ return true;
+}
+
const PointerToMemberData *BasicValueFactory::accumCXXBase(
llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
- const nonloc::PointerToMember &PTM) {
+ const nonloc::PointerToMember &PTM, const CastKind &kind) {
+ assert((kind == CK_DerivedToBaseMemberPointer ||
+ kind == CK_BaseToDerivedMemberPointer ||
+ kind == CK_ReinterpretMemberPointer) &&
+ "accumCXXBase called with wrong CastKind");
nonloc::PointerToMember::PTMDataType PTMDT = PTM.getPTMData();
const NamedDecl *ND = nullptr;
- llvm::ImmutableList<const CXXBaseSpecifier *> PathList;
+ llvm::ImmutableList<const CXXBaseSpecifier *> BaseSpecList;
if (PTMDT.isNull() || PTMDT.is<const NamedDecl *>()) {
if (PTMDT.is<const NamedDecl *>())
ND = PTMDT.get<const NamedDecl *>();
- PathList = CXXBaseListFactory.getEmptyList();
- } else { // const PointerToMemberData *
+ BaseSpecList = CXXBaseListFactory.getEmptyList();
+ } else {
const PointerToMemberData *PTMD = PTMDT.get<const PointerToMemberData *>();
ND = PTMD->getDeclaratorDecl();
- PathList = PTMD->getCXXBaseList();
+ BaseSpecList = PTMD->getCXXBaseList();
}
- for (const auto &I : llvm::reverse(PathRange))
- PathList = prependCXXBase(I, PathList);
- return getPointerToMemberData(ND, PathList);
+ assert(hasNoRepeatedElements(BaseSpecList) &&
+ "CXXBaseSpecifier list of PointerToMemberData must not have repeated "
+ "elements");
+
+ if (kind == CK_DerivedToBaseMemberPointer) {
+ // Here we pop off matching CXXBaseSpecifiers from BaseSpecList.
+ // Because, CK_DerivedToBaseMemberPointer comes from a static_cast and
+ // serves to remove a matching implicit cast. Note that static_cast's that
+ // are no-ops do not count since they produce an empty PathRange, a nice
+ // thing about Clang AST.
+
+ // Now we know that there are no repetitions in BaseSpecList.
+ // So, popping the first element from it corresponding to each element in
+ // PathRange is equivalent to only including elements that are in
+ // BaseSpecList but not it PathRange
+ auto ReducedBaseSpecList = CXXBaseListFactory.getEmptyList();
+ for (const CXXBaseSpecifier *BaseSpec : BaseSpecList) {
+ auto IsSameAsBaseSpec = [&BaseSpec](const CXXBaseSpecifier *I) -> bool {
+ return BaseSpec->getType() == I->getType();
+ };
+ if (llvm::none_of(PathRange, IsSameAsBaseSpec))
+ ReducedBaseSpecList =
+ CXXBaseListFactory.add(BaseSpec, ReducedBaseSpecList);
+ }
+
+ return getPointerToMemberData(ND, ReducedBaseSpecList);
+ }
+ // FIXME: Reinterpret casts on member-pointers are not handled properly by
+ // this code
+ for (const CXXBaseSpecifier *I : llvm::reverse(PathRange))
+ BaseSpecList = prependCXXBase(I, BaseSpecList);
+ return getPointerToMemberData(ND, BaseSpecList);
}
const llvm::APSInt*
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index bf38891..d6f69ae 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -1988,14 +1988,6 @@
const SourceManager &SM = getSourceManager();
const AnalyzerOptions &Opts = getAnalyzerOptions();
- StringRef ErrorTag = ErrorNode->getLocation().getTag()->getTagDescription();
-
- // See whether we need to silence the checker/package.
- // FIXME: This will not work if the report was emitted with an incorrect tag.
- for (const std::string &CheckerOrPackage : Opts.SilencedCheckersAndPackages) {
- if (ErrorTag.startswith(CheckerOrPackage))
- return nullptr;
- }
if (!PDC->shouldGenerateDiagnostics())
return generateEmptyDiagnosticForReport(R, getSourceManager());
@@ -2257,10 +2249,24 @@
insertToInterestingnessMap(InterestingSymbols, sym, TKind);
+ // FIXME: No tests exist for this code and it is questionable:
+ // How to handle multiple metadata for the same region?
if (const auto *meta = dyn_cast<SymbolMetadata>(sym))
markInteresting(meta->getRegion(), TKind);
}
+void PathSensitiveBugReport::markNotInteresting(SymbolRef sym) {
+ if (!sym)
+ return;
+ InterestingSymbols.erase(sym);
+
+ // The metadata part of markInteresting is not reversed here.
+ // Just making the same region not interesting is incorrect
+ // in specific cases.
+ if (const auto *meta = dyn_cast<SymbolMetadata>(sym))
+ markNotInteresting(meta->getRegion());
+}
+
void PathSensitiveBugReport::markInteresting(const MemRegion *R,
bugreporter::TrackingKind TKind) {
if (!R)
@@ -2273,6 +2279,17 @@
markInteresting(SR->getSymbol(), TKind);
}
+void PathSensitiveBugReport::markNotInteresting(const MemRegion *R) {
+ if (!R)
+ return;
+
+ R = R->getBaseRegion();
+ InterestingRegions.erase(R);
+
+ if (const auto *SR = dyn_cast<SymbolicRegion>(R))
+ markNotInteresting(SR->getSymbol());
+}
+
void PathSensitiveBugReport::markInteresting(SVal V,
bugreporter::TrackingKind TKind) {
markInteresting(V.getAsRegion(), TKind);
@@ -2738,8 +2755,8 @@
}
/// Generate notes from all visitors.
-/// Notes associated with {@code ErrorNode} are generated using
-/// {@code getEndPath}, and the rest are generated with {@code VisitNode}.
+/// Notes associated with @c ErrorNode are generated using
+/// @c getEndPath, and the rest are generated with @c VisitNode.
static std::unique_ptr<VisitorsDiagnosticsTy>
generateVisitorsDiagnostics(PathSensitiveBugReport *R,
const ExplodedNode *ErrorNode,
@@ -2749,7 +2766,7 @@
PathSensitiveBugReport::VisitorList visitors;
// Run visitors on all nodes starting from the node *before* the last one.
- // The last node is reserved for notes generated with {@code getEndPath}.
+ // The last node is reserved for notes generated with @c getEndPath.
const ExplodedNode *NextNode = ErrorNode->getFirstPred();
while (NextNode) {
@@ -2811,12 +2828,12 @@
// Register refutation visitors first, if they mark the bug invalid no
// further analysis is required
- R->addVisitor(std::make_unique<LikelyFalsePositiveSuppressionBRVisitor>());
+ R->addVisitor<LikelyFalsePositiveSuppressionBRVisitor>();
// Register additional node visitors.
- R->addVisitor(std::make_unique<NilReceiverBRVisitor>());
- R->addVisitor(std::make_unique<ConditionBRVisitor>());
- R->addVisitor(std::make_unique<TagVisitor>());
+ R->addVisitor<NilReceiverBRVisitor>();
+ R->addVisitor<ConditionBRVisitor>();
+ R->addVisitor<TagVisitor>();
BugReporterContext BRC(Reporter);
@@ -2829,7 +2846,7 @@
// If crosscheck is enabled, remove all visitors, add the refutation
// visitor and check again
R->clearVisitors();
- R->addVisitor(std::make_unique<FalsePositiveRefutationBRVisitor>());
+ R->addVisitor<FalsePositiveRefutationBRVisitor>();
// We don't overwrite the notes inserted by other visitors because the
// refutation manager does not add any new note to the path
@@ -3041,6 +3058,14 @@
if (!report)
return;
+ // See whether we need to silence the checker/package.
+ for (const std::string &CheckerOrPackage :
+ getAnalyzerOptions().SilencedCheckersAndPackages) {
+ if (report->getBugType().getCheckerName().startswith(
+ CheckerOrPackage))
+ return;
+ }
+
ArrayRef<PathDiagnosticConsumer*> Consumers = getPathDiagnosticConsumers();
std::unique_ptr<DiagnosticForConsumerMapTy> Diagnostics =
generateDiagnosticForConsumerMap(report, Consumers, bugReports);
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index bc72f4f..d06a2d4 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -65,6 +65,7 @@
using namespace clang;
using namespace ento;
+using namespace bugreporter;
//===----------------------------------------------------------------------===//
// Utility functions.
@@ -153,6 +154,28 @@
return E;
}
+static const MemRegion *
+getLocationRegionIfReference(const Expr *E, const ExplodedNode *N,
+ bool LookingForReference = true) {
+ if (const auto *DR = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ if (LookingForReference && !VD->getType()->isReferenceType())
+ return nullptr;
+ return N->getState()
+ ->getLValue(VD, N->getLocationContext())
+ .getAsRegion();
+ }
+ }
+
+ // FIXME: This does not handle other kinds of null references,
+ // for example, references from FieldRegions:
+ // struct Wrapper { int &ref; };
+ // Wrapper w = { *(int *)0 };
+ // w.ref = 1;
+
+ return nullptr;
+}
+
/// Comparing internal representations of symbolic values (via
/// SVal::operator==()) is a valid way to check if the value was updated,
/// unless it's a LazyCompoundVal that may have a different internal
@@ -830,10 +853,10 @@
bool EnableNullFPSuppression, PathSensitiveBugReport &BR,
const SVal V) {
AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
- if (EnableNullFPSuppression &&
- Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
- BR.addVisitor(std::make_unique<MacroNullReturnSuppressionVisitor>(
- R->getAs<SubRegion>(), V));
+ if (EnableNullFPSuppression && Options.ShouldSuppressNullReturnPaths &&
+ V.getAs<Loc>())
+ BR.addVisitor<MacroNullReturnSuppressionVisitor>(R->getAs<SubRegion>(),
+ V);
}
void* getTag() const {
@@ -883,7 +906,7 @@
///
/// This visitor is intended to be used when another visitor discovers that an
/// interesting value comes from an inlined function call.
-class ReturnVisitor : public BugReporterVisitor {
+class ReturnVisitor : public TrackingBugReporterVisitor {
const StackFrameContext *CalleeSFC;
enum {
Initial,
@@ -897,10 +920,11 @@
bugreporter::TrackingKind TKind;
public:
- ReturnVisitor(const StackFrameContext *Frame, bool Suppressed,
- AnalyzerOptions &Options, bugreporter::TrackingKind TKind)
- : CalleeSFC(Frame), EnableNullFPSuppression(Suppressed),
- Options(Options), TKind(TKind) {}
+ ReturnVisitor(TrackerRef ParentTracker, const StackFrameContext *Frame,
+ bool Suppressed, AnalyzerOptions &Options,
+ bugreporter::TrackingKind TKind)
+ : TrackingBugReporterVisitor(ParentTracker), CalleeSFC(Frame),
+ EnableNullFPSuppression(Suppressed), Options(Options), TKind(TKind) {}
static void *getTag() {
static int Tag = 0;
@@ -913,92 +937,6 @@
ID.AddBoolean(EnableNullFPSuppression);
}
- /// Adds a ReturnVisitor if the given statement represents a call that was
- /// inlined.
- ///
- /// This will search back through the ExplodedGraph, starting from the given
- /// node, looking for when the given statement was processed. If it turns out
- /// the statement is a call that was inlined, we add the visitor to the
- /// bug report, so it can print a note later.
- static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S,
- PathSensitiveBugReport &BR,
- bool InEnableNullFPSuppression,
- bugreporter::TrackingKind TKind) {
- if (!CallEvent::isCallStmt(S))
- return;
-
- // First, find when we processed the statement.
- // If we work with a 'CXXNewExpr' that is going to be purged away before
- // its call take place. We would catch that purge in the last condition
- // as a 'StmtPoint' so we have to bypass it.
- const bool BypassCXXNewExprEval = isa<CXXNewExpr>(S);
-
- // This is moving forward when we enter into another context.
- const StackFrameContext *CurrentSFC = Node->getStackFrame();
-
- do {
- // If that is satisfied we found our statement as an inlined call.
- if (Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>())
- if (CEE->getCalleeContext()->getCallSite() == S)
- break;
-
- // Try to move forward to the end of the call-chain.
- Node = Node->getFirstPred();
- if (!Node)
- break;
-
- const StackFrameContext *PredSFC = Node->getStackFrame();
-
- // If that is satisfied we found our statement.
- // FIXME: This code currently bypasses the call site for the
- // conservatively evaluated allocator.
- if (!BypassCXXNewExprEval)
- if (Optional<StmtPoint> SP = Node->getLocationAs<StmtPoint>())
- // See if we do not enter into another context.
- if (SP->getStmt() == S && CurrentSFC == PredSFC)
- break;
-
- CurrentSFC = PredSFC;
- } while (Node->getStackFrame() == CurrentSFC);
-
- // Next, step over any post-statement checks.
- while (Node && Node->getLocation().getAs<PostStmt>())
- Node = Node->getFirstPred();
- if (!Node)
- return;
-
- // Finally, see if we inlined the call.
- Optional<CallExitEnd> CEE = Node->getLocationAs<CallExitEnd>();
- if (!CEE)
- return;
-
- const StackFrameContext *CalleeContext = CEE->getCalleeContext();
- if (CalleeContext->getCallSite() != S)
- return;
-
- // Check the return value.
- ProgramStateRef State = Node->getState();
- SVal RetVal = Node->getSVal(S);
-
- // Handle cases where a reference is returned and then immediately used.
- if (cast<Expr>(S)->isGLValue())
- if (Optional<Loc> LValue = RetVal.getAs<Loc>())
- RetVal = State->getSVal(*LValue);
-
- // See if the return value is NULL. If so, suppress the report.
- AnalyzerOptions &Options = State->getAnalysisManager().options;
-
- bool EnableNullFPSuppression = false;
- if (InEnableNullFPSuppression &&
- Options.ShouldSuppressNullReturnPaths)
- if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
- EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
-
- BR.addVisitor(std::make_unique<ReturnVisitor>(CalleeContext,
- EnableNullFPSuppression,
- Options, TKind));
- }
-
PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N,
BugReporterContext &BRC,
PathSensitiveBugReport &BR) {
@@ -1045,8 +983,7 @@
RetE = RetE->IgnoreParenCasts();
// Let's track the return value.
- bugreporter::trackExpressionValue(
- N, RetE, BR, TKind, EnableNullFPSuppression);
+ getParentTracker().track(RetE, N, {TKind, EnableNullFPSuppression});
// Build an appropriate message based on the return value.
SmallString<64> Msg;
@@ -1162,7 +1099,9 @@
if (!State->isNull(*ArgV).isConstrainedTrue())
continue;
- if (trackExpressionValue(N, ArgE, BR, TKind, EnableNullFPSuppression))
+ if (getParentTracker()
+ .track(ArgE, N, {TKind, EnableNullFPSuppression})
+ .FoundSomethingToTrack)
ShouldInvalidate = false;
// If we /can't/ track the null pointer, we should err on the side of
@@ -1198,16 +1137,52 @@
} // end of anonymous namespace
//===----------------------------------------------------------------------===//
-// Implementation of FindLastStoreBRVisitor.
+// StoreSiteFinder
//===----------------------------------------------------------------------===//
-void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
+/// Finds last store into the given region,
+/// which is different from a given symbolic value.
+class StoreSiteFinder final : public TrackingBugReporterVisitor {
+ const MemRegion *R;
+ SVal V;
+ bool Satisfied = false;
+
+ TrackingOptions Options;
+ const StackFrameContext *OriginSFC;
+
+public:
+ /// \param V We're searching for the store where \c R received this value.
+ /// \param R The region we're tracking.
+ /// \param TKind May limit the amount of notes added to the bug report.
+ /// \param OriginSFC Only adds notes when the last store happened in a
+ /// different stackframe to this one. Disregarded if the tracking kind
+ /// is thorough.
+ /// This is useful, because for non-tracked regions, notes about
+ /// changes to its value in a nested stackframe could be pruned, and
+ /// this visitor can prevent that without polluting the bugpath too
+ /// much.
+ StoreSiteFinder(bugreporter::TrackerRef ParentTracker, KnownSVal V,
+ const MemRegion *R, TrackingOptions Options,
+ const StackFrameContext *OriginSFC = nullptr)
+ : TrackingBugReporterVisitor(ParentTracker), R(R), V(V), Options(Options),
+ OriginSFC(OriginSFC) {
+ assert(R);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
+};
+
+void StoreSiteFinder::Profile(llvm::FoldingSetNodeID &ID) const {
static int tag = 0;
ID.AddPointer(&tag);
ID.AddPointer(R);
ID.Add(V);
- ID.AddInteger(static_cast<int>(TKind));
- ID.AddBoolean(EnableNullFPSuppression);
+ ID.AddInteger(static_cast<int>(Options.Kind));
+ ID.AddBoolean(Options.EnableNullFPSuppression);
}
/// Returns true if \p N represents the DeclStmt declaring and initializing
@@ -1239,127 +1214,152 @@
return FrameSpace->getStackFrame() == LCtx->getStackFrame();
}
+static bool isObjCPointer(const MemRegion *R) {
+ if (R->isBoundable())
+ if (const auto *TR = dyn_cast<TypedValueRegion>(R))
+ return TR->getValueType()->isObjCObjectPointerType();
+
+ return false;
+}
+
+static bool isObjCPointer(const ValueDecl *D) {
+ return D->getType()->isObjCObjectPointerType();
+}
+
/// Show diagnostics for initializing or declaring a region \p R with a bad value.
-static void showBRDiagnostics(const char *action, llvm::raw_svector_ostream &os,
- const MemRegion *R, SVal V, const DeclStmt *DS) {
- if (R->canPrintPretty()) {
- R->printPretty(os);
- os << " ";
+static void showBRDiagnostics(llvm::raw_svector_ostream &OS, StoreInfo SI) {
+ const bool HasPrefix = SI.Dest->canPrintPretty();
+
+ if (HasPrefix) {
+ SI.Dest->printPretty(OS);
+ OS << " ";
}
- if (V.getAs<loc::ConcreteInt>()) {
- bool b = false;
- if (R->isBoundable()) {
- if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
- if (TR->getValueType()->isObjCObjectPointerType()) {
- os << action << "nil";
- b = true;
- }
- }
- }
- if (!b)
- os << action << "a null pointer value";
+ const char *Action = nullptr;
- } else if (auto CVal = V.getAs<nonloc::ConcreteInt>()) {
- os << action << CVal->getValue();
- } else if (DS) {
- if (V.isUndef()) {
- if (isa<VarRegion>(R)) {
+ switch (SI.StoreKind) {
+ case StoreInfo::Initialization:
+ Action = HasPrefix ? "initialized to " : "Initializing to ";
+ break;
+ case StoreInfo::BlockCapture:
+ Action = HasPrefix ? "captured by block as " : "Captured by block as ";
+ break;
+ default:
+ llvm_unreachable("Unexpected store kind");
+ }
+
+ if (SI.Value.getAs<loc::ConcreteInt>()) {
+ OS << Action << (isObjCPointer(SI.Dest) ? "nil" : "a null pointer value");
+
+ } else if (auto CVal = SI.Value.getAs<nonloc::ConcreteInt>()) {
+ OS << Action << CVal->getValue();
+
+ } else if (SI.Origin && SI.Origin->canPrintPretty()) {
+ OS << Action << "the value of ";
+ SI.Origin->printPretty(OS);
+
+ } else if (SI.StoreKind == StoreInfo::Initialization) {
+ // We don't need to check here, all these conditions were
+ // checked by StoreSiteFinder, when it figured out that it is
+ // initialization.
+ const auto *DS =
+ cast<DeclStmt>(SI.StoreSite->getLocationAs<PostStmt>()->getStmt());
+
+ if (SI.Value.isUndef()) {
+ if (isa<VarRegion>(SI.Dest)) {
const auto *VD = cast<VarDecl>(DS->getSingleDecl());
+
if (VD->getInit()) {
- os << (R->canPrintPretty() ? "initialized" : "Initializing")
- << " to a garbage value";
+ OS << (HasPrefix ? "initialized" : "Initializing")
+ << " to a garbage value";
} else {
- os << (R->canPrintPretty() ? "declared" : "Declaring")
- << " without an initial value";
+ OS << (HasPrefix ? "declared" : "Declaring")
+ << " without an initial value";
}
}
} else {
- os << (R->canPrintPretty() ? "initialized" : "Initialized")
- << " here";
+ OS << (HasPrefix ? "initialized" : "Initialized") << " here";
}
}
}
/// Display diagnostics for passing bad region as a parameter.
-static void showBRParamDiagnostics(llvm::raw_svector_ostream& os,
- const VarRegion *VR,
- SVal V) {
+static void showBRParamDiagnostics(llvm::raw_svector_ostream &OS,
+ StoreInfo SI) {
+ const auto *VR = cast<VarRegion>(SI.Dest);
const auto *Param = cast<ParmVarDecl>(VR->getDecl());
- os << "Passing ";
+ OS << "Passing ";
- if (V.getAs<loc::ConcreteInt>()) {
- if (Param->getType()->isObjCObjectPointerType())
- os << "nil object reference";
- else
- os << "null pointer value";
- } else if (V.isUndef()) {
- os << "uninitialized value";
- } else if (auto CI = V.getAs<nonloc::ConcreteInt>()) {
- os << "the value " << CI->getValue();
+ if (SI.Value.getAs<loc::ConcreteInt>()) {
+ OS << (isObjCPointer(Param) ? "nil object reference"
+ : "null pointer value");
+
+ } else if (SI.Value.isUndef()) {
+ OS << "uninitialized value";
+
+ } else if (auto CI = SI.Value.getAs<nonloc::ConcreteInt>()) {
+ OS << "the value " << CI->getValue();
+
+ } else if (SI.Origin && SI.Origin->canPrintPretty()) {
+ SI.Origin->printPretty(OS);
+
} else {
- os << "value";
+ OS << "value";
}
// Printed parameter indexes are 1-based, not 0-based.
unsigned Idx = Param->getFunctionScopeIndex() + 1;
- os << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
+ OS << " via " << Idx << llvm::getOrdinalSuffix(Idx) << " parameter";
if (VR->canPrintPretty()) {
- os << " ";
- VR->printPretty(os);
+ OS << " ";
+ VR->printPretty(OS);
}
}
/// Show default diagnostics for storing bad region.
-static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &os,
- const MemRegion *R, SVal V) {
- if (V.getAs<loc::ConcreteInt>()) {
- bool b = false;
- if (R->isBoundable()) {
- if (const auto *TR = dyn_cast<TypedValueRegion>(R)) {
- if (TR->getValueType()->isObjCObjectPointerType()) {
- os << "nil object reference stored";
- b = true;
- }
- }
- }
- if (!b) {
- if (R->canPrintPretty())
- os << "Null pointer value stored";
- else
- os << "Storing null pointer value";
- }
+static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &OS,
+ StoreInfo SI) {
+ const bool HasSuffix = SI.Dest->canPrintPretty();
- } else if (V.isUndef()) {
- if (R->canPrintPretty())
- os << "Uninitialized value stored";
- else
- os << "Storing uninitialized value";
+ if (SI.Value.getAs<loc::ConcreteInt>()) {
+ OS << (isObjCPointer(SI.Dest) ? "nil object reference stored"
+ : (HasSuffix ? "Null pointer value stored"
+ : "Storing null pointer value"));
- } else if (auto CV = V.getAs<nonloc::ConcreteInt>()) {
- if (R->canPrintPretty())
- os << "The value " << CV->getValue() << " is assigned";
+ } else if (SI.Value.isUndef()) {
+ OS << (HasSuffix ? "Uninitialized value stored"
+ : "Storing uninitialized value");
+
+ } else if (auto CV = SI.Value.getAs<nonloc::ConcreteInt>()) {
+ if (HasSuffix)
+ OS << "The value " << CV->getValue() << " is assigned";
else
- os << "Assigning " << CV->getValue();
+ OS << "Assigning " << CV->getValue();
+
+ } else if (SI.Origin && SI.Origin->canPrintPretty()) {
+ if (HasSuffix) {
+ OS << "The value of ";
+ SI.Origin->printPretty(OS);
+ OS << " is assigned";
+ } else {
+ OS << "Assigning the value of ";
+ SI.Origin->printPretty(OS);
+ }
} else {
- if (R->canPrintPretty())
- os << "Value assigned";
- else
- os << "Assigning value";
+ OS << (HasSuffix ? "Value assigned" : "Assigning value");
}
- if (R->canPrintPretty()) {
- os << " to ";
- R->printPretty(os);
+ if (HasSuffix) {
+ OS << " to ";
+ SI.Dest->printPretty(OS);
}
}
-PathDiagnosticPieceRef
-FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
- BugReporterContext &BRC,
- PathSensitiveBugReport &BR) {
+PathDiagnosticPieceRef StoreSiteFinder::VisitNode(const ExplodedNode *Succ,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) {
if (Satisfied)
return nullptr;
@@ -1451,11 +1451,78 @@
if (!IsParam)
InitE = InitE->IgnoreParenCasts();
- bugreporter::trackExpressionValue(
- StoreSite, InitE, BR, TKind, EnableNullFPSuppression);
+ getParentTracker().track(InitE, StoreSite, Options);
}
- if (TKind == TrackingKind::Condition &&
+ // Let's try to find the region where the value came from.
+ const MemRegion *OldRegion = nullptr;
+
+ // If we have init expression, it might be simply a reference
+ // to a variable, so we can use it.
+ if (InitE) {
+ // That region might still be not exactly what we are looking for.
+ // In situations like `int &ref = val;`, we can't say that
+ // `ref` is initialized with `val`, rather refers to `val`.
+ //
+ // In order, to mitigate situations like this, we check if the last
+ // stored value in that region is the value that we track.
+ //
+ // TODO: support other situations better.
+ if (const MemRegion *Candidate =
+ getLocationRegionIfReference(InitE, Succ, false)) {
+ const StoreManager &SM = BRC.getStateManager().getStoreManager();
+
+ // Here we traverse the graph up to find the last node where the
+ // candidate region is still in the store.
+ for (const ExplodedNode *N = StoreSite; N; N = N->getFirstPred()) {
+ if (SM.includedInBindings(N->getState()->getStore(), Candidate)) {
+ // And if it was bound to the target value, we can use it.
+ if (N->getState()->getSVal(Candidate) == V) {
+ OldRegion = Candidate;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Otherwise, if the current region does indeed contain the value
+ // we are looking for, we can look for a region where this value
+ // was before.
+ //
+ // It can be useful for situations like:
+ // new = identity(old)
+ // where the analyzer knows that 'identity' returns the value of its
+ // first argument.
+ //
+ // NOTE: If the region R is not a simple var region, it can contain
+ // V in one of its subregions.
+ if (!OldRegion && StoreSite->getState()->getSVal(R) == V) {
+ // Let's go up the graph to find the node where the region is
+ // bound to V.
+ const ExplodedNode *NodeWithoutBinding = StoreSite->getFirstPred();
+ for (;
+ NodeWithoutBinding && NodeWithoutBinding->getState()->getSVal(R) == V;
+ NodeWithoutBinding = NodeWithoutBinding->getFirstPred()) {
+ }
+
+ if (NodeWithoutBinding) {
+ // Let's try to find a unique binding for the value in that node.
+ // We want to use this to find unique bindings because of the following
+ // situations:
+ // b = a;
+ // c = identity(b);
+ //
+ // Telling the user that the value of 'a' is assigned to 'c', while
+ // correct, can be confusing.
+ StoreManager::FindUniqueBinding FB(V.getAsLocSymbol());
+ BRC.getStateManager().iterBindings(NodeWithoutBinding->getState(), FB);
+ if (FB)
+ OldRegion = FB.getRegion();
+ }
+ }
+
+ if (Options.Kind == TrackingKind::Condition && OriginSFC &&
!OriginSFC->isParentOf(StoreSite->getStackFrame()))
return nullptr;
@@ -1463,60 +1530,41 @@
SmallString<256> sbuf;
llvm::raw_svector_ostream os(sbuf);
+ StoreInfo SI = {StoreInfo::Assignment, // default kind
+ StoreSite,
+ InitE,
+ V,
+ R,
+ OldRegion};
+
if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) {
const Stmt *S = PS->getStmt();
- const char *action = nullptr;
const auto *DS = dyn_cast<DeclStmt>(S);
const auto *VR = dyn_cast<VarRegion>(R);
if (DS) {
- action = R->canPrintPretty() ? "initialized to " :
- "Initializing to ";
+ SI.StoreKind = StoreInfo::Initialization;
} else if (isa<BlockExpr>(S)) {
- action = R->canPrintPretty() ? "captured by block as " :
- "Captured by block as ";
+ SI.StoreKind = StoreInfo::BlockCapture;
if (VR) {
// See if we can get the BlockVarRegion.
ProgramStateRef State = StoreSite->getState();
SVal V = StoreSite->getSVal(S);
if (const auto *BDR =
- dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
+ dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
- if (auto KV = State->getSVal(OriginalR).getAs<KnownSVal>())
- BR.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
- *KV, OriginalR, EnableNullFPSuppression, TKind, OriginSFC));
+ getParentTracker().track(State->getSVal(OriginalR), OriginalR,
+ Options, OriginSFC);
}
}
}
}
- if (action)
- showBRDiagnostics(action, os, R, V, DS);
-
- } else if (StoreSite->getLocation().getAs<CallEnter>()) {
- if (const auto *VR = dyn_cast<VarRegion>(R))
- showBRParamDiagnostics(os, VR, V);
+ } else if (SI.StoreSite->getLocation().getAs<CallEnter>() &&
+ isa<VarRegion>(SI.Dest)) {
+ SI.StoreKind = StoreInfo::CallArgument;
}
- if (os.str().empty())
- showBRDefaultDiagnostics(os, R, V);
-
- if (TKind == bugreporter::TrackingKind::Condition)
- os << WillBeUsedForACondition;
-
- // Construct a new PathDiagnosticPiece.
- ProgramPoint P = StoreSite->getLocation();
- PathDiagnosticLocation L;
- if (P.getAs<CallEnter>() && InitE)
- L = PathDiagnosticLocation(InitE, BRC.getSourceManager(),
- P.getLocationContext());
-
- if (!L.isValid() || !L.asLocation().isValid())
- L = PathDiagnosticLocation::create(P, BRC.getSourceManager());
-
- if (!L.isValid() || !L.asLocation().isValid())
- return nullptr;
-
- return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
+ return getParentTracker().handle(SI, BRC, Options);
}
//===----------------------------------------------------------------------===//
@@ -1705,14 +1753,17 @@
/// An error is emitted at line 3. This visitor realizes that the branch
/// on line 2 is a control dependency of line 3, and tracks it's condition via
/// trackExpressionValue().
-class TrackControlDependencyCondBRVisitor final : public BugReporterVisitor {
+class TrackControlDependencyCondBRVisitor final
+ : public TrackingBugReporterVisitor {
const ExplodedNode *Origin;
ControlDependencyCalculator ControlDeps;
llvm::SmallSet<const CFGBlock *, 32> VisitedBlocks;
public:
- TrackControlDependencyCondBRVisitor(const ExplodedNode *O)
- : Origin(O), ControlDeps(&O->getCFG()) {}
+ TrackControlDependencyCondBRVisitor(TrackerRef ParentTracker,
+ const ExplodedNode *O)
+ : TrackingBugReporterVisitor(ParentTracker), Origin(O),
+ ControlDeps(&O->getCFG()) {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int x = 0;
@@ -1810,9 +1861,9 @@
// isn't sufficient, because a new visitor is created for each tracked
// expression, hence the BugReport level set.
if (BR.addTrackedCondition(N)) {
- bugreporter::trackExpressionValue(
- N, Condition, BR, bugreporter::TrackingKind::Condition,
- /*EnableNullFPSuppression=*/false);
+ getParentTracker().track(Condition, N,
+ {bugreporter::TrackingKind::Condition,
+ /*EnableNullFPSuppression=*/false});
return constructDebugPieceForTrackedCondition(Condition, N, BRC);
}
}
@@ -1825,28 +1876,7 @@
// Implementation of trackExpressionValue.
//===----------------------------------------------------------------------===//
-static const MemRegion *getLocationRegionIfReference(const Expr *E,
- const ExplodedNode *N) {
- if (const auto *DR = dyn_cast<DeclRefExpr>(E)) {
- if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
- if (!VD->getType()->isReferenceType())
- return nullptr;
- ProgramStateManager &StateMgr = N->getState()->getStateManager();
- MemRegionManager &MRMgr = StateMgr.getRegionManager();
- return MRMgr.getVarRegion(VD, N->getLocationContext());
- }
- }
-
- // FIXME: This does not handle other kinds of null references,
- // for example, references from FieldRegions:
- // struct Wrapper { int &ref; };
- // Wrapper w = { *(int *)0 };
- // w.ref = 1;
-
- return nullptr;
-}
-
-/// \return A subexpression of {@code Ex} which represents the
+/// \return A subexpression of @c Ex which represents the
/// expression-of-interest.
static const Expr *peelOffOuterExpr(const Expr *Ex,
const ExplodedNode *N) {
@@ -1924,152 +1954,472 @@
return N;
}
+//===----------------------------------------------------------------------===//
+// Tracker implementation
+//===----------------------------------------------------------------------===//
+
+PathDiagnosticPieceRef StoreHandler::constructNote(StoreInfo SI,
+ BugReporterContext &BRC,
+ StringRef NodeText) {
+ // Construct a new PathDiagnosticPiece.
+ ProgramPoint P = SI.StoreSite->getLocation();
+ PathDiagnosticLocation L;
+ if (P.getAs<CallEnter>() && SI.SourceOfTheValue)
+ L = PathDiagnosticLocation(SI.SourceOfTheValue, BRC.getSourceManager(),
+ P.getLocationContext());
+
+ if (!L.isValid() || !L.asLocation().isValid())
+ L = PathDiagnosticLocation::create(P, BRC.getSourceManager());
+
+ if (!L.isValid() || !L.asLocation().isValid())
+ return nullptr;
+
+ return std::make_shared<PathDiagnosticEventPiece>(L, NodeText);
+}
+
+class DefaultStoreHandler final : public StoreHandler {
+public:
+ using StoreHandler::StoreHandler;
+
+ PathDiagnosticPieceRef handle(StoreInfo SI, BugReporterContext &BRC,
+ TrackingOptions Opts) override {
+ // Okay, we've found the binding. Emit an appropriate message.
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream OS(Buffer);
+
+ switch (SI.StoreKind) {
+ case StoreInfo::Initialization:
+ case StoreInfo::BlockCapture:
+ showBRDiagnostics(OS, SI);
+ break;
+ case StoreInfo::CallArgument:
+ showBRParamDiagnostics(OS, SI);
+ break;
+ case StoreInfo::Assignment:
+ showBRDefaultDiagnostics(OS, SI);
+ break;
+ }
+
+ if (Opts.Kind == bugreporter::TrackingKind::Condition)
+ OS << WillBeUsedForACondition;
+
+ return constructNote(SI, BRC, OS.str());
+ }
+};
+
+class ControlDependencyHandler final : public ExpressionHandler {
+public:
+ using ExpressionHandler::ExpressionHandler;
+
+ Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
+ const ExplodedNode *LVNode,
+ TrackingOptions Opts) override {
+ PathSensitiveBugReport &Report = getParentTracker().getReport();
+
+ // We only track expressions if we believe that they are important. Chances
+ // are good that control dependencies to the tracking point are also
+ // important because of this, let's explain why we believe control reached
+ // this point.
+ // TODO: Shouldn't we track control dependencies of every bug location,
+ // rather than only tracked expressions?
+ if (LVNode->getState()
+ ->getAnalysisManager()
+ .getAnalyzerOptions()
+ .ShouldTrackConditions) {
+ Report.addVisitor<TrackControlDependencyCondBRVisitor>(
+ &getParentTracker(), InputNode);
+ return {/*FoundSomethingToTrack=*/true};
+ }
+
+ return {};
+ }
+};
+
+class NilReceiverHandler final : public ExpressionHandler {
+public:
+ using ExpressionHandler::ExpressionHandler;
+
+ Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
+ const ExplodedNode *LVNode,
+ TrackingOptions Opts) override {
+ // The message send could be nil due to the receiver being nil.
+ // At this point in the path, the receiver should be live since we are at
+ // the message send expr. If it is nil, start tracking it.
+ if (const Expr *Receiver =
+ NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
+ return getParentTracker().track(Receiver, LVNode, Opts);
+
+ return {};
+ }
+};
+
+class ArrayIndexHandler final : public ExpressionHandler {
+public:
+ using ExpressionHandler::ExpressionHandler;
+
+ Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
+ const ExplodedNode *LVNode,
+ TrackingOptions Opts) override {
+ // Track the index if this is an array subscript.
+ if (const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
+ return getParentTracker().track(
+ Arr->getIdx(), LVNode,
+ {Opts.Kind, /*EnableNullFPSuppression*/ false});
+
+ return {};
+ }
+};
+
+// TODO: extract it into more handlers
+class InterestingLValueHandler final : public ExpressionHandler {
+public:
+ using ExpressionHandler::ExpressionHandler;
+
+ Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
+ const ExplodedNode *LVNode,
+ TrackingOptions Opts) override {
+ ProgramStateRef LVState = LVNode->getState();
+ const StackFrameContext *SFC = LVNode->getStackFrame();
+ PathSensitiveBugReport &Report = getParentTracker().getReport();
+ Tracker::Result Result;
+
+ // See if the expression we're interested refers to a variable.
+ // If so, we can track both its contents and constraints on its value.
+ if (ExplodedGraph::isInterestingLValueExpr(Inner)) {
+ SVal LVal = LVNode->getSVal(Inner);
+
+ const MemRegion *RR = getLocationRegionIfReference(Inner, LVNode);
+ bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
+
+ // If this is a C++ reference to a null pointer, we are tracking the
+ // pointer. In addition, we should find the store at which the reference
+ // got initialized.
+ if (RR && !LVIsNull)
+ Result.combineWith(getParentTracker().track(LVal, RR, Opts, SFC));
+
+ // In case of C++ references, we want to differentiate between a null
+ // reference and reference to null pointer.
+ // If the LVal is null, check if we are dealing with null reference.
+ // For those, we want to track the location of the reference.
+ const MemRegion *R =
+ (RR && LVIsNull) ? RR : LVNode->getSVal(Inner).getAsRegion();
+
+ if (R) {
+
+ // Mark both the variable region and its contents as interesting.
+ SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
+ Report.addVisitor<NoStoreFuncVisitor>(cast<SubRegion>(R), Opts.Kind);
+
+ // When we got here, we do have something to track, and we will
+ // interrupt.
+ Result.FoundSomethingToTrack = true;
+ Result.WasInterrupted = true;
+
+ MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
+ LVNode, R, Opts.EnableNullFPSuppression, Report, V);
+
+ Report.markInteresting(V, Opts.Kind);
+ Report.addVisitor<UndefOrNullArgVisitor>(R);
+
+ // If the contents are symbolic and null, find out when they became
+ // null.
+ if (V.getAsLocSymbol(/*IncludeBaseRegions=*/true))
+ if (LVState->isNull(V).isConstrainedTrue())
+ Report.addVisitor<TrackConstraintBRVisitor>(V.castAs<DefinedSVal>(),
+ false);
+
+ // Add visitor, which will suppress inline defensive checks.
+ if (auto DV = V.getAs<DefinedSVal>())
+ if (!DV->isZeroConstant() && Opts.EnableNullFPSuppression)
+ // Note that LVNode may be too late (i.e., too far from the
+ // InputNode) because the lvalue may have been computed before the
+ // inlined call was evaluated. InputNode may as well be too early
+ // here, because the symbol is already dead; this, however, is fine
+ // because we can still find the node in which it collapsed to null
+ // previously.
+ Report.addVisitor<SuppressInlineDefensiveChecksVisitor>(*DV,
+ InputNode);
+ getParentTracker().track(V, R, Opts, SFC);
+ }
+ }
+
+ return Result;
+ }
+};
+
+/// Adds a ReturnVisitor if the given statement represents a call that was
+/// inlined.
+///
+/// This will search back through the ExplodedGraph, starting from the given
+/// node, looking for when the given statement was processed. If it turns out
+/// the statement is a call that was inlined, we add the visitor to the
+/// bug report, so it can print a note later.
+class InlinedFunctionCallHandler final : public ExpressionHandler {
+ using ExpressionHandler::ExpressionHandler;
+
+ Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
+ const ExplodedNode *ExprNode,
+ TrackingOptions Opts) override {
+ if (!CallEvent::isCallStmt(E))
+ return {};
+
+ // First, find when we processed the statement.
+ // If we work with a 'CXXNewExpr' that is going to be purged away before
+ // its call take place. We would catch that purge in the last condition
+ // as a 'StmtPoint' so we have to bypass it.
+ const bool BypassCXXNewExprEval = isa<CXXNewExpr>(E);
+
+ // This is moving forward when we enter into another context.
+ const StackFrameContext *CurrentSFC = ExprNode->getStackFrame();
+
+ do {
+ // If that is satisfied we found our statement as an inlined call.
+ if (Optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>())
+ if (CEE->getCalleeContext()->getCallSite() == E)
+ break;
+
+ // Try to move forward to the end of the call-chain.
+ ExprNode = ExprNode->getFirstPred();
+ if (!ExprNode)
+ break;
+
+ const StackFrameContext *PredSFC = ExprNode->getStackFrame();
+
+ // If that is satisfied we found our statement.
+ // FIXME: This code currently bypasses the call site for the
+ // conservatively evaluated allocator.
+ if (!BypassCXXNewExprEval)
+ if (Optional<StmtPoint> SP = ExprNode->getLocationAs<StmtPoint>())
+ // See if we do not enter into another context.
+ if (SP->getStmt() == E && CurrentSFC == PredSFC)
+ break;
+
+ CurrentSFC = PredSFC;
+ } while (ExprNode->getStackFrame() == CurrentSFC);
+
+ // Next, step over any post-statement checks.
+ while (ExprNode && ExprNode->getLocation().getAs<PostStmt>())
+ ExprNode = ExprNode->getFirstPred();
+ if (!ExprNode)
+ return {};
+
+ // Finally, see if we inlined the call.
+ Optional<CallExitEnd> CEE = ExprNode->getLocationAs<CallExitEnd>();
+ if (!CEE)
+ return {};
+
+ const StackFrameContext *CalleeContext = CEE->getCalleeContext();
+ if (CalleeContext->getCallSite() != E)
+ return {};
+
+ // Check the return value.
+ ProgramStateRef State = ExprNode->getState();
+ SVal RetVal = ExprNode->getSVal(E);
+
+ // Handle cases where a reference is returned and then immediately used.
+ if (cast<Expr>(E)->isGLValue())
+ if (Optional<Loc> LValue = RetVal.getAs<Loc>())
+ RetVal = State->getSVal(*LValue);
+
+ // See if the return value is NULL. If so, suppress the report.
+ AnalyzerOptions &Options = State->getAnalysisManager().options;
+
+ bool EnableNullFPSuppression = false;
+ if (Opts.EnableNullFPSuppression && Options.ShouldSuppressNullReturnPaths)
+ if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
+ EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
+
+ PathSensitiveBugReport &Report = getParentTracker().getReport();
+ Report.addVisitor<ReturnVisitor>(&getParentTracker(), CalleeContext,
+ EnableNullFPSuppression, Options,
+ Opts.Kind);
+ return {true};
+ }
+};
+
+class DefaultExpressionHandler final : public ExpressionHandler {
+public:
+ using ExpressionHandler::ExpressionHandler;
+
+ Tracker::Result handle(const Expr *Inner, const ExplodedNode *InputNode,
+ const ExplodedNode *LVNode,
+ TrackingOptions Opts) override {
+ ProgramStateRef LVState = LVNode->getState();
+ const StackFrameContext *SFC = LVNode->getStackFrame();
+ PathSensitiveBugReport &Report = getParentTracker().getReport();
+ Tracker::Result Result;
+
+ // If the expression is not an "lvalue expression", we can still
+ // track the constraints on its contents.
+ SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
+
+ // Is it a symbolic value?
+ if (auto L = V.getAs<loc::MemRegionVal>()) {
+ // FIXME: this is a hack for fixing a later crash when attempting to
+ // dereference a void* pointer.
+ // We should not try to dereference pointers at all when we don't care
+ // what is written inside the pointer.
+ bool CanDereference = true;
+ if (const auto *SR = L->getRegionAs<SymbolicRegion>()) {
+ if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
+ CanDereference = false;
+ } else if (L->getRegionAs<AllocaRegion>())
+ CanDereference = false;
+
+ // At this point we are dealing with the region's LValue.
+ // However, if the rvalue is a symbolic region, we should track it as
+ // well. Try to use the correct type when looking up the value.
+ SVal RVal;
+ if (ExplodedGraph::isInterestingLValueExpr(Inner))
+ RVal = LVState->getRawSVal(L.getValue(), Inner->getType());
+ else if (CanDereference)
+ RVal = LVState->getSVal(L->getRegion());
+
+ if (CanDereference) {
+ Report.addVisitor<UndefOrNullArgVisitor>(L->getRegion());
+ Result.FoundSomethingToTrack = true;
+
+ if (auto KV = RVal.getAs<KnownSVal>())
+ Result.combineWith(
+ getParentTracker().track(*KV, L->getRegion(), Opts, SFC));
+ }
+
+ const MemRegion *RegionRVal = RVal.getAsRegion();
+ if (isa_and_nonnull<SymbolicRegion>(RegionRVal)) {
+ Report.markInteresting(RegionRVal, Opts.Kind);
+ Report.addVisitor<TrackConstraintBRVisitor>(
+ loc::MemRegionVal(RegionRVal),
+ /*assumption=*/false);
+ Result.FoundSomethingToTrack = true;
+ }
+ }
+
+ return Result;
+ }
+};
+
+/// Attempts to add visitors to track an RValue expression back to its point of
+/// origin.
+class PRValueHandler final : public ExpressionHandler {
+public:
+ using ExpressionHandler::ExpressionHandler;
+
+ Tracker::Result handle(const Expr *E, const ExplodedNode *InputNode,
+ const ExplodedNode *ExprNode,
+ TrackingOptions Opts) override {
+ if (!E->isPRValue())
+ return {};
+
+ const ExplodedNode *RVNode = findNodeForExpression(ExprNode, E);
+ if (!RVNode)
+ return {};
+
+ ProgramStateRef RVState = RVNode->getState();
+ SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getLocationContext());
+ const auto *BO = dyn_cast<BinaryOperator>(E);
+
+ if (!BO || !BO->isMultiplicativeOp() || !V.isZeroConstant())
+ return {};
+
+ SVal RHSV = RVState->getSVal(BO->getRHS(), RVNode->getLocationContext());
+ SVal LHSV = RVState->getSVal(BO->getLHS(), RVNode->getLocationContext());
+
+ // Track both LHS and RHS of a multiplication.
+ Tracker::Result CombinedResult;
+ Tracker &Parent = getParentTracker();
+
+ const auto track = [&CombinedResult, &Parent, ExprNode, Opts](Expr *Inner) {
+ CombinedResult.combineWith(Parent.track(Inner, ExprNode, Opts));
+ };
+
+ if (BO->getOpcode() == BO_Mul) {
+ if (LHSV.isZeroConstant())
+ track(BO->getLHS());
+ if (RHSV.isZeroConstant())
+ track(BO->getRHS());
+ } else { // Track only the LHS of a division or a modulo.
+ if (LHSV.isZeroConstant())
+ track(BO->getLHS());
+ }
+
+ return CombinedResult;
+ }
+};
+
+Tracker::Tracker(PathSensitiveBugReport &Report) : Report(Report) {
+ // Default expression handlers.
+ addLowPriorityHandler<ControlDependencyHandler>();
+ addLowPriorityHandler<NilReceiverHandler>();
+ addLowPriorityHandler<ArrayIndexHandler>();
+ addLowPriorityHandler<InterestingLValueHandler>();
+ addLowPriorityHandler<InlinedFunctionCallHandler>();
+ addLowPriorityHandler<DefaultExpressionHandler>();
+ addLowPriorityHandler<PRValueHandler>();
+ // Default store handlers.
+ addHighPriorityHandler<DefaultStoreHandler>();
+}
+
+Tracker::Result Tracker::track(const Expr *E, const ExplodedNode *N,
+ TrackingOptions Opts) {
+ if (!E || !N)
+ return {};
+
+ const Expr *Inner = peelOffOuterExpr(E, N);
+ const ExplodedNode *LVNode = findNodeForExpression(N, Inner);
+ if (!LVNode)
+ return {};
+
+ Result CombinedResult;
+ // Iterate through the handlers in the order according to their priorities.
+ for (ExpressionHandlerPtr &Handler : ExpressionHandlers) {
+ CombinedResult.combineWith(Handler->handle(Inner, N, LVNode, Opts));
+ if (CombinedResult.WasInterrupted) {
+ // There is no need to confuse our users here.
+ // We got interrupted, but our users don't need to know about it.
+ CombinedResult.WasInterrupted = false;
+ break;
+ }
+ }
+
+ return CombinedResult;
+}
+
+Tracker::Result Tracker::track(SVal V, const MemRegion *R, TrackingOptions Opts,
+ const StackFrameContext *Origin) {
+ if (auto KV = V.getAs<KnownSVal>()) {
+ Report.addVisitor<StoreSiteFinder>(this, *KV, R, Opts, Origin);
+ return {true};
+ }
+ return {};
+}
+
+PathDiagnosticPieceRef Tracker::handle(StoreInfo SI, BugReporterContext &BRC,
+ TrackingOptions Opts) {
+ // Iterate through the handlers in the order according to their priorities.
+ for (StoreHandlerPtr &Handler : StoreHandlers) {
+ if (PathDiagnosticPieceRef Result = Handler->handle(SI, BRC, Opts))
+ // If the handler produced a non-null piece, return it.
+ // There is no need in asking other handlers.
+ return Result;
+ }
+ return {};
+}
+
bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
const Expr *E,
- PathSensitiveBugReport &report,
- bugreporter::TrackingKind TKind,
- bool EnableNullFPSuppression) {
- if (!E || !InputNode)
- return false;
+ PathSensitiveBugReport &Report,
+ TrackingOptions Opts) {
+ return Tracker::create(Report)
+ ->track(E, InputNode, Opts)
+ .FoundSomethingToTrack;
+}
- const Expr *Inner = peelOffOuterExpr(E, InputNode);
- const ExplodedNode *LVNode = findNodeForExpression(InputNode, Inner);
- if (!LVNode)
- return false;
-
- ProgramStateRef LVState = LVNode->getState();
- const StackFrameContext *SFC = LVNode->getStackFrame();
-
- // We only track expressions if we believe that they are important. Chances
- // are good that control dependencies to the tracking point are also improtant
- // because of this, let's explain why we believe control reached this point.
- // TODO: Shouldn't we track control dependencies of every bug location, rather
- // than only tracked expressions?
- if (LVState->getAnalysisManager().getAnalyzerOptions().ShouldTrackConditions)
- report.addVisitor(std::make_unique<TrackControlDependencyCondBRVisitor>(
- InputNode));
-
- // The message send could be nil due to the receiver being nil.
- // At this point in the path, the receiver should be live since we are at the
- // message send expr. If it is nil, start tracking it.
- if (const Expr *Receiver = NilReceiverBRVisitor::getNilReceiver(Inner, LVNode))
- trackExpressionValue(
- LVNode, Receiver, report, TKind, EnableNullFPSuppression);
-
- // Track the index if this is an array subscript.
- if (const auto *Arr = dyn_cast<ArraySubscriptExpr>(Inner))
- trackExpressionValue(
- LVNode, Arr->getIdx(), report, TKind, /*EnableNullFPSuppression*/false);
-
- // See if the expression we're interested refers to a variable.
- // If so, we can track both its contents and constraints on its value.
- if (ExplodedGraph::isInterestingLValueExpr(Inner)) {
- SVal LVal = LVNode->getSVal(Inner);
-
- const MemRegion *RR = getLocationRegionIfReference(Inner, LVNode);
- bool LVIsNull = LVState->isNull(LVal).isConstrainedTrue();
-
- // If this is a C++ reference to a null pointer, we are tracking the
- // pointer. In addition, we should find the store at which the reference
- // got initialized.
- if (RR && !LVIsNull)
- if (auto KV = LVal.getAs<KnownSVal>())
- report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
- *KV, RR, EnableNullFPSuppression, TKind, SFC));
-
- // In case of C++ references, we want to differentiate between a null
- // reference and reference to null pointer.
- // If the LVal is null, check if we are dealing with null reference.
- // For those, we want to track the location of the reference.
- const MemRegion *R = (RR && LVIsNull) ? RR :
- LVNode->getSVal(Inner).getAsRegion();
-
- if (R) {
-
- // Mark both the variable region and its contents as interesting.
- SVal V = LVState->getRawSVal(loc::MemRegionVal(R));
- report.addVisitor(
- std::make_unique<NoStoreFuncVisitor>(cast<SubRegion>(R), TKind));
-
- MacroNullReturnSuppressionVisitor::addMacroVisitorIfNecessary(
- LVNode, R, EnableNullFPSuppression, report, V);
-
- report.markInteresting(V, TKind);
- report.addVisitor(std::make_unique<UndefOrNullArgVisitor>(R));
-
- // If the contents are symbolic and null, find out when they became null.
- if (V.getAsLocSymbol(/*IncludeBaseRegions=*/true))
- if (LVState->isNull(V).isConstrainedTrue())
- report.addVisitor(std::make_unique<TrackConstraintBRVisitor>(
- V.castAs<DefinedSVal>(), false));
-
- // Add visitor, which will suppress inline defensive checks.
- if (auto DV = V.getAs<DefinedSVal>())
- if (!DV->isZeroConstant() && EnableNullFPSuppression) {
- // Note that LVNode may be too late (i.e., too far from the InputNode)
- // because the lvalue may have been computed before the inlined call
- // was evaluated. InputNode may as well be too early here, because
- // the symbol is already dead; this, however, is fine because we can
- // still find the node in which it collapsed to null previously.
- report.addVisitor(
- std::make_unique<SuppressInlineDefensiveChecksVisitor>(
- *DV, InputNode));
- }
-
- if (auto KV = V.getAs<KnownSVal>())
- report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
- *KV, R, EnableNullFPSuppression, TKind, SFC));
- return true;
- }
- }
-
- // If the expression is not an "lvalue expression", we can still
- // track the constraints on its contents.
- SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
-
- ReturnVisitor::addVisitorIfNecessary(
- LVNode, Inner, report, EnableNullFPSuppression, TKind);
-
- // Is it a symbolic value?
- if (auto L = V.getAs<loc::MemRegionVal>()) {
- // FIXME: this is a hack for fixing a later crash when attempting to
- // dereference a void* pointer.
- // We should not try to dereference pointers at all when we don't care
- // what is written inside the pointer.
- bool CanDereference = true;
- if (const auto *SR = L->getRegionAs<SymbolicRegion>()) {
- if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
- CanDereference = false;
- } else if (L->getRegionAs<AllocaRegion>())
- CanDereference = false;
-
- // At this point we are dealing with the region's LValue.
- // However, if the rvalue is a symbolic region, we should track it as well.
- // Try to use the correct type when looking up the value.
- SVal RVal;
- if (ExplodedGraph::isInterestingLValueExpr(Inner))
- RVal = LVState->getRawSVal(L.getValue(), Inner->getType());
- else if (CanDereference)
- RVal = LVState->getSVal(L->getRegion());
-
- if (CanDereference) {
- report.addVisitor(
- std::make_unique<UndefOrNullArgVisitor>(L->getRegion()));
-
- if (auto KV = RVal.getAs<KnownSVal>())
- report.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
- *KV, L->getRegion(), EnableNullFPSuppression, TKind, SFC));
- }
-
- const MemRegion *RegionRVal = RVal.getAsRegion();
- if (RegionRVal && isa<SymbolicRegion>(RegionRVal)) {
- report.markInteresting(RegionRVal, TKind);
- report.addVisitor(std::make_unique<TrackConstraintBRVisitor>(
- loc::MemRegionVal(RegionRVal), /*assumption=*/false));
- }
- }
- return true;
+void bugreporter::trackStoredValue(KnownSVal V, const MemRegion *R,
+ PathSensitiveBugReport &Report,
+ TrackingOptions Opts,
+ const StackFrameContext *Origin) {
+ Tracker::create(Report)->track(V, R, Opts, Origin);
}
//===----------------------------------------------------------------------===//
@@ -2118,9 +2468,9 @@
// The receiver was nil, and hence the method was skipped.
// Register a BugReporterVisitor to issue a message telling us how
// the receiver was null.
- bugreporter::trackExpressionValue(
- N, Receiver, BR, bugreporter::TrackingKind::Thorough,
- /*EnableNullFPSuppression*/ false);
+ bugreporter::trackExpressionValue(N, Receiver, BR,
+ {bugreporter::TrackingKind::Thorough,
+ /*EnableNullFPSuppression*/ false});
// Issue a message saying that the method was skipped.
PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
N->getLocationContext());
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CMakeLists.txt b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CMakeLists.txt
index d947d41..73ddec0 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -20,7 +20,7 @@
CommonBugCategories.cpp
ConstraintManager.cpp
CoreEngine.cpp
- DynamicSize.cpp
+ DynamicExtent.cpp
DynamicType.cpp
Environment.cpp
ExplodedGraph.cpp
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index a55d930..3785f49 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -47,6 +47,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -86,7 +87,7 @@
case VK_XValue:
ResultTy = Ctx.getRValueReferenceType(ResultTy);
break;
- case VK_RValue:
+ case VK_PRValue:
// No adjustment is necessary.
break;
}
@@ -466,6 +467,42 @@
llvm_unreachable("unknown callable kind");
}
+static bool isTransparentUnion(QualType T) {
+ const RecordType *UT = T->getAsUnionType();
+ return UT && UT->getDecl()->hasAttr<TransparentUnionAttr>();
+}
+
+// In some cases, symbolic cases should be transformed before we associate
+// them with parameters. This function incapsulates such cases.
+static SVal processArgument(SVal Value, const Expr *ArgumentExpr,
+ const ParmVarDecl *Parameter, SValBuilder &SVB) {
+ QualType ParamType = Parameter->getType();
+ QualType ArgumentType = ArgumentExpr->getType();
+
+ // Transparent unions allow users to easily convert values of union field
+ // types into union-typed objects.
+ //
+ // Also, more importantly, they allow users to define functions with different
+ // different parameter types, substituting types matching transparent union
+ // field types with the union type itself.
+ //
+ // Here, we check specifically for latter cases and prevent binding
+ // field-typed values to union-typed regions.
+ if (isTransparentUnion(ParamType) &&
+ // Let's check that we indeed trying to bind different types.
+ !isTransparentUnion(ArgumentType)) {
+ BasicValueFactory &BVF = SVB.getBasicValueFactory();
+
+ llvm::ImmutableList<SVal> CompoundSVals = BVF.getEmptySValList();
+ CompoundSVals = BVF.prependSVal(Value, CompoundSVals);
+
+ // Wrap it with compound value.
+ return SVB.makeCompoundVal(ParamType, CompoundSVals);
+ }
+
+ return Value;
+}
+
static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx,
CallEvent::BindingsTy &Bindings,
SValBuilder &SVB,
@@ -490,10 +527,12 @@
// determined in compile-time but not represented as arg-expressions,
// which makes getArgSVal() fail and return UnknownVal.
SVal ArgVal = Call.getArgSVal(Idx);
+ const Expr *ArgExpr = Call.getArgExpr(Idx);
if (!ArgVal.isUnknown()) {
Loc ParamLoc = SVB.makeLoc(
MRMgr.getParamVarRegion(Call.getOriginExpr(), Idx, CalleeCtx));
- Bindings.push_back(std::make_pair(ParamLoc, ArgVal));
+ Bindings.push_back(
+ std::make_pair(ParamLoc, processArgument(ArgVal, ArgExpr, *I, SVB)));
}
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
index 3d44d2c..3d64ce4 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
@@ -19,6 +19,10 @@
using namespace ento;
const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const {
+ const FunctionDecl *D = CE->getDirectCallee();
+ if (D)
+ return D;
+
const Expr *Callee = CE->getCallee();
SVal L = Pred->getSVal(Callee);
return L.getAsFunctionDecl();
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index cae7288..626ae1a 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -148,5 +148,39 @@
return IntValue.getSExtValue();
}
+OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,
+ bool IsBinary) {
+ llvm::StringMap<BinaryOperatorKind> BinOps{
+#define BINARY_OPERATION(Name, Spelling) {Spelling, BO_##Name},
+#include "clang/AST/OperationKinds.def"
+ };
+ llvm::StringMap<UnaryOperatorKind> UnOps{
+#define UNARY_OPERATION(Name, Spelling) {Spelling, UO_##Name},
+#include "clang/AST/OperationKinds.def"
+ };
+
+ switch (OOK) {
+#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
+ case OO_##Name: \
+ if (IsBinary) { \
+ auto BinOpIt = BinOps.find(Spelling); \
+ if (BinOpIt != BinOps.end()) \
+ return OperatorKind(BinOpIt->second); \
+ else \
+ llvm_unreachable("operator was expected to be binary but is not"); \
+ } else { \
+ auto UnOpIt = UnOps.find(Spelling); \
+ if (UnOpIt != UnOps.end()) \
+ return OperatorKind(UnOpIt->second); \
+ else \
+ llvm_unreachable("operator was expected to be unary but is not"); \
+ } \
+ break;
+#include "clang/Basic/OperatorKinds.def"
+ default:
+ llvm_unreachable("unexpected operator kind");
+ }
+}
+
} // namespace ento
} // namespace clang
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 86cecf6..e09399a 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -33,21 +33,20 @@
using namespace ento;
bool CheckerManager::hasPathSensitiveCheckers() const {
- return !StmtCheckers.empty() ||
- !PreObjCMessageCheckers.empty() ||
- !PostObjCMessageCheckers.empty() ||
- !PreCallCheckers.empty() ||
- !PostCallCheckers.empty() ||
- !LocationCheckers.empty() ||
- !BindCheckers.empty() ||
- !EndAnalysisCheckers.empty() ||
- !EndFunctionCheckers.empty() ||
- !BranchConditionCheckers.empty() ||
- !LiveSymbolsCheckers.empty() ||
- !DeadSymbolsCheckers.empty() ||
- !RegionChangesCheckers.empty() ||
- !EvalAssumeCheckers.empty() ||
- !EvalCallCheckers.empty();
+ const auto IfAnyAreNonEmpty = [](const auto &... Callbacks) -> bool {
+ bool Result = false;
+ // FIXME: Use fold expressions in C++17.
+ LLVM_ATTRIBUTE_UNUSED int Unused[]{0, (Result |= !Callbacks.empty())...};
+ return Result;
+ };
+ return IfAnyAreNonEmpty(
+ StmtCheckers, PreObjCMessageCheckers, ObjCMessageNilCheckers,
+ PostObjCMessageCheckers, PreCallCheckers, PostCallCheckers,
+ LocationCheckers, BindCheckers, EndAnalysisCheckers,
+ BeginFunctionCheckers, EndFunctionCheckers, BranchConditionCheckers,
+ NewAllocatorCheckers, LiveSymbolsCheckers, DeadSymbolsCheckers,
+ RegionChangesCheckers, PointerEscapeCheckers, EvalAssumeCheckers,
+ EvalCallCheckers, EndOfTranslationUnitCheckers);
}
void CheckerManager::finishedCheckerRegistration() {
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CommonBugCategories.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CommonBugCategories.cpp
index a601370..d12c35e 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CommonBugCategories.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CommonBugCategories.cpp
@@ -20,7 +20,9 @@
const char *const MemoryError = "Memory error";
const char *const UnixAPI = "Unix API";
const char *const CXXObjectLifecycle = "C++ object lifecycle";
+const char *const CXXMoveSemantics = "C++ move semantics";
const char *const SecurityError = "Security error";
+const char *const UnusedCode = "Unused code";
} // namespace categories
} // namespace ento
} // namespace clang
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 70deb13..bc939d2 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -219,13 +219,14 @@
// and we're taking the path that skips virtual base constructors.
if (L.getSrc()->getTerminator().isVirtualBaseBranch() &&
L.getDst() == *L.getSrc()->succ_begin()) {
- ProgramPoint P = L.withTag(getNoteTags().makeNoteTag(
+ ProgramPoint P = L.withTag(getDataTags().make<NoteTag>(
[](BugReporterContext &, PathSensitiveBugReport &) -> std::string {
// TODO: Just call out the name of the most derived class
// when we know it.
return "Virtual base initialization skipped because "
"it has already been handled by the most derived class";
- }, /*IsPrunable=*/true));
+ },
+ /*IsPrunable=*/true));
// Perform the transition.
ExplodedNodeSet Dst;
NodeBuilder Bldr(Pred, Dst, BuilderCtx);
@@ -349,6 +350,7 @@
HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
return;
+ case Stmt::SEHLeaveStmtClass:
case Stmt::ContinueStmtClass:
case Stmt::BreakStmtClass:
case Stmt::GotoStmtClass:
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
new file mode 100644
index 0000000..db9698b
--- /dev/null
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
@@ -0,0 +1,92 @@
+//===- DynamicExtent.cpp - Dynamic extent related APIs ----------*- 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 defines APIs that track and query dynamic extent information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+
+REGISTER_MAP_WITH_PROGRAMSTATE(DynamicExtentMap, const clang::ento::MemRegion *,
+ clang::ento::DefinedOrUnknownSVal)
+
+namespace clang {
+namespace ento {
+
+DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,
+ const MemRegion *MR, SValBuilder &SVB) {
+ MR = MR->StripCasts();
+
+ if (const DefinedOrUnknownSVal *Size = State->get<DynamicExtentMap>(MR))
+ return *Size;
+
+ return MR->getMemRegionManager().getStaticSize(MR, SVB);
+}
+
+DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB) {
+ return SVB.makeIntVal(SVB.getContext().getTypeSizeInChars(Ty).getQuantity(),
+ SVB.getArrayIndexType());
+}
+
+DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
+ const MemRegion *MR,
+ SValBuilder &SVB,
+ QualType ElementTy) {
+ MR = MR->StripCasts();
+
+ DefinedOrUnknownSVal Size = getDynamicExtent(State, MR, SVB);
+ SVal ElementSize = getElementExtent(ElementTy, SVB);
+
+ SVal ElementCount =
+ SVB.evalBinOp(State, BO_Div, Size, ElementSize, SVB.getArrayIndexType());
+
+ return ElementCount.castAs<DefinedOrUnknownSVal>();
+}
+
+SVal getDynamicExtentWithOffset(ProgramStateRef State, SVal BufV) {
+ SValBuilder &SvalBuilder = State->getStateManager().getSValBuilder();
+ const MemRegion *MRegion = BufV.getAsRegion();
+ if (!MRegion)
+ return UnknownVal();
+ RegionOffset Offset = MRegion->getAsOffset();
+ if (Offset.hasSymbolicOffset())
+ return UnknownVal();
+ const MemRegion *BaseRegion = MRegion->getBaseRegion();
+ if (!BaseRegion)
+ return UnknownVal();
+
+ NonLoc OffsetInBytes = SvalBuilder.makeArrayIndex(
+ Offset.getOffset() /
+ MRegion->getMemRegionManager().getContext().getCharWidth());
+ DefinedOrUnknownSVal ExtentInBytes =
+ getDynamicExtent(State, BaseRegion, SvalBuilder);
+
+ return SvalBuilder.evalBinOp(State, BinaryOperator::Opcode::BO_Sub,
+ ExtentInBytes, OffsetInBytes,
+ SvalBuilder.getArrayIndexType());
+}
+
+ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR,
+ DefinedOrUnknownSVal Size, SValBuilder &SVB) {
+ MR = MR->StripCasts();
+
+ if (Size.isUnknown())
+ return State;
+
+ return State->set<DynamicExtentMap>(MR->StripCasts(), Size);
+}
+
+} // namespace ento
+} // namespace clang
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/DynamicSize.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/DynamicSize.cpp
deleted file mode 100644
index 8b2172d..0000000
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/DynamicSize.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- DynamicSize.cpp - Dynamic size related APIs --------------*- 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 defines APIs that track and query dynamic size information.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
-#include "clang/AST/Expr.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-
-namespace clang {
-namespace ento {
-
-DefinedOrUnknownSVal getDynamicSize(ProgramStateRef State, const MemRegion *MR,
- SValBuilder &SVB) {
- return MR->getMemRegionManager().getStaticSize(MR, SVB);
-}
-
-DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State,
- const MemRegion *MR,
- SValBuilder &SVB,
- QualType ElementTy) {
- MemRegionManager &MemMgr = MR->getMemRegionManager();
- ASTContext &Ctx = MemMgr.getContext();
-
- DefinedOrUnknownSVal Size = getDynamicSize(State, MR, SVB);
- SVal ElementSizeV = SVB.makeIntVal(
- Ctx.getTypeSizeInChars(ElementTy).getQuantity(), SVB.getArrayIndexType());
-
- SVal DivisionV =
- SVB.evalBinOp(State, BO_Div, Size, ElementSizeV, SVB.getArrayIndexType());
-
- return DivisionV.castAs<DefinedOrUnknownSVal>();
-}
-
-SVal getDynamicSizeWithOffset(ProgramStateRef State, const SVal &BufV) {
- SValBuilder &SvalBuilder = State->getStateManager().getSValBuilder();
- const MemRegion *MRegion = BufV.getAsRegion();
- if (!MRegion)
- return UnknownVal();
- RegionOffset Offset = MRegion->getAsOffset();
- if (Offset.hasSymbolicOffset())
- return UnknownVal();
- const MemRegion *BaseRegion = MRegion->getBaseRegion();
- if (!BaseRegion)
- return UnknownVal();
-
- NonLoc OffsetInBytes = SvalBuilder.makeArrayIndex(
- Offset.getOffset() /
- MRegion->getMemRegionManager().getContext().getCharWidth());
- DefinedOrUnknownSVal ExtentInBytes =
- getDynamicSize(State, BaseRegion, SvalBuilder);
-
- return SvalBuilder.evalBinOp(State, BinaryOperator::Opcode::BO_Sub,
- ExtentInBytes, OffsetInBytes,
- SvalBuilder.getArrayIndexType());
-}
-
-} // namespace ento
-} // namespace clang
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index f285b65..66332d3 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1238,6 +1238,7 @@
case Stmt::SEHExceptStmtClass:
case Stmt::SEHLeaveStmtClass:
case Stmt::SEHFinallyStmtClass:
+ case Stmt::OMPCanonicalLoopClass:
case Stmt::OMPParallelDirectiveClass:
case Stmt::OMPSimdDirectiveClass:
case Stmt::OMPForDirectiveClass:
@@ -1292,7 +1293,12 @@
case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
- case Stmt::CapturedStmtClass: {
+ case Stmt::OMPTileDirectiveClass:
+ case Stmt::OMPInteropDirectiveClass:
+ case Stmt::OMPDispatchDirectiveClass:
+ case Stmt::OMPMaskedDirectiveClass:
+ case Stmt::CapturedStmtClass:
+ case Stmt::OMPUnrollDirectiveClass: {
const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
Engine.addAbortedBlock(node, currBldrCtx->getBlock());
break;
@@ -1414,6 +1420,7 @@
case Stmt::OMPArraySectionExprClass:
case Stmt::OMPArrayShapingExprClass:
case Stmt::OMPIteratorExprClass:
+ case Stmt::SYCLUniqueStableNameExprClass:
case Stmt::TypeTraitExprClass: {
Bldr.takeNodes(Pred);
ExplodedNodeSet preVisit;
@@ -3137,8 +3144,8 @@
/// \p PreCallback: callback before break.
/// \p PostCallback: callback after break.
- /// \p Stop: stop iteration if returns {@code true}
- /// \return Whether {@code Stop} ever returned {@code true}.
+ /// \p Stop: stop iteration if returns @c true
+ /// \return Whether @c Stop ever returned @c true.
static bool traverseHiddenNodes(
const ExplodedNode *N,
llvm::function_ref<void(const ExplodedNode *)> PreCallback,
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 18d1b21..7ad3dca 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -282,29 +282,14 @@
return state;
}
-ProgramStateRef ExprEngine::handleLVectorSplat(
- ProgramStateRef state, const LocationContext* LCtx, const CastExpr* CastE,
- StmtNodeBuilder &Bldr, ExplodedNode* Pred) {
- // Recover some path sensitivity by conjuring a new value.
- QualType resultType = CastE->getType();
- if (CastE->isGLValue())
- resultType = getContext().getPointerType(resultType);
- SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx,
- resultType,
- currBldrCtx->blockCount());
- state = state->BindExpr(CastE, LCtx, result);
- Bldr.generateNode(CastE, Pred, state);
-
- return state;
-}
-
void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
ExplodedNodeSet dstPreStmt;
getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
- if (CastE->getCastKind() == CK_LValueToRValue) {
+ if (CastE->getCastKind() == CK_LValueToRValue ||
+ CastE->getCastKind() == CK_LValueToRValueBitCast) {
for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
I!=E; ++I) {
ExplodedNode *subExprNode = *I;
@@ -332,6 +317,7 @@
switch (CastE->getCastKind()) {
case CK_LValueToRValue:
+ case CK_LValueToRValueBitCast:
llvm_unreachable("LValueToRValue casts handled earlier.");
case CK_ToVoid:
continue;
@@ -380,7 +366,6 @@
case CK_Dependent:
case CK_ArrayToPointerDecay:
case CK_BitCast:
- case CK_LValueToRValueBitCast:
case CK_AddressSpaceConversion:
case CK_BooleanToSignedIntegral:
case CK_IntegralToPointer:
@@ -526,22 +511,28 @@
case CK_ReinterpretMemberPointer: {
SVal V = state->getSVal(Ex, LCtx);
if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) {
- SVal CastedPTMSV = svalBuilder.makePointerToMember(
- getBasicVals().accumCXXBase(
- llvm::make_range<CastExpr::path_const_iterator>(
- CastE->path_begin(), CastE->path_end()), *PTMSV));
+ SVal CastedPTMSV =
+ svalBuilder.makePointerToMember(getBasicVals().accumCXXBase(
+ CastE->path(), *PTMSV, CastE->getCastKind()));
state = state->BindExpr(CastE, LCtx, CastedPTMSV);
Bldr.generateNode(CastE, Pred, state);
continue;
}
// Explicitly proceed with default handler for this case cascade.
- state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred);
- continue;
}
+ LLVM_FALLTHROUGH;
// Various C++ casts that are not handled yet.
case CK_ToUnion:
+ case CK_MatrixCast:
case CK_VectorSplat: {
- state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred);
+ QualType resultType = CastE->getType();
+ if (CastE->isGLValue())
+ resultType = getContext().getPointerType(resultType);
+ SVal result = svalBuilder.conjureSymbolVal(
+ /*symbolTag=*/nullptr, CastE, LCtx, resultType,
+ currBldrCtx->blockCount());
+ state = state->BindExpr(CastE, LCtx, result);
+ Bldr.generateNode(CastE, Pred, state);
continue;
}
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 996d364..e6918e0 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -18,6 +18,7 @@
#include "clang/Analysis/ConstructionContext.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
@@ -689,16 +690,30 @@
// See if we need to conjure a heap pointer instead of
// a regular unknown pointer.
- bool IsHeapPointer = false;
- if (const auto *CNE = dyn_cast<CXXNewExpr>(E))
- if (CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
- // FIXME: Delegate this to evalCall in MallocChecker?
- IsHeapPointer = true;
+ const auto *CNE = dyn_cast<CXXNewExpr>(E);
+ if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
+ R = svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count);
+ const MemRegion *MR = R.getAsRegion()->StripCasts();
+
+ // Store the extent of the allocated object(s).
+ SVal ElementCount;
+ if (const Expr *SizeExpr = CNE->getArraySize().getValueOr(nullptr)) {
+ ElementCount = State->getSVal(SizeExpr, LCtx);
+ } else {
+ ElementCount = svalBuilder.makeIntVal(1, /*IsUnsigned=*/true);
}
- R = IsHeapPointer ? svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count)
- : svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy,
- Count);
+ SVal ElementSize = getElementExtent(CNE->getAllocatedType(), svalBuilder);
+
+ SVal Size =
+ svalBuilder.evalBinOp(State, BO_Mul, ElementCount, ElementSize,
+ svalBuilder.getArrayIndexType());
+
+ State = setDynamicExtent(State, MR, Size.castAs<DefinedOrUnknownSVal>(),
+ svalBuilder);
+ } else {
+ R = svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
+ }
}
return State->BindExpr(E, LCtx, R);
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 149459c..64fc32e 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -10,11 +10,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/IssueHash.h"
-#include "clang/Analysis/PathDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Stmt.h"
+#include "clang/Analysis/IssueHash.h"
+#include "clang/Analysis/MacroExpansionContext.h"
+#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
@@ -135,14 +136,16 @@
void ento::createHTMLDiagnosticConsumer(
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
const std::string &OutputDir, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions) {
// FIXME: HTML is currently our default output type, but if the output
// directory isn't specified, it acts like if it was in the minimal text
// output mode. This doesn't make much sense, we should have the minimal text
// as our default. In the case of backward compatibility concerns, this could
// be preserved with -analyzer-config-compatibility-mode=true.
- createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU);
+ createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU,
+ MacroExpansions);
// TODO: Emit an error here.
if (OutputDir.empty())
@@ -154,8 +157,10 @@
void ento::createHTMLSingleFileDiagnosticConsumer(
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
const std::string &OutputDir, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
- createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU);
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const clang::MacroExpansionContext &MacroExpansions) {
+ createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU,
+ MacroExpansions);
// TODO: Emit an error here.
if (OutputDir.empty())
@@ -167,13 +172,29 @@
void ento::createPlistHTMLDiagnosticConsumer(
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
const std::string &prefix, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions) {
createHTMLDiagnosticConsumer(
- DiagOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP,
- CTU);
- createPlistMultiFileDiagnosticConsumer(DiagOpts, C, prefix, PP, CTU);
+ DiagOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP, CTU,
+ MacroExpansions);
+ createPlistMultiFileDiagnosticConsumer(DiagOpts, C, prefix, PP, CTU,
+ MacroExpansions);
createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, prefix, PP,
- CTU);
+ CTU, MacroExpansions);
+}
+
+void ento::createSarifHTMLDiagnosticConsumer(
+ PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
+ const std::string &sarif_file, const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions) {
+ createHTMLDiagnosticConsumer(
+ DiagOpts, C, std::string(llvm::sys::path::parent_path(sarif_file)), PP,
+ CTU, MacroExpansions);
+ createSarifDiagnosticConsumer(DiagOpts, C, sarif_file, PP, CTU,
+ MacroExpansions);
+ createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, sarif_file,
+ PP, CTU, MacroExpansions);
}
//===----------------------------------------------------------------------===//
@@ -254,11 +275,11 @@
<< "' absolute: " << EC.message() << '\n';
return;
}
- if (std::error_code EC =
- llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) {
- llvm::errs() << "warning: could not create file in '" << Directory
- << "': " << EC.message() << '\n';
- return;
+ if (std::error_code EC = llvm::sys::fs::createUniqueFile(
+ Model, FD, ResultPath, llvm::sys::fs::OF_Text)) {
+ llvm::errs() << "warning: could not create file in '" << Directory
+ << "': " << EC.message() << '\n';
+ return;
}
} else {
int i = 1;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
index dc268e5..e5f4e9e 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp
@@ -79,14 +79,17 @@
return State;
}
-static internal::Matcher<Stmt> simpleCondition(StringRef BindName) {
- return binaryOperator(anyOf(hasOperatorName("<"), hasOperatorName(">"),
- hasOperatorName("<="), hasOperatorName(">="),
- hasOperatorName("!=")),
- hasEitherOperand(ignoringParenImpCasts(declRefExpr(
- to(varDecl(hasType(isInteger())).bind(BindName))))),
- hasEitherOperand(ignoringParenImpCasts(
- integerLiteral().bind("boundNum"))))
+static internal::Matcher<Stmt> simpleCondition(StringRef BindName,
+ StringRef RefName) {
+ return binaryOperator(
+ anyOf(hasOperatorName("<"), hasOperatorName(">"),
+ hasOperatorName("<="), hasOperatorName(">="),
+ hasOperatorName("!=")),
+ hasEitherOperand(ignoringParenImpCasts(
+ declRefExpr(to(varDecl(hasType(isInteger())).bind(BindName)))
+ .bind(RefName))),
+ hasEitherOperand(
+ ignoringParenImpCasts(integerLiteral().bind("boundNum"))))
.bind("conditionOperator");
}
@@ -138,7 +141,7 @@
static internal::Matcher<Stmt> forLoopMatcher() {
return forStmt(
- hasCondition(simpleCondition("initVarName")),
+ hasCondition(simpleCondition("initVarName", "initVarRef")),
// Initialization should match the form: 'int i = 6' or 'i = 42'.
hasLoopInit(
anyOf(declStmt(hasSingleDecl(
@@ -156,17 +159,52 @@
hasUnaryOperand(declRefExpr(
to(varDecl(allOf(equalsBoundNode("initVarName"),
hasType(isInteger())))))))),
- unless(hasBody(hasSuspiciousStmt("initVarName")))).bind("forLoop");
+ unless(hasBody(hasSuspiciousStmt("initVarName"))))
+ .bind("forLoop");
}
-static bool isPossiblyEscaped(const VarDecl *VD, ExplodedNode *N) {
- // Global variables assumed as escaped variables.
+static bool isCapturedByReference(ExplodedNode *N, const DeclRefExpr *DR) {
+
+ // Get the lambda CXXRecordDecl
+ assert(DR->refersToEnclosingVariableOrCapture());
+ const LocationContext *LocCtxt = N->getLocationContext();
+ const Decl *D = LocCtxt->getDecl();
+ const auto *MD = cast<CXXMethodDecl>(D);
+ assert(MD && MD->getParent()->isLambda() &&
+ "Captured variable should only be seen while evaluating a lambda");
+ const CXXRecordDecl *LambdaCXXRec = MD->getParent();
+
+ // Lookup the fields of the lambda
+ llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
+ FieldDecl *LambdaThisCaptureField;
+ LambdaCXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
+
+ // Check if the counter is captured by reference
+ const VarDecl *VD = cast<VarDecl>(DR->getDecl()->getCanonicalDecl());
+ assert(VD);
+ const FieldDecl *FD = LambdaCaptureFields[VD];
+ assert(FD && "Captured variable without a corresponding field");
+ return FD->getType()->isReferenceType();
+}
+
+// A loop counter is considered escaped if:
+// case 1: It is a global variable.
+// case 2: It is a reference parameter or a reference capture.
+// case 3: It is assigned to a non-const reference variable or parameter.
+// case 4: Has its address taken.
+static bool isPossiblyEscaped(ExplodedNode *N, const DeclRefExpr *DR) {
+ const VarDecl *VD = cast<VarDecl>(DR->getDecl()->getCanonicalDecl());
+ assert(VD);
+ // Case 1:
if (VD->hasGlobalStorage())
return true;
- const bool isParm = isa<ParmVarDecl>(VD);
- // Reference parameters are assumed as escaped variables.
- if (isParm && VD->getType()->isReferenceType())
+ const bool IsRefParamOrCapture =
+ isa<ParmVarDecl>(VD) || DR->refersToEnclosingVariableOrCapture();
+ // Case 2:
+ if ((DR->refersToEnclosingVariableOrCapture() &&
+ isCapturedByReference(N, DR)) ||
+ (IsRefParamOrCapture && VD->getType()->isReferenceType()))
return true;
while (!N->pred_empty()) {
@@ -189,6 +227,7 @@
// on VD and reference initialized by VD.
ASTContext &ASTCtx =
N->getLocationContext()->getAnalysisDeclContext()->getASTContext();
+ // Case 3 and 4:
auto Match =
match(stmt(anyOf(callByRef(equalsNode(VD)), getAddrTo(equalsNode(VD)),
assignedToRef(equalsNode(VD)))),
@@ -199,8 +238,8 @@
N = N->getFirstPred();
}
- // Parameter declaration will not be found.
- if (isParm)
+ // Reference parameter and reference capture will not be found.
+ if (IsRefParamOrCapture)
return false;
llvm_unreachable("Reached root without finding the declaration of VD");
@@ -218,7 +257,7 @@
if (Matches.empty())
return false;
- auto CounterVar = Matches[0].getNodeAs<VarDecl>("initVarName");
+ const auto *CounterVarRef = Matches[0].getNodeAs<DeclRefExpr>("initVarRef");
llvm::APInt BoundNum =
Matches[0].getNodeAs<IntegerLiteral>("boundNum")->getValue();
llvm::APInt InitNum =
@@ -235,7 +274,7 @@
maxStep = (BoundNum - InitNum).abs().getZExtValue();
// Check if the counter of the loop is not escaped before.
- return !isPossiblyEscaped(CounterVar->getCanonicalDecl(), Pred);
+ return !isPossiblyEscaped(Pred, CounterVarRef);
}
bool madeNewBranch(ExplodedNode *N, const Stmt *LoopStmt) {
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 455adf5..bd725ee 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -28,6 +28,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
@@ -729,13 +730,6 @@
// MemRegionManager methods.
//===----------------------------------------------------------------------===//
-static DefinedOrUnknownSVal getTypeSize(QualType Ty, ASTContext &Ctx,
- SValBuilder &SVB) {
- CharUnits Size = Ctx.getTypeSizeInChars(Ty);
- QualType SizeTy = SVB.getArrayIndexType();
- return SVB.makeIntVal(Size.getQuantity(), SizeTy);
-}
-
DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
SValBuilder &SVB) const {
const auto *SR = cast<SubRegion>(MR);
@@ -766,7 +760,7 @@
if (Ty->isIncompleteType())
return UnknownVal();
- return getTypeSize(Ty, Ctx, SVB);
+ return getElementExtent(Ty, SVB);
}
case MemRegion::FieldRegionKind: {
// Force callers to deal with bitfields explicitly.
@@ -774,7 +768,7 @@
return UnknownVal();
QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
- DefinedOrUnknownSVal Size = getTypeSize(Ty, Ctx, SVB);
+ DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB);
// A zero-length array at the end of a struct often stands for dynamically
// allocated extra memory.
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 35e320c..92104d6 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/IssueHash.h"
+#include "clang/Analysis/MacroExpansionContext.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/PlistSupport.h"
@@ -43,6 +44,7 @@
const std::string OutputFile;
const Preprocessor &PP;
const cross_tu::CrossTranslationUnitContext &CTU;
+ const MacroExpansionContext &MacroExpansions;
const bool SupportsCrossFileDiagnostics;
void printBugPath(llvm::raw_ostream &o, const FIDMap &FM,
@@ -52,6 +54,7 @@
PlistDiagnostics(PathDiagnosticConsumerOptions DiagOpts,
const std::string &OutputFile, const Preprocessor &PP,
const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions,
bool supportsMultipleFiles);
~PlistDiagnostics() override {}
@@ -80,14 +83,14 @@
const FIDMap& FM;
const Preprocessor &PP;
const cross_tu::CrossTranslationUnitContext &CTU;
+ const MacroExpansionContext &MacroExpansions;
llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;
public:
- PlistPrinter(const FIDMap& FM,
- const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU)
- : FM(FM), PP(PP), CTU(CTU) {
- }
+ PlistPrinter(const FIDMap &FM, const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions)
+ : FM(FM), PP(PP), CTU(CTU), MacroExpansions(MacroExpansions) {}
void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) {
ReportPiece(o, P, /*indent*/ 4, /*depth*/ 0, /*includeControlFlow*/ true);
@@ -154,28 +157,17 @@
} // end of anonymous namespace
-namespace {
-
-struct ExpansionInfo {
- std::string MacroName;
- std::string Expansion;
- ExpansionInfo(std::string N, std::string E)
- : MacroName(std::move(N)), Expansion(std::move(E)) {}
-};
-
-} // end of anonymous namespace
-
-/// Print coverage information to output stream {@code o}.
-/// May modify the used list of files {@code Fids} by inserting new ones.
+/// Print coverage information to output stream @c o.
+/// May modify the used list of files @c Fids by inserting new ones.
static void printCoverage(const PathDiagnostic *D,
unsigned InputIndentLevel,
SmallVectorImpl<FileID> &Fids,
FIDMap &FM,
llvm::raw_fd_ostream &o);
-static ExpansionInfo
-getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU);
+static Optional<StringRef> getExpandedMacro(
+ SourceLocation MacroLoc, const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions, const SourceManager &SM);
//===----------------------------------------------------------------------===//
// Methods of PlistPrinter.
@@ -388,7 +380,17 @@
for (const PathDiagnosticMacroPiece *P : MacroPieces) {
const SourceManager &SM = PP.getSourceManager();
- ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP, CTU);
+
+ SourceLocation MacroExpansionLoc =
+ P->getLocation().asLocation().getExpansionLoc();
+
+ const Optional<StringRef> MacroName =
+ MacroExpansions.getOriginalText(MacroExpansionLoc);
+ const Optional<StringRef> ExpansionText =
+ getExpandedMacro(MacroExpansionLoc, CTU, MacroExpansions, SM);
+
+ if (!MacroName.hasValue() || !ExpansionText.hasValue())
+ continue;
Indent(o, indent) << "<dict>\n";
++indent;
@@ -405,11 +407,11 @@
// Output the macro name.
Indent(o, indent) << "<key>name</key>";
- EmitString(o, EI.MacroName) << '\n';
+ EmitString(o, MacroName.getValue()) << '\n';
// Output what it expands into.
Indent(o, indent) << "<key>expansion</key>";
- EmitString(o, EI.Expansion) << '\n';
+ EmitString(o, ExpansionText.getValue()) << '\n';
// Finish up.
--indent;
@@ -482,8 +484,8 @@
// Static function definitions.
//===----------------------------------------------------------------------===//
-/// Print coverage information to output stream {@code o}.
-/// May modify the used list of files {@code Fids} by inserting new ones.
+/// Print coverage information to output stream @c o.
+/// May modify the used list of files @c Fids by inserting new ones.
static void printCoverage(const PathDiagnostic *D,
unsigned InputIndentLevel,
SmallVectorImpl<FileID> &Fids,
@@ -522,8 +524,9 @@
PlistDiagnostics::PlistDiagnostics(
PathDiagnosticConsumerOptions DiagOpts, const std::string &output,
const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU,
- bool supportsMultipleFiles)
+ const MacroExpansionContext &MacroExpansions, bool supportsMultipleFiles)
: DiagOpts(std::move(DiagOpts)), OutputFile(output), PP(PP), CTU(CTU),
+ MacroExpansions(MacroExpansions),
SupportsCrossFileDiagnostics(supportsMultipleFiles) {
// FIXME: Will be used by a later planned change.
(void)this->CTU;
@@ -532,36 +535,40 @@
void ento::createPlistDiagnosticConsumer(
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
const std::string &OutputFile, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions) {
// TODO: Emit an error here.
if (OutputFile.empty())
return;
C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU,
+ MacroExpansions,
/*supportsMultipleFiles=*/false));
createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,
- PP, CTU);
+ PP, CTU, MacroExpansions);
}
void ento::createPlistMultiFileDiagnosticConsumer(
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
const std::string &OutputFile, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions) {
// TODO: Emit an error here.
if (OutputFile.empty())
return;
C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU,
+ MacroExpansions,
/*supportsMultipleFiles=*/true));
createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,
- PP, CTU);
+ PP, CTU, MacroExpansions);
}
void PlistDiagnostics::printBugPath(llvm::raw_ostream &o, const FIDMap &FM,
const PathPieces &Path) {
- PlistPrinter Printer(FM, PP, CTU);
+ PlistPrinter Printer(FM, PP, CTU, MacroExpansions);
assert(std::is_partitioned(Path.begin(), Path.end(),
[](const PathDiagnosticPieceRef &E) {
return E->getKind() == PathDiagnosticPiece::Note;
@@ -653,7 +660,7 @@
// Open the file.
std::error_code EC;
- llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
llvm::errs() << "warning: could not create file: " << EC.message() << '\n';
return;
@@ -815,570 +822,17 @@
}
//===----------------------------------------------------------------------===//
-// Declarations of helper functions and data structures for expanding macros.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-using ArgTokensTy = llvm::SmallVector<Token, 2>;
-
-} // end of anonymous namespace
-
-LLVM_DUMP_METHOD static void dumpArgTokensToStream(llvm::raw_ostream &Out,
- const Preprocessor &PP,
- const ArgTokensTy &Toks);
-
-namespace {
-/// Maps unexpanded macro parameters to expanded arguments. A macro argument may
-/// need to expanded further when it is nested inside another macro.
-class MacroParamMap : public std::map<const IdentifierInfo *, ArgTokensTy> {
-public:
- void expandFromPrevMacro(const MacroParamMap &Super);
-
- LLVM_DUMP_METHOD void dump(const Preprocessor &PP) const {
- dumpToStream(llvm::errs(), PP);
- }
-
- LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &Out,
- const Preprocessor &PP) const;
-};
-
-struct MacroExpansionInfo {
- std::string Name;
- const MacroInfo *MI = nullptr;
- MacroParamMap ParamMap;
-
- MacroExpansionInfo(std::string N, const MacroInfo *MI, MacroParamMap M)
- : Name(std::move(N)), MI(MI), ParamMap(std::move(M)) {}
-};
-
-class TokenPrinter {
- llvm::raw_ostream &OS;
- const Preprocessor &PP;
-
- Token PrevTok, PrevPrevTok;
- TokenConcatenation ConcatInfo;
-
-public:
- TokenPrinter(llvm::raw_ostream &OS, const Preprocessor &PP)
- : OS(OS), PP(PP), ConcatInfo(PP) {
- PrevTok.setKind(tok::unknown);
- PrevPrevTok.setKind(tok::unknown);
- }
-
- void printToken(const Token &Tok);
-};
-
-/// Wrapper around a Lexer object that can lex tokens one-by-one. Its possible
-/// to "inject" a range of tokens into the stream, in which case the next token
-/// is retrieved from the next element of the range, until the end of the range
-/// is reached.
-class TokenStream {
-public:
- TokenStream(SourceLocation ExpanLoc, const SourceManager &SM,
- const LangOptions &LangOpts)
- : ExpanLoc(ExpanLoc) {
- FileID File;
- unsigned Offset;
- std::tie(File, Offset) = SM.getDecomposedLoc(ExpanLoc);
- llvm::MemoryBufferRef MB = SM.getBufferOrFake(File);
- const char *MacroNameTokenPos = MB.getBufferStart() + Offset;
-
- RawLexer = std::make_unique<Lexer>(SM.getLocForStartOfFile(File), LangOpts,
- MB.getBufferStart(), MacroNameTokenPos,
- MB.getBufferEnd());
- }
-
- void next(Token &Result) {
- if (CurrTokenIt == TokenRange.end()) {
- RawLexer->LexFromRawLexer(Result);
- return;
- }
- Result = *CurrTokenIt;
- CurrTokenIt++;
- }
-
- void injectRange(const ArgTokensTy &Range) {
- TokenRange = Range;
- CurrTokenIt = TokenRange.begin();
- }
-
- std::unique_ptr<Lexer> RawLexer;
- ArgTokensTy TokenRange;
- ArgTokensTy::iterator CurrTokenIt = TokenRange.begin();
- SourceLocation ExpanLoc;
-};
-
-} // end of anonymous namespace
-
-/// The implementation method of getMacroExpansion: It prints the expansion of
-/// a macro to \p Printer, and returns with the name of the macro.
-///
-/// Since macros can be nested in one another, this function may call itself
-/// recursively.
-///
-/// Unfortunately, macro arguments have to expanded manually. To understand why,
-/// observe the following example:
-///
-/// #define PRINT(x) print(x)
-/// #define DO_SOMETHING(str) PRINT(str)
-///
-/// DO_SOMETHING("Cute panda cubs.");
-///
-/// As we expand the last line, we'll immediately replace PRINT(str) with
-/// print(x). The information that both 'str' and 'x' refers to the same string
-/// is an information we have to forward, hence the argument \p PrevParamMap.
-///
-/// To avoid infinite recursion we maintain the already processed tokens in
-/// a set. This is carried as a parameter through the recursive calls. The set
-/// is extended with the currently processed token and after processing it, the
-/// token is removed. If the token is already in the set, then recursion stops:
-///
-/// #define f(y) x
-/// #define x f(x)
-static std::string getMacroNameAndPrintExpansion(
- TokenPrinter &Printer, SourceLocation MacroLoc, const Preprocessor &PP,
- const MacroParamMap &PrevParamMap,
- llvm::SmallPtrSet<IdentifierInfo *, 8> &AlreadyProcessedTokens);
-
-/// Retrieves the name of the macro and what it's parameters expand into
-/// at \p ExpanLoc.
-///
-/// For example, for the following macro expansion:
-///
-/// #define SET_TO_NULL(x) x = 0
-/// #define NOT_SUSPICIOUS(a) \
-/// { \
-/// int b = 0; \
-/// } \
-/// SET_TO_NULL(a)
-///
-/// int *ptr = new int(4);
-/// NOT_SUSPICIOUS(&ptr);
-/// *ptr = 5;
-///
-/// When \p ExpanLoc references the last line, the macro name "NOT_SUSPICIOUS"
-/// and the MacroArgMap map { (a, &ptr) } will be returned.
-///
-/// When \p ExpanLoc references "SET_TO_NULL(a)" within the definition of
-/// "NOT_SUSPICOUS", the macro name "SET_TO_NULL" and the MacroArgMap map
-/// { (x, a) } will be returned.
-static MacroExpansionInfo
-getMacroExpansionInfo(const MacroParamMap &PrevParamMap,
- SourceLocation ExpanLoc, const Preprocessor &PP);
-
-/// Retrieves the ')' token that matches '(' \p It points to.
-static MacroInfo::tokens_iterator getMatchingRParen(
- MacroInfo::tokens_iterator It,
- MacroInfo::tokens_iterator End);
-
-/// Retrieves the macro info for \p II refers to at \p Loc. This is important
-/// because macros can be redefined or undefined.
-static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
- const SourceManager &SM,
- const IdentifierInfo *II,
- SourceLocation Loc);
-
-//===----------------------------------------------------------------------===//
// Definitions of helper functions and methods for expanding macros.
//===----------------------------------------------------------------------===//
-static ExpansionInfo
-getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
-
- const Preprocessor *PPToUse = &PP;
- if (auto LocAndUnit = CTU.getImportedFromSourceLocation(MacroLoc)) {
- MacroLoc = LocAndUnit->first;
- PPToUse = &LocAndUnit->second->getPreprocessor();
+static Optional<StringRef>
+getExpandedMacro(SourceLocation MacroExpansionLoc,
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions,
+ const SourceManager &SM) {
+ if (auto CTUMacroExpCtx =
+ CTU.getMacroExpansionContextForSourceLocation(MacroExpansionLoc)) {
+ return CTUMacroExpCtx->getExpandedText(MacroExpansionLoc);
}
-
- llvm::SmallString<200> ExpansionBuf;
- llvm::raw_svector_ostream OS(ExpansionBuf);
- TokenPrinter Printer(OS, *PPToUse);
- llvm::SmallPtrSet<IdentifierInfo*, 8> AlreadyProcessedTokens;
-
- std::string MacroName = getMacroNameAndPrintExpansion(
- Printer, MacroLoc, *PPToUse, MacroParamMap{}, AlreadyProcessedTokens);
- return {MacroName, std::string(OS.str())};
-}
-
-static std::string getMacroNameAndPrintExpansion(
- TokenPrinter &Printer, SourceLocation MacroLoc, const Preprocessor &PP,
- const MacroParamMap &PrevParamMap,
- llvm::SmallPtrSet<IdentifierInfo *, 8> &AlreadyProcessedTokens) {
-
- const SourceManager &SM = PP.getSourceManager();
-
- MacroExpansionInfo MExpInfo =
- getMacroExpansionInfo(PrevParamMap, SM.getExpansionLoc(MacroLoc), PP);
- IdentifierInfo *MacroNameII = PP.getIdentifierInfo(MExpInfo.Name);
-
- // TODO: If the macro definition contains another symbol then this function is
- // called recursively. In case this symbol is the one being defined, it will
- // be an infinite recursion which is stopped by this "if" statement. However,
- // in this case we don't get the full expansion text in the Plist file. See
- // the test file where "value" is expanded to "garbage_" instead of
- // "garbage_value".
- if (!AlreadyProcessedTokens.insert(MacroNameII).second)
- return MExpInfo.Name;
-
- if (!MExpInfo.MI)
- return MExpInfo.Name;
-
- // Manually expand its arguments from the previous macro.
- MExpInfo.ParamMap.expandFromPrevMacro(PrevParamMap);
-
- // Iterate over the macro's tokens and stringify them.
- for (auto It = MExpInfo.MI->tokens_begin(), E = MExpInfo.MI->tokens_end();
- It != E; ++It) {
- Token T = *It;
-
- // If this token is not an identifier, we only need to print it.
- if (T.isNot(tok::identifier)) {
- Printer.printToken(T);
- continue;
- }
-
- const auto *II = T.getIdentifierInfo();
- assert(II &&
- "This token is an identifier but has no IdentifierInfo!");
-
- // If this token is a macro that should be expanded inside the current
- // macro.
- if (getMacroInfoForLocation(PP, SM, II, T.getLocation())) {
- getMacroNameAndPrintExpansion(Printer, T.getLocation(), PP,
- MExpInfo.ParamMap, AlreadyProcessedTokens);
-
- // If this is a function-like macro, skip its arguments, as
- // getExpandedMacro() already printed them. If this is the case, let's
- // first jump to the '(' token.
- auto N = std::next(It);
- if (N != E && N->is(tok::l_paren))
- It = getMatchingRParen(++It, E);
- continue;
- }
-
- // If this token is the current macro's argument, we should expand it.
- auto ParamToArgIt = MExpInfo.ParamMap.find(II);
- if (ParamToArgIt != MExpInfo.ParamMap.end()) {
- for (MacroInfo::tokens_iterator ArgIt = ParamToArgIt->second.begin(),
- ArgEnd = ParamToArgIt->second.end();
- ArgIt != ArgEnd; ++ArgIt) {
-
- // These tokens may still be macros, if that is the case, handle it the
- // same way we did above.
- const auto *ArgII = ArgIt->getIdentifierInfo();
- if (!ArgII) {
- Printer.printToken(*ArgIt);
- continue;
- }
-
- const auto *MI = PP.getMacroInfo(ArgII);
- if (!MI) {
- Printer.printToken(*ArgIt);
- continue;
- }
-
- getMacroNameAndPrintExpansion(Printer, ArgIt->getLocation(), PP,
- MExpInfo.ParamMap,
- AlreadyProcessedTokens);
- // Peek the next token if it is a tok::l_paren. This way we can decide
- // if this is the application or just a reference to a function maxro
- // symbol:
- //
- // #define apply(f) ...
- // #define func(x) ...
- // apply(func)
- // apply(func(42))
- auto N = std::next(ArgIt);
- if (N != ArgEnd && N->is(tok::l_paren))
- ArgIt = getMatchingRParen(++ArgIt, ArgEnd);
- }
- continue;
- }
-
- // If control reached here, then this token isn't a macro identifier, nor an
- // unexpanded macro argument that we need to handle, print it.
- Printer.printToken(T);
- }
-
- AlreadyProcessedTokens.erase(MacroNameII);
-
- return MExpInfo.Name;
-}
-
-static MacroExpansionInfo
-getMacroExpansionInfo(const MacroParamMap &PrevParamMap,
- SourceLocation ExpanLoc, const Preprocessor &PP) {
-
- const SourceManager &SM = PP.getSourceManager();
- const LangOptions &LangOpts = PP.getLangOpts();
-
- // First, we create a Lexer to lex *at the expansion location* the tokens
- // referring to the macro's name and its arguments.
- TokenStream TStream(ExpanLoc, SM, LangOpts);
-
- // Acquire the macro's name.
- Token TheTok;
- TStream.next(TheTok);
-
- std::string MacroName = PP.getSpelling(TheTok);
-
- const auto *II = PP.getIdentifierInfo(MacroName);
- assert(II && "Failed to acquire the IdentifierInfo for the macro!");
-
- const MacroInfo *MI = getMacroInfoForLocation(PP, SM, II, ExpanLoc);
- // assert(MI && "The macro must've been defined at it's expansion location!");
- //
- // We should always be able to obtain the MacroInfo in a given TU, but if
- // we're running the analyzer with CTU, the Preprocessor won't contain the
- // directive history (or anything for that matter) from another TU.
- // TODO: assert when we're not running with CTU.
- if (!MI)
- return { MacroName, MI, {} };
-
- // Acquire the macro's arguments at the expansion point.
- //
- // The rough idea here is to lex from the first left parentheses to the last
- // right parentheses, and map the macro's parameter to what they will be
- // expanded to. A macro argument may contain several token (like '3 + 4'), so
- // we'll lex until we find a tok::comma or tok::r_paren, at which point we
- // start lexing the next argument or finish.
- ArrayRef<const IdentifierInfo *> MacroParams = MI->params();
- if (MacroParams.empty())
- return { MacroName, MI, {} };
-
- TStream.next(TheTok);
- // When this is a token which expands to another macro function then its
- // parentheses are not at its expansion locaiton. For example:
- //
- // #define foo(x) int bar() { return x; }
- // #define apply_zero(f) f(0)
- // apply_zero(foo)
- // ^
- // This is not a tok::l_paren, but foo is a function.
- if (TheTok.isNot(tok::l_paren))
- return { MacroName, MI, {} };
-
- MacroParamMap ParamMap;
-
- // When the argument is a function call, like
- // CALL_FN(someFunctionName(param1, param2))
- // we will find tok::l_paren, tok::r_paren, and tok::comma that do not divide
- // actual macro arguments, or do not represent the macro argument's closing
- // parentheses, so we'll count how many parentheses aren't closed yet.
- // If ParanthesesDepth
- // * = 0, then there are no more arguments to lex.
- // * = 1, then if we find a tok::comma, we can start lexing the next arg.
- // * > 1, then tok::comma is a part of the current arg.
- int ParenthesesDepth = 1;
-
- // If we encounter the variadic arg, we will lex until the closing
- // tok::r_paren, even if we lex a tok::comma and ParanthesesDepth == 1.
- const IdentifierInfo *VariadicParamII = PP.getIdentifierInfo("__VA_ARGS__");
- if (MI->isGNUVarargs()) {
- // If macro uses GNU-style variadic args, the param name is user-supplied,
- // an not "__VA_ARGS__". E.g.:
- // #define FOO(a, b, myvargs...)
- // In this case, just use the last parameter:
- VariadicParamII = *(MacroParams.rbegin());
- }
-
- for (const IdentifierInfo *CurrParamII : MacroParams) {
- MacroParamMap::mapped_type ArgTokens;
-
- // One could also simply not supply a single argument to __VA_ARGS__ -- this
- // results in a preprocessor warning, but is not an error:
- // #define VARIADIC(ptr, ...) \
- // someVariadicTemplateFunction(__VA_ARGS__)
- //
- // int *ptr;
- // VARIADIC(ptr); // Note that there are no commas, this isn't just an
- // // empty parameter -- there are no parameters for '...'.
- // In any other case, ParenthesesDepth mustn't be 0 here.
- if (ParenthesesDepth != 0) {
-
- // Lex the first token of the next macro parameter.
- TStream.next(TheTok);
-
- while (CurrParamII == VariadicParamII || ParenthesesDepth != 1 ||
- !TheTok.is(tok::comma)) {
- assert(TheTok.isNot(tok::eof) &&
- "EOF encountered while looking for expanded macro args!");
-
- if (TheTok.is(tok::l_paren))
- ++ParenthesesDepth;
-
- if (TheTok.is(tok::r_paren))
- --ParenthesesDepth;
-
- if (ParenthesesDepth == 0)
- break;
-
- if (TheTok.is(tok::raw_identifier)) {
- PP.LookUpIdentifierInfo(TheTok);
- // This token is a variadic parameter:
- //
- // #define PARAMS_RESOLVE_TO_VA_ARGS(i, fmt) foo(i, fmt); \
- // i = 0;
- // #define DISPATCH(...) \
- // PARAMS_RESOLVE_TO_VA_ARGS(__VA_ARGS__);
- // // ^~~~~~~~~~~ Variadic parameter here
- //
- // void multipleParamsResolveToVA_ARGS(void) {
- // int x = 1;
- // DISPATCH(x, "LF1M healer"); // Multiple arguments are mapped to
- // // a single __VA_ARGS__ parameter.
- // (void)(10 / x);
- // }
- //
- // We will stumble across this while trying to expand
- // PARAMS_RESOLVE_TO_VA_ARGS. By this point, we already noted during
- // the processing of DISPATCH what __VA_ARGS__ maps to, so we'll
- // retrieve the next series of tokens from that.
- if (TheTok.getIdentifierInfo() == VariadicParamII) {
- TStream.injectRange(PrevParamMap.at(VariadicParamII));
- TStream.next(TheTok);
- continue;
- }
- }
-
- ArgTokens.push_back(TheTok);
- TStream.next(TheTok);
- }
- } else {
- assert(CurrParamII == VariadicParamII &&
- "No more macro arguments are found, but the current parameter "
- "isn't the variadic arg!");
- }
-
- ParamMap.emplace(CurrParamII, std::move(ArgTokens));
- }
-
- assert(TheTok.is(tok::r_paren) &&
- "Expanded macro argument acquisition failed! After the end of the loop"
- " this token should be ')'!");
-
- return {MacroName, MI, ParamMap};
-}
-
-static MacroInfo::tokens_iterator getMatchingRParen(
- MacroInfo::tokens_iterator It,
- MacroInfo::tokens_iterator End) {
-
- assert(It->is(tok::l_paren) && "This token should be '('!");
-
- // Skip until we find the closing ')'.
- int ParenthesesDepth = 1;
- while (ParenthesesDepth != 0) {
- ++It;
-
- assert(It->isNot(tok::eof) &&
- "Encountered EOF while attempting to skip macro arguments!");
- assert(It != End &&
- "End of the macro definition reached before finding ')'!");
-
- if (It->is(tok::l_paren))
- ++ParenthesesDepth;
-
- if (It->is(tok::r_paren))
- --ParenthesesDepth;
- }
- return It;
-}
-
-static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
- const SourceManager &SM,
- const IdentifierInfo *II,
- SourceLocation Loc) {
-
- const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
- if (!MD)
- return nullptr;
-
- return MD->findDirectiveAtLoc(Loc, SM).getMacroInfo();
-}
-
-void MacroParamMap::expandFromPrevMacro(const MacroParamMap &Super) {
-
- for (value_type &Pair : *this) {
- ArgTokensTy &CurrArgTokens = Pair.second;
-
- // For each token in the expanded macro argument.
- auto It = CurrArgTokens.begin();
- while (It != CurrArgTokens.end()) {
- if (It->isNot(tok::identifier)) {
- ++It;
- continue;
- }
-
- const auto *II = It->getIdentifierInfo();
- assert(II);
-
- // Is this an argument that "Super" expands further?
- if (!Super.count(II)) {
- ++It;
- continue;
- }
-
- const ArgTokensTy &SuperArgTokens = Super.at(II);
-
- It = CurrArgTokens.insert(It, SuperArgTokens.begin(),
- SuperArgTokens.end());
- std::advance(It, SuperArgTokens.size());
- It = CurrArgTokens.erase(It);
- }
- }
-}
-
-void MacroParamMap::dumpToStream(llvm::raw_ostream &Out,
- const Preprocessor &PP) const {
- for (const std::pair<const IdentifierInfo *, ArgTokensTy> Pair : *this) {
- Out << Pair.first->getName() << " -> ";
- dumpArgTokensToStream(Out, PP, Pair.second);
- Out << '\n';
- }
-}
-
-static void dumpArgTokensToStream(llvm::raw_ostream &Out,
- const Preprocessor &PP,
- const ArgTokensTy &Toks) {
- TokenPrinter Printer(Out, PP);
- for (Token Tok : Toks)
- Printer.printToken(Tok);
-}
-
-void TokenPrinter::printToken(const Token &Tok) {
- // TODO: Handle GNU extensions where hash and hashhash occurs right before
- // __VA_ARGS__.
- // cppreference.com: "some compilers offer an extension that allows ## to
- // appear after a comma and before __VA_ARGS__, in which case the ## does
- // nothing when the variable arguments are present, but removes the comma when
- // the variable arguments are not present: this makes it possible to define
- // macros such as fprintf (stderr, format, ##__VA_ARGS__)"
- // FIXME: Handle named variadic macro parameters (also a GNU extension).
-
- // If this is the first token to be printed, don't print space.
- if (PrevTok.isNot(tok::unknown)) {
- // If the tokens were already space separated, or if they must be to avoid
- // them being implicitly pasted, add a space between them.
- if(Tok.hasLeadingSpace() || ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok,
- Tok)) {
- // AvoidConcat doesn't check for ##, don't print a space around it.
- if (PrevTok.isNot(tok::hashhash) && Tok.isNot(tok::hashhash)) {
- OS << ' ';
- }
- }
- }
-
- if (!Tok.isOneOf(tok::hash, tok::hashhash)) {
- if (PrevTok.is(tok::hash))
- OS << '\"' << PP.getSpelling(Tok) << '\"';
- else
- OS << PP.getSpelling(Tok);
- }
-
- PrevPrevTok = PrevTok;
- PrevTok = Tok;
+ return MacroExpansions.getExpandedText(MacroExpansionLoc);
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index a481bde..6955457 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -19,7 +19,13 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <iterator>
using namespace clang;
using namespace ento;
@@ -97,47 +103,63 @@
return CmpOpTable[getIndexFromOp(CurrentOP)][CmpOpCount];
}
};
+
//===----------------------------------------------------------------------===//
// RangeSet implementation
//===----------------------------------------------------------------------===//
-void RangeSet::IntersectInRange(BasicValueFactory &BV, Factory &F,
- const llvm::APSInt &Lower,
- const llvm::APSInt &Upper,
- PrimRangeSet &newRanges,
- PrimRangeSet::iterator &i,
- PrimRangeSet::iterator &e) const {
- // There are six cases for each range R in the set:
- // 1. R is entirely before the intersection range.
- // 2. R is entirely after the intersection range.
- // 3. R contains the entire intersection range.
- // 4. R starts before the intersection range and ends in the middle.
- // 5. R starts in the middle of the intersection range and ends after it.
- // 6. R is entirely contained in the intersection range.
- // These correspond to each of the conditions below.
- for (/* i = begin(), e = end() */; i != e; ++i) {
- if (i->To() < Lower) {
- continue;
- }
- if (i->From() > Upper) {
- break;
- }
+RangeSet::ContainerType RangeSet::Factory::EmptySet{};
- if (i->Includes(Lower)) {
- if (i->Includes(Upper)) {
- newRanges =
- F.add(newRanges, Range(BV.getValue(Lower), BV.getValue(Upper)));
- break;
- } else
- newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To()));
- } else {
- if (i->Includes(Upper)) {
- newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper)));
- break;
- } else
- newRanges = F.add(newRanges, *i);
- }
+RangeSet RangeSet::Factory::add(RangeSet Original, Range Element) {
+ ContainerType Result;
+ Result.reserve(Original.size() + 1);
+
+ const_iterator Lower = llvm::lower_bound(Original, Element);
+ Result.insert(Result.end(), Original.begin(), Lower);
+ Result.push_back(Element);
+ Result.insert(Result.end(), Lower, Original.end());
+
+ return makePersistent(std::move(Result));
+}
+
+RangeSet RangeSet::Factory::add(RangeSet Original, const llvm::APSInt &Point) {
+ return add(Original, Range(Point));
+}
+
+RangeSet RangeSet::Factory::getRangeSet(Range From) {
+ ContainerType Result;
+ Result.push_back(From);
+ return makePersistent(std::move(Result));
+}
+
+RangeSet RangeSet::Factory::makePersistent(ContainerType &&From) {
+ llvm::FoldingSetNodeID ID;
+ void *InsertPos;
+
+ From.Profile(ID);
+ ContainerType *Result = Cache.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!Result) {
+ // It is cheaper to fully construct the resulting range on stack
+ // and move it to the freshly allocated buffer if we don't have
+ // a set like this already.
+ Result = construct(std::move(From));
+ Cache.InsertNode(Result, InsertPos);
}
+
+ return Result;
+}
+
+RangeSet::ContainerType *RangeSet::Factory::construct(ContainerType &&From) {
+ void *Buffer = Arena.Allocate();
+ return new (Buffer) ContainerType(std::move(From));
+}
+
+RangeSet RangeSet::Factory::add(RangeSet LHS, RangeSet RHS) {
+ ContainerType Result;
+ std::merge(LHS.begin(), LHS.end(), RHS.begin(), RHS.end(),
+ std::back_inserter(Result));
+ return makePersistent(std::move(Result));
}
const llvm::APSInt &RangeSet::getMinValue() const {
@@ -147,22 +169,31 @@
const llvm::APSInt &RangeSet::getMaxValue() const {
assert(!isEmpty());
- // NOTE: It's a shame that we can't implement 'getMaxValue' without scanning
- // the whole tree to get to the last element.
- // llvm::ImmutableSet should support decrement for 'end' iterators
- // or reverse order iteration.
- auto It = begin();
- for (auto End = end(); std::next(It) != End; ++It) {
- }
- return It->To();
+ return std::prev(end())->To();
+}
+
+bool RangeSet::containsImpl(llvm::APSInt &Point) const {
+ if (isEmpty() || !pin(Point))
+ return false;
+
+ Range Dummy(Point);
+ const_iterator It = llvm::upper_bound(*this, Dummy);
+ if (It == begin())
+ return false;
+
+ return std::prev(It)->Includes(Point);
+}
+
+bool RangeSet::pin(llvm::APSInt &Point) const {
+ APSIntType Type(getMinValue());
+ if (Type.testInRange(Point, true) != APSIntType::RTR_Within)
+ return false;
+
+ Type.apply(Point);
+ return true;
}
bool RangeSet::pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const {
- if (isEmpty()) {
- // This range is already infeasible.
- return false;
- }
-
// This function has nine cases, the cartesian product of range-testing
// both the upper and lower bounds against the symbol's type.
// Each case requires a different pinning operation.
@@ -243,129 +274,216 @@
return true;
}
-// Returns a set containing the values in the receiving set, intersected with
-// the closed range [Lower, Upper]. Unlike the Range type, this range uses
-// modular arithmetic, corresponding to the common treatment of C integer
-// overflow. Thus, if the Lower bound is greater than the Upper bound, the
-// range is taken to wrap around. This is equivalent to taking the
-// intersection with the two ranges [Min, Upper] and [Lower, Max],
-// or, alternatively, /removing/ all integers between Upper and Lower.
-RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F,
- llvm::APSInt Lower, llvm::APSInt Upper) const {
- PrimRangeSet newRanges = F.getEmptySet();
+RangeSet RangeSet::Factory::intersect(RangeSet What, llvm::APSInt Lower,
+ llvm::APSInt Upper) {
+ if (What.isEmpty() || !What.pin(Lower, Upper))
+ return getEmptySet();
- if (isEmpty() || !pin(Lower, Upper))
- return newRanges;
+ ContainerType DummyContainer;
- PrimRangeSet::iterator i = begin(), e = end();
- if (Lower <= Upper)
- IntersectInRange(BV, F, Lower, Upper, newRanges, i, e);
- else {
- // The order of the next two statements is important!
- // IntersectInRange() does not reset the iteration state for i and e.
- // Therefore, the lower range most be handled first.
- IntersectInRange(BV, F, BV.getMinValue(Upper), Upper, newRanges, i, e);
- IntersectInRange(BV, F, Lower, BV.getMaxValue(Lower), newRanges, i, e);
+ if (Lower <= Upper) {
+ // [Lower, Upper] is a regular range.
+ //
+ // Shortcut: check that there is even a possibility of the intersection
+ // by checking the two following situations:
+ //
+ // <---[ What ]---[------]------>
+ // Lower Upper
+ // -or-
+ // <----[------]----[ What ]---->
+ // Lower Upper
+ if (What.getMaxValue() < Lower || Upper < What.getMinValue())
+ return getEmptySet();
+
+ DummyContainer.push_back(
+ Range(ValueFactory.getValue(Lower), ValueFactory.getValue(Upper)));
+ } else {
+ // [Lower, Upper] is an inverted range, i.e. [MIN, Upper] U [Lower, MAX]
+ //
+ // Shortcut: check that there is even a possibility of the intersection
+ // by checking the following situation:
+ //
+ // <------]---[ What ]---[------>
+ // Upper Lower
+ if (What.getMaxValue() < Lower && Upper < What.getMinValue())
+ return getEmptySet();
+
+ DummyContainer.push_back(
+ Range(ValueFactory.getMinValue(Upper), ValueFactory.getValue(Upper)));
+ DummyContainer.push_back(
+ Range(ValueFactory.getValue(Lower), ValueFactory.getMaxValue(Lower)));
}
- return newRanges;
+ return intersect(*What.Impl, DummyContainer);
}
-// Returns a set containing the values in the receiving set, intersected with
-// the range set passed as parameter.
-RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F,
- const RangeSet &Other) const {
- PrimRangeSet newRanges = F.getEmptySet();
+RangeSet RangeSet::Factory::intersect(const RangeSet::ContainerType &LHS,
+ const RangeSet::ContainerType &RHS) {
+ ContainerType Result;
+ Result.reserve(std::max(LHS.size(), RHS.size()));
- for (iterator i = Other.begin(), e = Other.end(); i != e; ++i) {
- RangeSet newPiece = Intersect(BV, F, i->From(), i->To());
- for (iterator j = newPiece.begin(), ee = newPiece.end(); j != ee; ++j) {
- newRanges = F.add(newRanges, *j);
- }
+ const_iterator First = LHS.begin(), Second = RHS.begin(),
+ FirstEnd = LHS.end(), SecondEnd = RHS.end();
+
+ const auto SwapIterators = [&First, &FirstEnd, &Second, &SecondEnd]() {
+ std::swap(First, Second);
+ std::swap(FirstEnd, SecondEnd);
+ };
+
+ // If we ran out of ranges in one set, but not in the other,
+ // it means that those elements are definitely not in the
+ // intersection.
+ while (First != FirstEnd && Second != SecondEnd) {
+ // We want to keep the following invariant at all times:
+ //
+ // ----[ First ---------------------->
+ // --------[ Second ----------------->
+ if (Second->From() < First->From())
+ SwapIterators();
+
+ // Loop where the invariant holds:
+ do {
+ // Check for the following situation:
+ //
+ // ----[ First ]--------------------->
+ // ---------------[ Second ]--------->
+ //
+ // which means that...
+ if (Second->From() > First->To()) {
+ // ...First is not in the intersection.
+ //
+ // We should move on to the next range after First and break out of the
+ // loop because the invariant might not be true.
+ ++First;
+ break;
+ }
+
+ // We have a guaranteed intersection at this point!
+ // And this is the current situation:
+ //
+ // ----[ First ]----------------->
+ // -------[ Second ------------------>
+ //
+ // Additionally, it definitely starts with Second->From().
+ const llvm::APSInt &IntersectionStart = Second->From();
+
+ // It is important to know which of the two ranges' ends
+ // is greater. That "longer" range might have some other
+ // intersections, while the "shorter" range might not.
+ if (Second->To() > First->To()) {
+ // Here we make a decision to keep First as the "longer"
+ // range.
+ SwapIterators();
+ }
+
+ // At this point, we have the following situation:
+ //
+ // ---- First ]-------------------->
+ // ---- Second ]--[ Second+1 ---------->
+ //
+ // We don't know the relationship between First->From and
+ // Second->From and we don't know whether Second+1 intersects
+ // with First.
+ //
+ // However, we know that [IntersectionStart, Second->To] is
+ // a part of the intersection...
+ Result.push_back(Range(IntersectionStart, Second->To()));
+ ++Second;
+ // ...and that the invariant will hold for a valid Second+1
+ // because First->From <= Second->To < (Second+1)->From.
+ } while (Second != SecondEnd);
}
- return newRanges;
+ if (Result.empty())
+ return getEmptySet();
+
+ return makePersistent(std::move(Result));
}
-// Turn all [A, B] ranges to [-B, -A], when "-" is a C-like unary minus
-// operation under the values of the type.
-//
-// We also handle MIN because applying unary minus to MIN does not change it.
-// Example 1:
-// char x = -128; // -128 is a MIN value in a range of 'char'
-// char y = -x; // y: -128
-// Example 2:
-// unsigned char x = 0; // 0 is a MIN value in a range of 'unsigned char'
-// unsigned char y = -x; // y: 0
-//
-// And it makes us to separate the range
-// like [MIN, N] to [MIN, MIN] U [-N,MAX].
-// For instance, whole range is {-128..127} and subrange is [-128,-126],
-// thus [-128,-127,-126,.....] negates to [-128,.....,126,127].
-//
-// Negate restores disrupted ranges on bounds,
-// e.g. [MIN, B] => [MIN, MIN] U [-B, MAX] => [MIN, B].
-RangeSet RangeSet::Negate(BasicValueFactory &BV, Factory &F) const {
- PrimRangeSet newRanges = F.getEmptySet();
+RangeSet RangeSet::Factory::intersect(RangeSet LHS, RangeSet RHS) {
+ // Shortcut: let's see if the intersection is even possible.
+ if (LHS.isEmpty() || RHS.isEmpty() || LHS.getMaxValue() < RHS.getMinValue() ||
+ RHS.getMaxValue() < LHS.getMinValue())
+ return getEmptySet();
- if (isEmpty())
- return newRanges;
+ return intersect(*LHS.Impl, *RHS.Impl);
+}
- const llvm::APSInt sampleValue = getMinValue();
- const llvm::APSInt &MIN = BV.getMinValue(sampleValue);
- const llvm::APSInt &MAX = BV.getMaxValue(sampleValue);
+RangeSet RangeSet::Factory::intersect(RangeSet LHS, llvm::APSInt Point) {
+ if (LHS.containsImpl(Point))
+ return getRangeSet(ValueFactory.getValue(Point));
+
+ return getEmptySet();
+}
+
+RangeSet RangeSet::Factory::negate(RangeSet What) {
+ if (What.isEmpty())
+ return getEmptySet();
+
+ const llvm::APSInt SampleValue = What.getMinValue();
+ const llvm::APSInt &MIN = ValueFactory.getMinValue(SampleValue);
+ const llvm::APSInt &MAX = ValueFactory.getMaxValue(SampleValue);
+
+ ContainerType Result;
+ Result.reserve(What.size() + (SampleValue == MIN));
// Handle a special case for MIN value.
- iterator i = begin();
- const llvm::APSInt &from = i->From();
- const llvm::APSInt &to = i->To();
- if (from == MIN) {
- // If [from, to] are [MIN, MAX], then just return the same [MIN, MAX].
- if (to == MAX) {
- newRanges = ranges;
- } else {
- // Add separate range for the lowest value.
- newRanges = F.add(newRanges, Range(MIN, MIN));
- // Skip adding the second range in case when [from, to] are [MIN, MIN].
- if (to != MIN) {
- newRanges = F.add(newRanges, Range(BV.getValue(-to), MAX));
- }
+ const_iterator It = What.begin();
+ const_iterator End = What.end();
+
+ const llvm::APSInt &From = It->From();
+ const llvm::APSInt &To = It->To();
+
+ if (From == MIN) {
+ // If the range [From, To] is [MIN, MAX], then result is also [MIN, MAX].
+ if (To == MAX) {
+ return What;
}
+
+ const_iterator Last = std::prev(End);
+
+ // Try to find and unite the following ranges:
+ // [MIN, MIN] & [MIN + 1, N] => [MIN, N].
+ if (Last->To() == MAX) {
+ // It means that in the original range we have ranges
+ // [MIN, A], ... , [B, MAX]
+ // And the result should be [MIN, -B], ..., [-A, MAX]
+ Result.emplace_back(MIN, ValueFactory.getValue(-Last->From()));
+ // We already negated Last, so we can skip it.
+ End = Last;
+ } else {
+ // Add a separate range for the lowest value.
+ Result.emplace_back(MIN, MIN);
+ }
+
+ // Skip adding the second range in case when [From, To] are [MIN, MIN].
+ if (To != MIN) {
+ Result.emplace_back(ValueFactory.getValue(-To), MAX);
+ }
+
// Skip the first range in the loop.
- ++i;
+ ++It;
}
// Negate all other ranges.
- for (iterator e = end(); i != e; ++i) {
+ for (; It != End; ++It) {
// Negate int values.
- const llvm::APSInt &newFrom = BV.getValue(-i->To());
- const llvm::APSInt &newTo = BV.getValue(-i->From());
+ const llvm::APSInt &NewFrom = ValueFactory.getValue(-It->To());
+ const llvm::APSInt &NewTo = ValueFactory.getValue(-It->From());
+
// Add a negated range.
- newRanges = F.add(newRanges, Range(newFrom, newTo));
+ Result.emplace_back(NewFrom, NewTo);
}
- if (newRanges.isSingleton())
- return newRanges;
-
- // Try to find and unite next ranges:
- // [MIN, MIN] & [MIN + 1, N] => [MIN, N].
- iterator iter1 = newRanges.begin();
- iterator iter2 = std::next(iter1);
-
- if (iter1->To() == MIN && (iter2->From() - 1) == MIN) {
- const llvm::APSInt &to = iter2->To();
- // remove adjacent ranges
- newRanges = F.remove(newRanges, *iter1);
- newRanges = F.remove(newRanges, *newRanges.begin());
- // add united range
- newRanges = F.add(newRanges, Range(MIN, to));
- }
-
- return newRanges;
+ llvm::sort(Result);
+ return makePersistent(std::move(Result));
}
-RangeSet RangeSet::Delete(BasicValueFactory &BV, Factory &F,
- const llvm::APSInt &Point) const {
+RangeSet RangeSet::Factory::deletePoint(RangeSet From,
+ const llvm::APSInt &Point) {
+ if (!From.contains(Point))
+ return From;
+
llvm::APSInt Upper = Point;
llvm::APSInt Lower = Point;
@@ -373,22 +491,17 @@
--Lower;
// Notice that the lower bound is greater than the upper bound.
- return Intersect(BV, F, Upper, Lower);
+ return intersect(From, Upper, Lower);
}
-void RangeSet::print(raw_ostream &os) const {
- bool isFirst = true;
- os << "{ ";
- for (iterator i = begin(), e = end(); i != e; ++i) {
- if (isFirst)
- isFirst = false;
- else
- os << ", ";
+void Range::dump(raw_ostream &OS) const {
+ OS << '[' << toString(From(), 10) << ", " << toString(To(), 10) << ']';
+}
- os << '[' << i->From().toString(10) << ", " << i->To().toString(10)
- << ']';
- }
- os << " }";
+void RangeSet::dump(raw_ostream &OS) const {
+ OS << "{ ";
+ llvm::interleaveComma(*this, OS, [&OS](const Range &R) { R.dump(OS); });
+ OS << " }";
}
REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(SymbolSet, SymbolRef)
@@ -436,33 +549,43 @@
SymbolRef Sym);
/// Merge classes for the given symbols and return a new state.
- LLVM_NODISCARD static inline ProgramStateRef
- merge(BasicValueFactory &BV, RangeSet::Factory &F, ProgramStateRef State,
- SymbolRef First, SymbolRef Second);
+ LLVM_NODISCARD static inline ProgramStateRef merge(RangeSet::Factory &F,
+ ProgramStateRef State,
+ SymbolRef First,
+ SymbolRef Second);
// Merge this class with the given class and return a new state.
- LLVM_NODISCARD inline ProgramStateRef merge(BasicValueFactory &BV,
- RangeSet::Factory &F,
- ProgramStateRef State,
- EquivalenceClass Other);
+ LLVM_NODISCARD inline ProgramStateRef
+ merge(RangeSet::Factory &F, ProgramStateRef State, EquivalenceClass Other);
/// Return a set of class members for the given state.
- LLVM_NODISCARD inline SymbolSet getClassMembers(ProgramStateRef State);
+ LLVM_NODISCARD inline SymbolSet getClassMembers(ProgramStateRef State) const;
+
/// Return true if the current class is trivial in the given state.
- LLVM_NODISCARD inline bool isTrivial(ProgramStateRef State);
+ /// A class is trivial if and only if there is not any member relations stored
+ /// to it in State/ClassMembers.
+ /// An equivalence class with one member might seem as it does not hold any
+ /// meaningful information, i.e. that is a tautology. However, during the
+ /// removal of dead symbols we do not remove classes with one member for
+ /// resource and performance reasons. Consequently, a class with one member is
+ /// not necessarily trivial. It could happen that we have a class with two
+ /// members and then during the removal of dead symbols we remove one of its
+ /// members. In this case, the class is still non-trivial (it still has the
+ /// mappings in ClassMembers), even though it has only one member.
+ LLVM_NODISCARD inline bool isTrivial(ProgramStateRef State) const;
+
/// Return true if the current class is trivial and its only member is dead.
LLVM_NODISCARD inline bool isTriviallyDead(ProgramStateRef State,
- SymbolReaper &Reaper);
+ SymbolReaper &Reaper) const;
LLVM_NODISCARD static inline ProgramStateRef
- markDisequal(BasicValueFactory &BV, RangeSet::Factory &F,
- ProgramStateRef State, SymbolRef First, SymbolRef Second);
+ markDisequal(RangeSet::Factory &F, ProgramStateRef State, SymbolRef First,
+ SymbolRef Second);
LLVM_NODISCARD static inline ProgramStateRef
- markDisequal(BasicValueFactory &BV, RangeSet::Factory &F,
- ProgramStateRef State, EquivalenceClass First,
- EquivalenceClass Second);
+ markDisequal(RangeSet::Factory &F, ProgramStateRef State,
+ EquivalenceClass First, EquivalenceClass Second);
LLVM_NODISCARD inline ProgramStateRef
- markDisequal(BasicValueFactory &BV, RangeSet::Factory &F,
- ProgramStateRef State, EquivalenceClass Other) const;
+ markDisequal(RangeSet::Factory &F, ProgramStateRef State,
+ EquivalenceClass Other) const;
LLVM_NODISCARD static inline ClassSet
getDisequalClasses(ProgramStateRef State, SymbolRef Sym);
LLVM_NODISCARD inline ClassSet
@@ -470,9 +593,23 @@
LLVM_NODISCARD inline ClassSet
getDisequalClasses(DisequalityMapTy Map, ClassSet::Factory &Factory) const;
+ LLVM_NODISCARD static inline Optional<bool> areEqual(ProgramStateRef State,
+ EquivalenceClass First,
+ EquivalenceClass Second);
LLVM_NODISCARD static inline Optional<bool>
areEqual(ProgramStateRef State, SymbolRef First, SymbolRef Second);
+ /// Iterate over all symbols and try to simplify them.
+ LLVM_NODISCARD static inline ProgramStateRef simplify(SValBuilder &SVB,
+ RangeSet::Factory &F,
+ ProgramStateRef State,
+ EquivalenceClass Class);
+
+ void dumpToStream(ProgramStateRef State, raw_ostream &os) const;
+ LLVM_DUMP_METHOD void dump(ProgramStateRef State) const {
+ dumpToStream(State, llvm::errs());
+ }
+
/// Check equivalence data for consistency.
LLVM_NODISCARD LLVM_ATTRIBUTE_UNUSED static bool
isClassDataConsistent(ProgramStateRef State);
@@ -515,15 +652,13 @@
}
static inline SymbolSet::Factory &getMembersFactory(ProgramStateRef State);
- inline ProgramStateRef mergeImpl(BasicValueFactory &BV, RangeSet::Factory &F,
- ProgramStateRef State, SymbolSet Members,
- EquivalenceClass Other,
+ inline ProgramStateRef mergeImpl(RangeSet::Factory &F, ProgramStateRef State,
+ SymbolSet Members, EquivalenceClass Other,
SymbolSet OtherMembers);
- static inline void
+ static inline bool
addToDisequalityInfo(DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
- BasicValueFactory &BV, RangeSet::Factory &F,
- ProgramStateRef State, EquivalenceClass First,
- EquivalenceClass Second);
+ RangeSet::Factory &F, ProgramStateRef State,
+ EquivalenceClass First, EquivalenceClass Second);
/// This is a unique identifier of the class.
uintptr_t ID;
@@ -533,6 +668,15 @@
// Constraint functions
//===----------------------------------------------------------------------===//
+LLVM_NODISCARD LLVM_ATTRIBUTE_UNUSED bool
+areFeasible(ConstraintRangeTy Constraints) {
+ return llvm::none_of(
+ Constraints,
+ [](const std::pair<EquivalenceClass, RangeSet> &ClassConstraint) {
+ return ClassConstraint.second.isEmpty();
+ });
+}
+
LLVM_NODISCARD inline const RangeSet *getConstraint(ProgramStateRef State,
EquivalenceClass Class) {
return State->get<ConstraintRange>(Class);
@@ -543,70 +687,52 @@
return getConstraint(State, EquivalenceClass::find(State, Sym));
}
+LLVM_NODISCARD ProgramStateRef setConstraint(ProgramStateRef State,
+ EquivalenceClass Class,
+ RangeSet Constraint) {
+ return State->set<ConstraintRange>(Class, Constraint);
+}
+
+LLVM_NODISCARD ProgramStateRef setConstraints(ProgramStateRef State,
+ ConstraintRangeTy Constraints) {
+ return State->set<ConstraintRange>(Constraints);
+}
+
//===----------------------------------------------------------------------===//
// Equality/diseqiality abstraction
//===----------------------------------------------------------------------===//
-/// A small helper structure representing symbolic equality.
+/// A small helper function for detecting symbolic (dis)equality.
///
/// Equality check can have different forms (like a == b or a - b) and this
/// class encapsulates those away if the only thing the user wants to check -
-/// whether it's equality/diseqiality or not and have an easy access to the
-/// compared symbols.
-struct EqualityInfo {
-public:
- SymbolRef Left, Right;
- // true for equality and false for disequality.
- bool IsEquality = true;
-
- void invert() { IsEquality = !IsEquality; }
- /// Extract equality information from the given symbol and the constants.
- ///
- /// This function assumes the following expression Sym + Adjustment != Int.
- /// It is a default because the most widespread case of the equality check
- /// is (A == B) + 0 != 0.
- static Optional<EqualityInfo> extract(SymbolRef Sym, const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
- // As of now, the only equality form supported is Sym + 0 != 0.
- if (!Int.isNullValue() || !Adjustment.isNullValue())
- return llvm::None;
-
- return extract(Sym);
+/// whether it's equality/diseqiality or not.
+///
+/// \returns true if assuming this Sym to be true means equality of operands
+/// false if it means disequality of operands
+/// None otherwise
+Optional<bool> meansEquality(const SymSymExpr *Sym) {
+ switch (Sym->getOpcode()) {
+ case BO_Sub:
+ // This case is: A - B != 0 -> disequality check.
+ return false;
+ case BO_EQ:
+ // This case is: A == B != 0 -> equality check.
+ return true;
+ case BO_NE:
+ // This case is: A != B != 0 -> diseqiality check.
+ return false;
+ default:
+ return llvm::None;
}
- /// Extract equality information from the given symbol.
- static Optional<EqualityInfo> extract(SymbolRef Sym) {
- return EqualityExtractor().Visit(Sym);
- }
-
-private:
- class EqualityExtractor
- : public SymExprVisitor<EqualityExtractor, Optional<EqualityInfo>> {
- public:
- Optional<EqualityInfo> VisitSymSymExpr(const SymSymExpr *Sym) const {
- switch (Sym->getOpcode()) {
- case BO_Sub:
- // This case is: A - B != 0 -> disequality check.
- return EqualityInfo{Sym->getLHS(), Sym->getRHS(), false};
- case BO_EQ:
- // This case is: A == B != 0 -> equality check.
- return EqualityInfo{Sym->getLHS(), Sym->getRHS(), true};
- case BO_NE:
- // This case is: A != B != 0 -> diseqiality check.
- return EqualityInfo{Sym->getLHS(), Sym->getRHS(), false};
- default:
- return llvm::None;
- }
- }
- };
-};
+}
//===----------------------------------------------------------------------===//
// Intersection functions
//===----------------------------------------------------------------------===//
template <class SecondTy, class... RestTy>
-LLVM_NODISCARD inline RangeSet intersect(BasicValueFactory &BV,
- RangeSet::Factory &F, RangeSet Head,
+LLVM_NODISCARD inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
SecondTy Second, RestTy... Tail);
template <class... RangeTy> struct IntersectionTraits;
@@ -629,15 +755,14 @@
};
template <class EndTy>
-LLVM_NODISCARD inline EndTy intersect(BasicValueFactory &BV,
- RangeSet::Factory &F, EndTy End) {
+LLVM_NODISCARD inline EndTy intersect(RangeSet::Factory &F, EndTy End) {
// If the list contains only RangeSet or Optional<RangeSet>, simply return
// that range set.
return End;
}
LLVM_NODISCARD LLVM_ATTRIBUTE_UNUSED inline Optional<RangeSet>
-intersect(BasicValueFactory &BV, RangeSet::Factory &F, const RangeSet *End) {
+intersect(RangeSet::Factory &F, const RangeSet *End) {
// This is an extraneous conversion from a raw pointer into Optional<RangeSet>
if (End) {
return *End;
@@ -646,25 +771,23 @@
}
template <class... RestTy>
-LLVM_NODISCARD inline RangeSet intersect(BasicValueFactory &BV,
- RangeSet::Factory &F, RangeSet Head,
+LLVM_NODISCARD inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
RangeSet Second, RestTy... Tail) {
// Here we call either the <RangeSet,RangeSet,...> or <RangeSet,...> version
// of the function and can be sure that the result is RangeSet.
- return intersect(BV, F, Head.Intersect(BV, F, Second), Tail...);
+ return intersect(F, F.intersect(Head, Second), Tail...);
}
template <class SecondTy, class... RestTy>
-LLVM_NODISCARD inline RangeSet intersect(BasicValueFactory &BV,
- RangeSet::Factory &F, RangeSet Head,
+LLVM_NODISCARD inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
SecondTy Second, RestTy... Tail) {
if (Second) {
// Here we call the <RangeSet,RangeSet,...> version of the function...
- return intersect(BV, F, Head, *Second, Tail...);
+ return intersect(F, Head, *Second, Tail...);
}
// ...and here it is either <RangeSet,RangeSet,...> or <RangeSet,...>, which
// means that the result is definitely RangeSet.
- return intersect(BV, F, Head, Tail...);
+ return intersect(F, Head, Tail...);
}
/// Main generic intersect function.
@@ -689,12 +812,12 @@
template <class HeadTy, class SecondTy, class... RestTy>
LLVM_NODISCARD inline
typename IntersectionTraits<HeadTy, SecondTy, RestTy...>::Type
- intersect(BasicValueFactory &BV, RangeSet::Factory &F, HeadTy Head,
- SecondTy Second, RestTy... Tail) {
+ intersect(RangeSet::Factory &F, HeadTy Head, SecondTy Second,
+ RestTy... Tail) {
if (Head) {
- return intersect(BV, F, *Head, Second, Tail...);
+ return intersect(F, *Head, Second, Tail...);
}
- return intersect(BV, F, Second, Tail...);
+ return intersect(F, Second, Tail...);
}
//===----------------------------------------------------------------------===//
@@ -710,9 +833,9 @@
: public SymExprVisitor<SymbolicRangeInferrer, RangeSet> {
public:
template <class SourceType>
- static RangeSet inferRange(BasicValueFactory &BV, RangeSet::Factory &F,
- ProgramStateRef State, SourceType Origin) {
- SymbolicRangeInferrer Inferrer(BV, F, State);
+ static RangeSet inferRange(RangeSet::Factory &F, ProgramStateRef State,
+ SourceType Origin) {
+ SymbolicRangeInferrer Inferrer(F, State);
return Inferrer.infer(Origin);
}
@@ -733,13 +856,18 @@
}
RangeSet VisitSymSymExpr(const SymSymExpr *Sym) {
- return VisitBinaryOperator(Sym);
+ return intersect(
+ RangeFactory,
+ // If Sym is (dis)equality, we might have some information
+ // on that in our equality classes data structure.
+ getRangeForEqualities(Sym),
+ // And we should always check what we can get from the operands.
+ VisitBinaryOperator(Sym));
}
private:
- SymbolicRangeInferrer(BasicValueFactory &BV, RangeSet::Factory &F,
- ProgramStateRef S)
- : ValueFactory(BV), RangeFactory(F), State(S) {}
+ SymbolicRangeInferrer(RangeSet::Factory &F, ProgramStateRef S)
+ : ValueFactory(F.getValueFactory()), RangeFactory(F), State(S) {}
/// Infer range information from the given integer constant.
///
@@ -763,26 +891,25 @@
}
RangeSet infer(SymbolRef Sym) {
- if (Optional<RangeSet> ConstraintBasedRange = intersect(
- ValueFactory, RangeFactory, getConstraint(State, Sym),
- // If Sym is a difference of symbols A - B, then maybe we have range
- // set stored for B - A.
- //
- // If we have range set stored for both A - B and B - A then
- // calculate the effective range set by intersecting the range set
- // for A - B and the negated range set of B - A.
- getRangeForNegatedSub(Sym), getRangeForEqualities(Sym))) {
- return *ConstraintBasedRange;
- }
-
- // If Sym is a comparison expression (except <=>),
- // find any other comparisons with the same operands.
- // See function description.
- if (Optional<RangeSet> CmpRangeSet = getRangeForComparisonSymbol(Sym)) {
- return *CmpRangeSet;
- }
-
- return Visit(Sym);
+ return intersect(
+ RangeFactory,
+ // Of course, we should take the constraint directly associated with
+ // this symbol into consideration.
+ getConstraint(State, Sym),
+ // If Sym is a difference of symbols A - B, then maybe we have range
+ // set stored for B - A.
+ //
+ // If we have range set stored for both A - B and B - A then
+ // calculate the effective range set by intersecting the range set
+ // for A - B and the negated range set of B - A.
+ getRangeForNegatedSub(Sym),
+ // If Sym is a comparison expression (except <=>),
+ // find any other comparisons with the same operands.
+ // See function description.
+ getRangeForComparisonSymbol(Sym),
+ // Apart from the Sym itself, we can infer quite a lot if we look
+ // into subexpressions of Sym.
+ Visit(Sym));
}
RangeSet infer(EquivalenceClass Class) {
@@ -940,7 +1067,7 @@
/// Return a range set subtracting zero from \p Domain.
RangeSet assumeNonZero(RangeSet Domain, QualType T) {
APSIntType IntType = ValueFactory.getAPSIntType(T);
- return Domain.Delete(ValueFactory, RangeFactory, IntType.getZeroValue());
+ return RangeFactory.deletePoint(Domain, IntType.getZeroValue());
}
// FIXME: Once SValBuilder supports unary minus, we should use SValBuilder to
@@ -963,7 +1090,7 @@
SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), T);
if (const RangeSet *NegatedRange = getConstraint(State, NegatedSym)) {
- return NegatedRange->Negate(ValueFactory, RangeFactory);
+ return RangeFactory.negate(*NegatedRange);
}
}
}
@@ -1054,17 +1181,21 @@
return llvm::None;
}
- Optional<RangeSet> getRangeForEqualities(SymbolRef Sym) {
- Optional<EqualityInfo> Equality = EqualityInfo::extract(Sym);
+ Optional<RangeSet> getRangeForEqualities(const SymSymExpr *Sym) {
+ Optional<bool> Equality = meansEquality(Sym);
if (!Equality)
return llvm::None;
- if (Optional<bool> AreEqual = EquivalenceClass::areEqual(
- State, Equality->Left, Equality->Right)) {
- if (*AreEqual == Equality->IsEquality) {
+ if (Optional<bool> AreEqual =
+ EquivalenceClass::areEqual(State, Sym->getLHS(), Sym->getRHS())) {
+ // Here we cover two cases at once:
+ // * if Sym is equality and its operands are known to be equal -> true
+ // * if Sym is disequality and its operands are disequal -> true
+ if (*AreEqual == *Equality) {
return getTrueRange(Sym->getType());
}
+ // Opposite combinations result in false.
return getFalseRange(Sym->getType());
}
@@ -1251,13 +1382,215 @@
}
//===----------------------------------------------------------------------===//
+// Constraint assignment logic
+//===----------------------------------------------------------------------===//
+
+/// ConstraintAssignorBase is a small utility class that unifies visitor
+/// for ranges with a visitor for constraints (rangeset/range/constant).
+///
+/// It is designed to have one derived class, but generally it can have more.
+/// Derived class can control which types we handle by defining methods of the
+/// following form:
+///
+/// bool handle${SYMBOL}To${CONSTRAINT}(const SYMBOL *Sym,
+/// CONSTRAINT Constraint);
+///
+/// where SYMBOL is the type of the symbol (e.g. SymSymExpr, SymbolCast, etc.)
+/// CONSTRAINT is the type of constraint (RangeSet/Range/Const)
+/// return value signifies whether we should try other handle methods
+/// (i.e. false would mean to stop right after calling this method)
+template <class Derived> class ConstraintAssignorBase {
+public:
+ using Const = const llvm::APSInt &;
+
+#define DISPATCH(CLASS) return assign##CLASS##Impl(cast<CLASS>(Sym), Constraint)
+
+#define ASSIGN(CLASS, TO, SYM, CONSTRAINT) \
+ if (!static_cast<Derived *>(this)->assign##CLASS##To##TO(SYM, CONSTRAINT)) \
+ return false
+
+ void assign(SymbolRef Sym, RangeSet Constraint) {
+ assignImpl(Sym, Constraint);
+ }
+
+ bool assignImpl(SymbolRef Sym, RangeSet Constraint) {
+ switch (Sym->getKind()) {
+#define SYMBOL(Id, Parent) \
+ case SymExpr::Id##Kind: \
+ DISPATCH(Id);
+#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
+ }
+ llvm_unreachable("Unknown SymExpr kind!");
+ }
+
+#define DEFAULT_ASSIGN(Id) \
+ bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) { \
+ return true; \
+ } \
+ bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
+ bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
+
+ // When we dispatch for constraint types, we first try to check
+ // if the new constraint is the constant and try the corresponding
+ // assignor methods. If it didn't interrupt, we can proceed to the
+ // range, and finally to the range set.
+#define CONSTRAINT_DISPATCH(Id) \
+ if (const llvm::APSInt *Const = Constraint.getConcreteValue()) { \
+ ASSIGN(Id, Const, Sym, *Const); \
+ } \
+ if (Constraint.size() == 1) { \
+ ASSIGN(Id, Range, Sym, *Constraint.begin()); \
+ } \
+ ASSIGN(Id, RangeSet, Sym, Constraint)
+
+ // Our internal assign method first tries to call assignor methods for all
+ // constraint types that apply. And if not interrupted, continues with its
+ // parent class.
+#define SYMBOL(Id, Parent) \
+ bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) { \
+ CONSTRAINT_DISPATCH(Id); \
+ DISPATCH(Parent); \
+ } \
+ DEFAULT_ASSIGN(Id)
+#define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent)
+#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
+
+ // Default implementations for the top class that doesn't have parents.
+ bool assignSymExprImpl(const SymExpr *Sym, RangeSet Constraint) {
+ CONSTRAINT_DISPATCH(SymExpr);
+ return true;
+ }
+ DEFAULT_ASSIGN(SymExpr);
+
+#undef DISPATCH
+#undef CONSTRAINT_DISPATCH
+#undef DEFAULT_ASSIGN
+#undef ASSIGN
+};
+
+/// A little component aggregating all of the reasoning we have about
+/// assigning new constraints to symbols.
+///
+/// The main purpose of this class is to associate constraints to symbols,
+/// and impose additional constraints on other symbols, when we can imply
+/// them.
+///
+/// It has a nice symmetry with SymbolicRangeInferrer. When the latter
+/// can provide more precise ranges by looking into the operands of the
+/// expression in question, ConstraintAssignor looks into the operands
+/// to see if we can imply more from the new constraint.
+class ConstraintAssignor : public ConstraintAssignorBase<ConstraintAssignor> {
+public:
+ template <class ClassOrSymbol>
+ LLVM_NODISCARD static ProgramStateRef
+ assign(ProgramStateRef State, SValBuilder &Builder, RangeSet::Factory &F,
+ ClassOrSymbol CoS, RangeSet NewConstraint) {
+ if (!State || NewConstraint.isEmpty())
+ return nullptr;
+
+ ConstraintAssignor Assignor{State, Builder, F};
+ return Assignor.assign(CoS, NewConstraint);
+ }
+
+ inline bool assignSymExprToConst(const SymExpr *Sym, Const Constraint);
+ inline bool assignSymSymExprToRangeSet(const SymSymExpr *Sym,
+ RangeSet Constraint);
+
+private:
+ ConstraintAssignor(ProgramStateRef State, SValBuilder &Builder,
+ RangeSet::Factory &F)
+ : State(State), Builder(Builder), RangeFactory(F) {}
+ using Base = ConstraintAssignorBase<ConstraintAssignor>;
+
+ /// Base method for handling new constraints for symbols.
+ LLVM_NODISCARD ProgramStateRef assign(SymbolRef Sym, RangeSet NewConstraint) {
+ // All constraints are actually associated with equivalence classes, and
+ // that's what we are going to do first.
+ State = assign(EquivalenceClass::find(State, Sym), NewConstraint);
+ if (!State)
+ return nullptr;
+
+ // And after that we can check what other things we can get from this
+ // constraint.
+ Base::assign(Sym, NewConstraint);
+ return State;
+ }
+
+ /// Base method for handling new constraints for classes.
+ LLVM_NODISCARD ProgramStateRef assign(EquivalenceClass Class,
+ RangeSet NewConstraint) {
+ // There is a chance that we might need to update constraints for the
+ // classes that are known to be disequal to Class.
+ //
+ // In order for this to be even possible, the new constraint should
+ // be simply a constant because we can't reason about range disequalities.
+ if (const llvm::APSInt *Point = NewConstraint.getConcreteValue()) {
+
+ ConstraintRangeTy Constraints = State->get<ConstraintRange>();
+ ConstraintRangeTy::Factory &CF = State->get_context<ConstraintRange>();
+
+ // Add new constraint.
+ Constraints = CF.add(Constraints, Class, NewConstraint);
+
+ for (EquivalenceClass DisequalClass : Class.getDisequalClasses(State)) {
+ RangeSet UpdatedConstraint = SymbolicRangeInferrer::inferRange(
+ RangeFactory, State, DisequalClass);
+
+ UpdatedConstraint = RangeFactory.deletePoint(UpdatedConstraint, *Point);
+
+ // If we end up with at least one of the disequal classes to be
+ // constrained with an empty range-set, the state is infeasible.
+ if (UpdatedConstraint.isEmpty())
+ return nullptr;
+
+ Constraints = CF.add(Constraints, DisequalClass, UpdatedConstraint);
+ }
+ assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
+ "a state with infeasible constraints");
+
+ return setConstraints(State, Constraints);
+ }
+
+ return setConstraint(State, Class, NewConstraint);
+ }
+
+ ProgramStateRef trackDisequality(ProgramStateRef State, SymbolRef LHS,
+ SymbolRef RHS) {
+ return EquivalenceClass::markDisequal(RangeFactory, State, LHS, RHS);
+ }
+
+ ProgramStateRef trackEquality(ProgramStateRef State, SymbolRef LHS,
+ SymbolRef RHS) {
+ return EquivalenceClass::merge(RangeFactory, State, LHS, RHS);
+ }
+
+ LLVM_NODISCARD Optional<bool> interpreteAsBool(RangeSet Constraint) {
+ assert(!Constraint.isEmpty() && "Empty ranges shouldn't get here");
+
+ if (Constraint.getConcreteValue())
+ return !Constraint.getConcreteValue()->isNullValue();
+
+ APSIntType T{Constraint.getMinValue()};
+ Const Zero = T.getZeroValue();
+ if (!Constraint.contains(Zero))
+ return true;
+
+ return llvm::None;
+ }
+
+ ProgramStateRef State;
+ SValBuilder &Builder;
+ RangeSet::Factory &RangeFactory;
+};
+
+//===----------------------------------------------------------------------===//
// Constraint manager implementation details
//===----------------------------------------------------------------------===//
class RangeConstraintManager : public RangedConstraintManager {
public:
RangeConstraintManager(ExprEngine *EE, SValBuilder &SVB)
- : RangedConstraintManager(EE, SVB) {}
+ : RangedConstraintManager(EE, SVB), F(getBasicVals()) {}
//===------------------------------------------------------------------===//
// Implementation for interface from ConstraintManager.
@@ -1284,6 +1617,15 @@
void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n",
unsigned int Space = 0, bool IsDot = false) const override;
+ void printConstraints(raw_ostream &Out, ProgramStateRef State,
+ const char *NL = "\n", unsigned int Space = 0,
+ bool IsDot = false) const;
+ void printEquivalenceClasses(raw_ostream &Out, ProgramStateRef State,
+ const char *NL = "\n", unsigned int Space = 0,
+ bool IsDot = false) const;
+ void printDisequalities(raw_ostream &Out, ProgramStateRef State,
+ const char *NL = "\n", unsigned int Space = 0,
+ bool IsDot = false) const;
//===------------------------------------------------------------------===//
// Implementation for interface from RangedConstraintManager.
@@ -1326,6 +1668,10 @@
RangeSet getRange(ProgramStateRef State, SymbolRef Sym);
RangeSet getRange(ProgramStateRef State, EquivalenceClass Class);
+ ProgramStateRef setRange(ProgramStateRef State, SymbolRef Sym,
+ RangeSet Range);
+ ProgramStateRef setRange(ProgramStateRef State, EquivalenceClass Class,
+ RangeSet Range);
RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
@@ -1342,89 +1688,64 @@
RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment);
-
- //===------------------------------------------------------------------===//
- // Equality tracking implementation
- //===------------------------------------------------------------------===//
-
- ProgramStateRef trackEQ(RangeSet NewConstraint, ProgramStateRef State,
- SymbolRef Sym, const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
- return track<true>(NewConstraint, State, Sym, Int, Adjustment);
- }
-
- ProgramStateRef trackNE(RangeSet NewConstraint, ProgramStateRef State,
- SymbolRef Sym, const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
- return track<false>(NewConstraint, State, Sym, Int, Adjustment);
- }
-
- template <bool EQ>
- ProgramStateRef track(RangeSet NewConstraint, ProgramStateRef State,
- SymbolRef Sym, const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
- if (NewConstraint.isEmpty())
- // This is an infeasible assumption.
- return nullptr;
-
- ProgramStateRef NewState = setConstraint(State, Sym, NewConstraint);
- if (auto Equality = EqualityInfo::extract(Sym, Int, Adjustment)) {
- // If the original assumption is not Sym + Adjustment !=/</> Int,
- // we should invert IsEquality flag.
- Equality->IsEquality = Equality->IsEquality != EQ;
- return track(NewState, *Equality);
- }
-
- return NewState;
- }
-
- ProgramStateRef track(ProgramStateRef State, EqualityInfo ToTrack) {
- if (ToTrack.IsEquality) {
- return trackEquality(State, ToTrack.Left, ToTrack.Right);
- }
- return trackDisequality(State, ToTrack.Left, ToTrack.Right);
- }
-
- ProgramStateRef trackDisequality(ProgramStateRef State, SymbolRef LHS,
- SymbolRef RHS) {
- return EquivalenceClass::markDisequal(getBasicVals(), F, State, LHS, RHS);
- }
-
- ProgramStateRef trackEquality(ProgramStateRef State, SymbolRef LHS,
- SymbolRef RHS) {
- return EquivalenceClass::merge(getBasicVals(), F, State, LHS, RHS);
- }
-
- LLVM_NODISCARD inline ProgramStateRef setConstraint(ProgramStateRef State,
- EquivalenceClass Class,
- RangeSet Constraint) {
- ConstraintRangeTy Constraints = State->get<ConstraintRange>();
- ConstraintRangeTy::Factory &CF = State->get_context<ConstraintRange>();
-
- // Add new constraint.
- Constraints = CF.add(Constraints, Class, Constraint);
-
- // There is a chance that we might need to update constraints for the
- // classes that are known to be disequal to Class.
- //
- // In order for this to be even possible, the new constraint should
- // be simply a constant because we can't reason about range disequalities.
- if (const llvm::APSInt *Point = Constraint.getConcreteValue())
- for (EquivalenceClass DisequalClass : Class.getDisequalClasses(State)) {
- RangeSet UpdatedConstraint =
- getRange(State, DisequalClass).Delete(getBasicVals(), F, *Point);
- Constraints = CF.add(Constraints, DisequalClass, UpdatedConstraint);
- }
-
- return State->set<ConstraintRange>(Constraints);
- }
-
- LLVM_NODISCARD inline ProgramStateRef
- setConstraint(ProgramStateRef State, SymbolRef Sym, RangeSet Constraint) {
- return setConstraint(State, EquivalenceClass::find(State, Sym), Constraint);
- }
};
+bool ConstraintAssignor::assignSymExprToConst(const SymExpr *Sym,
+ const llvm::APSInt &Constraint) {
+ llvm::SmallSet<EquivalenceClass, 4> SimplifiedClasses;
+ // Iterate over all equivalence classes and try to simplify them.
+ ClassMembersTy Members = State->get<ClassMembers>();
+ for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members) {
+ EquivalenceClass Class = ClassToSymbolSet.first;
+ State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
+ if (!State)
+ return false;
+ SimplifiedClasses.insert(Class);
+ }
+
+ // Trivial equivalence classes (those that have only one symbol member) are
+ // not stored in the State. Thus, we must skim through the constraints as
+ // well. And we try to simplify symbols in the constraints.
+ ConstraintRangeTy Constraints = State->get<ConstraintRange>();
+ for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
+ EquivalenceClass Class = ClassConstraint.first;
+ if (SimplifiedClasses.count(Class)) // Already simplified.
+ continue;
+ State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
+ if (!State)
+ return false;
+ }
+
+ return true;
+}
+
+bool ConstraintAssignor::assignSymSymExprToRangeSet(const SymSymExpr *Sym,
+ RangeSet Constraint) {
+ Optional<bool> ConstraintAsBool = interpreteAsBool(Constraint);
+
+ if (!ConstraintAsBool)
+ return true;
+
+ if (Optional<bool> Equality = meansEquality(Sym)) {
+ // Here we cover two cases:
+ // * if Sym is equality and the new constraint is true -> Sym's operands
+ // should be marked as equal
+ // * if Sym is disequality and the new constraint is false -> Sym's
+ // operands should be also marked as equal
+ if (*Equality == *ConstraintAsBool) {
+ State = trackEquality(State, Sym->getLHS(), Sym->getRHS());
+ } else {
+ // Other combinations leave as with disequal operands.
+ State = trackDisequality(State, Sym->getLHS(), Sym->getRHS());
+ }
+
+ if (!State)
+ return false;
+ }
+
+ return true;
+}
+
} // end anonymous namespace
std::unique_ptr<ConstraintManager>
@@ -1455,8 +1776,19 @@
// EqualityClass implementation details
//===----------------------------------------------------------------------===//
+LLVM_DUMP_METHOD void EquivalenceClass::dumpToStream(ProgramStateRef State,
+ raw_ostream &os) const {
+ SymbolSet ClassMembers = getClassMembers(State);
+ for (const SymbolRef &MemberSym : ClassMembers) {
+ MemberSym->dump();
+ os << "\n";
+ }
+}
+
inline EquivalenceClass EquivalenceClass::find(ProgramStateRef State,
SymbolRef Sym) {
+ assert(State && "State should not be null");
+ assert(Sym && "Symbol should not be null");
// We store far from all Symbol -> Class mappings
if (const EquivalenceClass *NontrivialClass = State->get<ClassMap>(Sym))
return *NontrivialClass;
@@ -1465,19 +1797,17 @@
return Sym;
}
-inline ProgramStateRef EquivalenceClass::merge(BasicValueFactory &BV,
- RangeSet::Factory &F,
+inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
ProgramStateRef State,
SymbolRef First,
SymbolRef Second) {
EquivalenceClass FirstClass = find(State, First);
EquivalenceClass SecondClass = find(State, Second);
- return FirstClass.merge(BV, F, State, SecondClass);
+ return FirstClass.merge(F, State, SecondClass);
}
-inline ProgramStateRef EquivalenceClass::merge(BasicValueFactory &BV,
- RangeSet::Factory &F,
+inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
ProgramStateRef State,
EquivalenceClass Other) {
// It is already the same class.
@@ -1505,15 +1835,14 @@
// its members. Merging is not a trivial operation, so it's easier to
// merge the smaller class into the bigger one.
if (Members.getHeight() >= OtherMembers.getHeight()) {
- return mergeImpl(BV, F, State, Members, Other, OtherMembers);
+ return mergeImpl(F, State, Members, Other, OtherMembers);
} else {
- return Other.mergeImpl(BV, F, State, OtherMembers, *this, Members);
+ return Other.mergeImpl(F, State, OtherMembers, *this, Members);
}
}
inline ProgramStateRef
-EquivalenceClass::mergeImpl(BasicValueFactory &ValueFactory,
- RangeSet::Factory &RangeFactory,
+EquivalenceClass::mergeImpl(RangeSet::Factory &RangeFactory,
ProgramStateRef State, SymbolSet MyMembers,
EquivalenceClass Other, SymbolSet OtherMembers) {
// Essentially what we try to recreate here is some kind of union-find
@@ -1536,7 +1865,7 @@
// Intersection here makes perfect sense because both of these constraints
// must hold for the whole new class.
if (Optional<RangeSet> NewClassConstraint =
- intersect(ValueFactory, RangeFactory, getConstraint(State, *this),
+ intersect(RangeFactory, getConstraint(State, *this),
getConstraint(State, Other))) {
// NOTE: Essentially, NewClassConstraint should NEVER be infeasible because
// range inferrer shouldn't generate ranges incompatible with
@@ -1552,6 +1881,9 @@
// Assign new constraints for this class.
Constraints = CRF.add(Constraints, *this, *NewClassConstraint);
+ assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
+ "a state with infeasible constraints");
+
State = State->set<ConstraintRange>(Constraints);
}
@@ -1585,6 +1917,11 @@
// 4. Update disequality relations
ClassSet DisequalToOther = Other.getDisequalClasses(DisequalityInfo, CF);
+ // We are about to merge two classes but they are already known to be
+ // non-equal. This is a contradiction.
+ if (DisequalToOther.contains(*this))
+ return nullptr;
+
if (!DisequalToOther.isEmpty()) {
ClassSet DisequalToThis = getDisequalClasses(DisequalityInfo, CF);
DisequalityInfo = DF.remove(DisequalityInfo, Other);
@@ -1622,7 +1959,7 @@
return State->get_context<SymbolSet>();
}
-SymbolSet EquivalenceClass::getClassMembers(ProgramStateRef State) {
+SymbolSet EquivalenceClass::getClassMembers(ProgramStateRef State) const {
if (const SymbolSet *Members = State->get<ClassMembers>(*this))
return *Members;
@@ -1632,34 +1969,31 @@
return F.add(F.getEmptySet(), getRepresentativeSymbol());
}
-bool EquivalenceClass::isTrivial(ProgramStateRef State) {
+bool EquivalenceClass::isTrivial(ProgramStateRef State) const {
return State->get<ClassMembers>(*this) == nullptr;
}
bool EquivalenceClass::isTriviallyDead(ProgramStateRef State,
- SymbolReaper &Reaper) {
+ SymbolReaper &Reaper) const {
return isTrivial(State) && Reaper.isDead(getRepresentativeSymbol());
}
-inline ProgramStateRef EquivalenceClass::markDisequal(BasicValueFactory &VF,
- RangeSet::Factory &RF,
+inline ProgramStateRef EquivalenceClass::markDisequal(RangeSet::Factory &RF,
ProgramStateRef State,
SymbolRef First,
SymbolRef Second) {
- return markDisequal(VF, RF, State, find(State, First), find(State, Second));
+ return markDisequal(RF, State, find(State, First), find(State, Second));
}
-inline ProgramStateRef EquivalenceClass::markDisequal(BasicValueFactory &VF,
- RangeSet::Factory &RF,
+inline ProgramStateRef EquivalenceClass::markDisequal(RangeSet::Factory &RF,
ProgramStateRef State,
EquivalenceClass First,
EquivalenceClass Second) {
- return First.markDisequal(VF, RF, State, Second);
+ return First.markDisequal(RF, State, Second);
}
inline ProgramStateRef
-EquivalenceClass::markDisequal(BasicValueFactory &VF, RangeSet::Factory &RF,
- ProgramStateRef State,
+EquivalenceClass::markDisequal(RangeSet::Factory &RF, ProgramStateRef State,
EquivalenceClass Other) const {
// If we know that two classes are equal, we can only produce an infeasible
// state.
@@ -1672,10 +2006,14 @@
// Disequality is a symmetric relation, so if we mark A as disequal to B,
// we should also mark B as disequalt to A.
- addToDisequalityInfo(DisequalityInfo, Constraints, VF, RF, State, *this,
- Other);
- addToDisequalityInfo(DisequalityInfo, Constraints, VF, RF, State, Other,
- *this);
+ if (!addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, *this,
+ Other) ||
+ !addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, Other,
+ *this))
+ return nullptr;
+
+ assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
+ "a state with infeasible constraints");
State = State->set<DisequalityMap>(DisequalityInfo);
State = State->set<ConstraintRange>(Constraints);
@@ -1683,10 +2021,10 @@
return State;
}
-inline void EquivalenceClass::addToDisequalityInfo(
+inline bool EquivalenceClass::addToDisequalityInfo(
DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
- BasicValueFactory &VF, RangeSet::Factory &RF, ProgramStateRef State,
- EquivalenceClass First, EquivalenceClass Second) {
+ RangeSet::Factory &RF, ProgramStateRef State, EquivalenceClass First,
+ EquivalenceClass Second) {
// 1. Get all of the required factories.
DisequalityMapTy::Factory &F = State->get_context<DisequalityMap>();
@@ -1709,19 +2047,31 @@
if (const llvm::APSInt *Point = SecondConstraint->getConcreteValue()) {
RangeSet FirstConstraint = SymbolicRangeInferrer::inferRange(
- VF, RF, State, First.getRepresentativeSymbol());
+ RF, State, First.getRepresentativeSymbol());
- FirstConstraint = FirstConstraint.Delete(VF, RF, *Point);
+ FirstConstraint = RF.deletePoint(FirstConstraint, *Point);
+
+ // If the First class is about to be constrained with an empty
+ // range-set, the state is infeasible.
+ if (FirstConstraint.isEmpty())
+ return false;
+
Constraints = CRF.add(Constraints, First, FirstConstraint);
}
+
+ return true;
}
inline Optional<bool> EquivalenceClass::areEqual(ProgramStateRef State,
SymbolRef FirstSym,
SymbolRef SecondSym) {
- EquivalenceClass First = find(State, FirstSym);
- EquivalenceClass Second = find(State, SecondSym);
+ return EquivalenceClass::areEqual(State, find(State, FirstSym),
+ find(State, SecondSym));
+}
+inline Optional<bool> EquivalenceClass::areEqual(ProgramStateRef State,
+ EquivalenceClass First,
+ EquivalenceClass Second) {
// The same equivalence class => symbols are equal.
if (First == Second)
return true;
@@ -1736,6 +2086,29 @@
return llvm::None;
}
+// Iterate over all symbols and try to simplify them. Once a symbol is
+// simplified then we check if we can merge the simplified symbol's equivalence
+// class to this class. This way, we simplify not just the symbols but the
+// classes as well: we strive to keep the number of the classes to be the
+// absolute minimum.
+LLVM_NODISCARD ProgramStateRef
+EquivalenceClass::simplify(SValBuilder &SVB, RangeSet::Factory &F,
+ ProgramStateRef State, EquivalenceClass Class) {
+ SymbolSet ClassMembers = Class.getClassMembers(State);
+ for (const SymbolRef &MemberSym : ClassMembers) {
+ SymbolRef SimplifiedMemberSym = ento::simplify(State, MemberSym);
+ if (SimplifiedMemberSym && MemberSym != SimplifiedMemberSym) {
+ // The simplified symbol should be the member of the original Class,
+ // however, it might be in another existing class at the moment. We
+ // have to merge these classes.
+ State = merge(F, State, MemberSym, SimplifiedMemberSym);
+ if (!State)
+ return nullptr;
+ }
+ }
+ return State;
+}
+
inline ClassSet EquivalenceClass::getDisequalClasses(ProgramStateRef State,
SymbolRef Sym) {
return find(State, Sym).getDisequalClasses(State);
@@ -1862,7 +2235,7 @@
llvm::APSInt Zero = IntType.getZeroValue();
// Check if zero is in the set of possible values.
- if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty())
+ if (!Ranges->contains(Zero))
return false;
// Zero is a possible value, but it is not the /only/ possible value.
@@ -2017,12 +2390,13 @@
RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
SymbolRef Sym) {
- return SymbolicRangeInferrer::inferRange(getBasicVals(), F, State, Sym);
+ return SymbolicRangeInferrer::inferRange(F, State, Sym);
}
-RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
- EquivalenceClass Class) {
- return SymbolicRangeInferrer::inferRange(getBasicVals(), F, State, Class);
+ProgramStateRef RangeConstraintManager::setRange(ProgramStateRef State,
+ SymbolRef Sym,
+ RangeSet Range) {
+ return ConstraintAssignor::assign(State, getSValBuilder(), F, Sym, Range);
}
//===------------------------------------------------------------------------===
@@ -2047,10 +2421,10 @@
return St;
llvm::APSInt Point = AdjustmentType.convert(Int) - Adjustment;
+ RangeSet New = getRange(St, Sym);
+ New = F.deletePoint(New, Point);
- RangeSet New = getRange(St, Sym).Delete(getBasicVals(), F, Point);
-
- return trackNE(New, St, Sym, Int, Adjustment);
+ return setRange(St, Sym, New);
}
ProgramStateRef
@@ -2064,9 +2438,10 @@
// [Int-Adjustment, Int-Adjustment]
llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
- RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
+ RangeSet New = getRange(St, Sym);
+ New = F.intersect(New, AdjInt);
- return trackEQ(New, St, Sym, Int, Adjustment);
+ return setRange(St, Sym, New);
}
RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St,
@@ -2094,7 +2469,8 @@
llvm::APSInt Upper = ComparisonVal - Adjustment;
--Upper;
- return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ RangeSet Result = getRange(St, Sym);
+ return F.intersect(Result, Lower, Upper);
}
ProgramStateRef
@@ -2102,7 +2478,7 @@
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
- return trackNE(New, St, Sym, Int, Adjustment);
+ return setRange(St, Sym, New);
}
RangeSet RangeConstraintManager::getSymGTRange(ProgramStateRef St,
@@ -2130,7 +2506,8 @@
llvm::APSInt Upper = Max - Adjustment;
++Lower;
- return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ RangeSet SymRange = getRange(St, Sym);
+ return F.intersect(SymRange, Lower, Upper);
}
ProgramStateRef
@@ -2138,7 +2515,7 @@
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
- return trackNE(New, St, Sym, Int, Adjustment);
+ return setRange(St, Sym, New);
}
RangeSet RangeConstraintManager::getSymGERange(ProgramStateRef St,
@@ -2166,7 +2543,8 @@
llvm::APSInt Lower = ComparisonVal - Adjustment;
llvm::APSInt Upper = Max - Adjustment;
- return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ RangeSet SymRange = getRange(St, Sym);
+ return F.intersect(SymRange, Lower, Upper);
}
ProgramStateRef
@@ -2174,7 +2552,7 @@
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
- return New.isEmpty() ? nullptr : setConstraint(St, Sym, New);
+ return setRange(St, Sym, New);
}
RangeSet
@@ -2202,7 +2580,8 @@
llvm::APSInt Lower = Min - Adjustment;
llvm::APSInt Upper = ComparisonVal - Adjustment;
- return RS().Intersect(getBasicVals(), F, Lower, Upper);
+ RangeSet Default = RS();
+ return F.intersect(Default, Lower, Upper);
}
RangeSet RangeConstraintManager::getSymLERange(ProgramStateRef St,
@@ -2217,7 +2596,7 @@
const llvm::APSInt &Int,
const llvm::APSInt &Adjustment) {
RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
- return New.isEmpty() ? nullptr : setConstraint(St, Sym, New);
+ return setRange(St, Sym, New);
}
ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange(
@@ -2227,7 +2606,7 @@
if (New.isEmpty())
return nullptr;
RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment);
- return Out.isEmpty() ? nullptr : setConstraint(State, Sym, Out);
+ return setRange(State, Sym, Out);
}
ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
@@ -2235,8 +2614,8 @@
const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
- RangeSet New(RangeLT.addRange(F, RangeGT));
- return New.isEmpty() ? nullptr : setConstraint(State, Sym, New);
+ RangeSet New(F.add(RangeLT, RangeGT));
+ return setRange(State, Sym, New);
}
//===----------------------------------------------------------------------===//
@@ -2246,6 +2625,23 @@
void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State,
const char *NL, unsigned int Space,
bool IsDot) const {
+ printConstraints(Out, State, NL, Space, IsDot);
+ printEquivalenceClasses(Out, State, NL, Space, IsDot);
+ printDisequalities(Out, State, NL, Space, IsDot);
+}
+
+static std::string toString(const SymbolRef &Sym) {
+ std::string S;
+ llvm::raw_string_ostream O(S);
+ Sym->dumpToStream(O);
+ return O.str();
+}
+
+void RangeConstraintManager::printConstraints(raw_ostream &Out,
+ ProgramStateRef State,
+ const char *NL,
+ unsigned int Space,
+ bool IsDot) const {
ConstraintRangeTy Constraints = State->get<ConstraintRange>();
Indent(Out, Space, IsDot) << "\"constraints\": ";
@@ -2254,25 +2650,162 @@
return;
}
+ std::map<std::string, RangeSet> OrderedConstraints;
+ for (std::pair<EquivalenceClass, RangeSet> P : Constraints) {
+ SymbolSet ClassMembers = P.first.getClassMembers(State);
+ for (const SymbolRef &ClassMember : ClassMembers) {
+ bool insertion_took_place;
+ std::tie(std::ignore, insertion_took_place) =
+ OrderedConstraints.insert({toString(ClassMember), P.second});
+ assert(insertion_took_place &&
+ "two symbols should not have the same dump");
+ }
+ }
+
++Space;
Out << '[' << NL;
bool First = true;
- for (std::pair<EquivalenceClass, RangeSet> P : Constraints) {
- SymbolSet ClassMembers = P.first.getClassMembers(State);
-
- // We can print the same constraint for every class member.
- for (SymbolRef ClassMember : ClassMembers) {
- if (First) {
- First = false;
- } else {
- Out << ',';
- Out << NL;
- }
- Indent(Out, Space, IsDot)
- << "{ \"symbol\": \"" << ClassMember << "\", \"range\": \"";
- P.second.print(Out);
- Out << "\" }";
+ for (std::pair<std::string, RangeSet> P : OrderedConstraints) {
+ if (First) {
+ First = false;
+ } else {
+ Out << ',';
+ Out << NL;
}
+ Indent(Out, Space, IsDot)
+ << "{ \"symbol\": \"" << P.first << "\", \"range\": \"";
+ P.second.dump(Out);
+ Out << "\" }";
+ }
+ Out << NL;
+
+ --Space;
+ Indent(Out, Space, IsDot) << "]," << NL;
+}
+
+static std::string toString(ProgramStateRef State, EquivalenceClass Class) {
+ SymbolSet ClassMembers = Class.getClassMembers(State);
+ llvm::SmallVector<SymbolRef, 8> ClassMembersSorted(ClassMembers.begin(),
+ ClassMembers.end());
+ llvm::sort(ClassMembersSorted,
+ [](const SymbolRef &LHS, const SymbolRef &RHS) {
+ return toString(LHS) < toString(RHS);
+ });
+
+ bool FirstMember = true;
+
+ std::string Str;
+ llvm::raw_string_ostream Out(Str);
+ Out << "[ ";
+ for (SymbolRef ClassMember : ClassMembersSorted) {
+ if (FirstMember)
+ FirstMember = false;
+ else
+ Out << ", ";
+ Out << "\"" << ClassMember << "\"";
+ }
+ Out << " ]";
+ return Out.str();
+}
+
+void RangeConstraintManager::printEquivalenceClasses(raw_ostream &Out,
+ ProgramStateRef State,
+ const char *NL,
+ unsigned int Space,
+ bool IsDot) const {
+ ClassMembersTy Members = State->get<ClassMembers>();
+
+ Indent(Out, Space, IsDot) << "\"equivalence_classes\": ";
+ if (Members.isEmpty()) {
+ Out << "null," << NL;
+ return;
+ }
+
+ std::set<std::string> MembersStr;
+ for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members)
+ MembersStr.insert(toString(State, ClassToSymbolSet.first));
+
+ ++Space;
+ Out << '[' << NL;
+ bool FirstClass = true;
+ for (const std::string &Str : MembersStr) {
+ if (FirstClass) {
+ FirstClass = false;
+ } else {
+ Out << ',';
+ Out << NL;
+ }
+ Indent(Out, Space, IsDot);
+ Out << Str;
+ }
+ Out << NL;
+
+ --Space;
+ Indent(Out, Space, IsDot) << "]," << NL;
+}
+
+void RangeConstraintManager::printDisequalities(raw_ostream &Out,
+ ProgramStateRef State,
+ const char *NL,
+ unsigned int Space,
+ bool IsDot) const {
+ DisequalityMapTy Disequalities = State->get<DisequalityMap>();
+
+ Indent(Out, Space, IsDot) << "\"disequality_info\": ";
+ if (Disequalities.isEmpty()) {
+ Out << "null," << NL;
+ return;
+ }
+
+ // Transform the disequality info to an ordered map of
+ // [string -> (ordered set of strings)]
+ using EqClassesStrTy = std::set<std::string>;
+ using DisequalityInfoStrTy = std::map<std::string, EqClassesStrTy>;
+ DisequalityInfoStrTy DisequalityInfoStr;
+ for (std::pair<EquivalenceClass, ClassSet> ClassToDisEqSet : Disequalities) {
+ EquivalenceClass Class = ClassToDisEqSet.first;
+ ClassSet DisequalClasses = ClassToDisEqSet.second;
+ EqClassesStrTy MembersStr;
+ for (EquivalenceClass DisEqClass : DisequalClasses)
+ MembersStr.insert(toString(State, DisEqClass));
+ DisequalityInfoStr.insert({toString(State, Class), MembersStr});
+ }
+
+ ++Space;
+ Out << '[' << NL;
+ bool FirstClass = true;
+ for (std::pair<std::string, EqClassesStrTy> ClassToDisEqSet :
+ DisequalityInfoStr) {
+ const std::string &Class = ClassToDisEqSet.first;
+ if (FirstClass) {
+ FirstClass = false;
+ } else {
+ Out << ',';
+ Out << NL;
+ }
+ Indent(Out, Space, IsDot) << "{" << NL;
+ unsigned int DisEqSpace = Space + 1;
+ Indent(Out, DisEqSpace, IsDot) << "\"class\": ";
+ Out << Class;
+ const EqClassesStrTy &DisequalClasses = ClassToDisEqSet.second;
+ if (!DisequalClasses.empty()) {
+ Out << "," << NL;
+ Indent(Out, DisEqSpace, IsDot) << "\"disequal_to\": [" << NL;
+ unsigned int DisEqClassSpace = DisEqSpace + 1;
+ Indent(Out, DisEqClassSpace, IsDot);
+ bool FirstDisEqClass = true;
+ for (const std::string &DisEqClass : DisequalClasses) {
+ if (FirstDisEqClass) {
+ FirstDisEqClass = false;
+ } else {
+ Out << ',' << NL;
+ Indent(Out, DisEqClassSpace, IsDot);
+ }
+ Out << DisEqClass;
+ }
+ Out << "]" << NL;
+ }
+ Indent(Out, Space, IsDot) << "}";
}
Out << NL;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
index e7a03e6..d227c02 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp
@@ -23,12 +23,14 @@
ProgramStateRef RangedConstraintManager::assumeSym(ProgramStateRef State,
SymbolRef Sym,
bool Assumption) {
+ Sym = simplify(State, Sym);
+
// Handle SymbolData.
- if (isa<SymbolData>(Sym)) {
+ if (isa<SymbolData>(Sym))
return assumeSymUnsupported(State, Sym, Assumption);
- // Handle symbolic expression.
- } else if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(Sym)) {
+ // Handle symbolic expression.
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(Sym)) {
// We can only simplify expressions whose RHS is an integer.
BinaryOperator::Opcode op = SIE->getOpcode();
@@ -93,6 +95,9 @@
ProgramStateRef RangedConstraintManager::assumeSymInclusiveRange(
ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
const llvm::APSInt &To, bool InRange) {
+
+ Sym = simplify(State, Sym);
+
// Get the type used for calculating wraparound.
BasicValueFactory &BVF = getBasicVals();
APSIntType WraparoundType = BVF.getAPSIntType(Sym->getType());
@@ -121,6 +126,8 @@
ProgramStateRef
RangedConstraintManager::assumeSymUnsupported(ProgramStateRef State,
SymbolRef Sym, bool Assumption) {
+ Sym = simplify(State, Sym);
+
BasicValueFactory &BVF = getBasicVals();
QualType T = Sym->getType();
@@ -219,6 +226,13 @@
}
}
-} // end of namespace ento
+SymbolRef simplify(ProgramStateRef State, SymbolRef Sym) {
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+ SVal SimplifiedVal = SVB.simplifySVal(State, SVB.makeSymbolVal(Sym));
+ if (SymbolRef SimplifiedSym = SimplifiedVal.getAsSymbol())
+ return SimplifiedSym;
+ return Sym;
+}
+} // end of namespace ento
} // end of namespace clang
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
index 57fde32..4ffa1aa 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -23,7 +23,6 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
@@ -1479,7 +1478,7 @@
return UnknownVal();
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
- return CastRetrievedVal(getBindingForField(B, FR), FR, T);
+ return svalBuilder.evalCast(getBindingForField(B, FR), T, QualType{});
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
// FIXME: Here we actually perform an implicit conversion from the loaded
@@ -1487,7 +1486,7 @@
// more intelligently. For example, an 'element' can encompass multiple
// bound regions (e.g., several bound bytes), or could be a subset of
// a larger value.
- return CastRetrievedVal(getBindingForElement(B, ER), ER, T);
+ return svalBuilder.evalCast(getBindingForElement(B, ER), T, QualType{});
}
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
@@ -1497,7 +1496,7 @@
// reinterpretted, it is possible we stored a different value that could
// fit within the ivar. Either we need to cast these when storing them
// or reinterpret them lazily (as we do here).
- return CastRetrievedVal(getBindingForObjCIvar(B, IVR), IVR, T);
+ return svalBuilder.evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});
}
if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
@@ -1507,7 +1506,7 @@
// variable is reinterpretted, it is possible we stored a different value
// that could fit within the variable. Either we need to cast these when
// storing them or reinterpret them lazily (as we do here).
- return CastRetrievedVal(getBindingForVar(B, VR), VR, T);
+ return svalBuilder.evalCast(getBindingForVar(B, VR), T, QualType{});
}
const SVal *V = B.lookup(R, BindingKey::Direct);
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 72b8ada..b459b5a 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -107,7 +107,7 @@
return val;
}
- return evalCastFromNonLoc(val.castAs<NonLoc>(), ArrayIndexTy);
+ return evalCast(val, ArrayIndexTy, QualType{});
}
nonloc::ConcreteInt SValBuilder::makeBoolVal(const CXXBoolLiteralExpr *boolean){
@@ -192,12 +192,19 @@
const LocationContext *LCtx,
unsigned VisitCount) {
QualType T = E->getType();
- assert(Loc::isLocType(T));
- assert(SymbolManager::canSymbolicate(T));
- if (T->isNullPtrType())
- return makeZeroVal(T);
+ return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
+}
- SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
+DefinedOrUnknownSVal
+SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
+ const LocationContext *LCtx,
+ QualType type, unsigned VisitCount) {
+ assert(Loc::isLocType(type));
+ assert(SymbolManager::canSymbolicate(type));
+ if (type->isNullPtrType())
+ return makeZeroVal(type);
+
+ SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, VisitCount);
return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
}
@@ -268,6 +275,13 @@
return loc::MemRegionVal(BD);
}
+Optional<loc::MemRegionVal>
+SValBuilder::getCastedMemRegionVal(const MemRegion *R, QualType Ty) {
+ if (auto OptR = StateMgr.getStoreManager().castRegion(R, Ty))
+ return loc::MemRegionVal(*OptR);
+ return None;
+}
+
/// Return a memory region for the 'this' object reference.
loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
const StackFrameContext *SFC) {
@@ -423,6 +437,14 @@
return UnknownVal();
}
+ if (op == BinaryOperatorKind::BO_Cmp) {
+ // We can't reason about C++20 spaceship operator yet.
+ //
+ // FIXME: Support C++20 spaceship operator.
+ // The main problem here is that the result is not integer.
+ return UnknownVal();
+ }
+
if (Optional<Loc> LV = lhs.getAs<Loc>()) {
if (Optional<Loc> RV = rhs.getAs<Loc>())
return evalBinOpLL(state, op, *LV, *RV, type);
@@ -530,108 +552,272 @@
return evalCast(val, castTy, originalTy);
}
-// FIXME: should rewrite according to the cast kind.
-SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
- castTy = Context.getCanonicalType(castTy);
- originalTy = Context.getCanonicalType(originalTy);
- if (val.isUnknownOrUndef() || castTy == originalTy)
- return val;
+//===----------------------------------------------------------------------===//
+// Cast methods.
+// `evalCast` is the main method
+// `evalCastKind` and `evalCastSubKind` are helpers
+//===----------------------------------------------------------------------===//
- if (castTy->isBooleanType()) {
- if (val.isUnknownOrUndef())
- return val;
- if (val.isConstant())
- return makeTruthVal(!val.isZeroConstant(), castTy);
- if (!Loc::isLocType(originalTy) &&
- !originalTy->isIntegralOrEnumerationType() &&
- !originalTy->isMemberPointerType())
- return UnknownVal();
- if (SymbolRef Sym = val.getAsSymbol(true)) {
- BasicValueFactory &BVF = getBasicValueFactory();
- // FIXME: If we had a state here, we could see if the symbol is known to
- // be zero, but we don't.
- return makeNonLoc(Sym, BO_NE, BVF.getValue(0, Sym->getType()), castTy);
- }
- // Loc values are not always true, they could be weakly linked functions.
- if (Optional<Loc> L = val.getAs<Loc>())
- return evalCastFromLoc(*L, castTy);
+/// Cast a given SVal to another SVal using given QualType's.
+/// \param V -- SVal that should be casted.
+/// \param CastTy -- QualType that V should be casted according to.
+/// \param OriginalTy -- QualType which is associated to V. It provides
+/// additional information about what type the cast performs from.
+/// \returns the most appropriate casted SVal.
+/// Note: Many cases don't use an exact OriginalTy. It can be extracted
+/// from SVal or the cast can performs unconditionaly. Always pass OriginalTy!
+/// It can be crucial in certain cases and generates different results.
+/// FIXME: If `OriginalTy.isNull()` is true, then cast performs based on CastTy
+/// only. This behavior is uncertain and should be improved.
+SVal SValBuilder::evalCast(SVal V, QualType CastTy, QualType OriginalTy) {
+ if (CastTy.isNull())
+ return V;
- Loc L = val.castAs<nonloc::LocAsInteger>().getLoc();
- return evalCastFromLoc(L, castTy);
+ CastTy = Context.getCanonicalType(CastTy);
+
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ if (!IsUnknownOriginalType) {
+ OriginalTy = Context.getCanonicalType(OriginalTy);
+
+ if (CastTy == OriginalTy)
+ return V;
+
+ // FIXME: Move this check to the most appropriate
+ // evalCastKind/evalCastSubKind function. For const casts, casts to void,
+ // just propagate the value.
+ if (!CastTy->isVariableArrayType() && !OriginalTy->isVariableArrayType())
+ if (shouldBeModeledWithNoOp(Context, Context.getPointerType(CastTy),
+ Context.getPointerType(OriginalTy)))
+ return V;
}
- // For const casts, casts to void, just propagate the value.
- if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
- if (shouldBeModeledWithNoOp(Context, Context.getPointerType(castTy),
- Context.getPointerType(originalTy)))
- return val;
+ // Cast SVal according to kinds.
+ switch (V.getBaseKind()) {
+ case SVal::UndefinedValKind:
+ return evalCastKind(V.castAs<UndefinedVal>(), CastTy, OriginalTy);
+ case SVal::UnknownValKind:
+ return evalCastKind(V.castAs<UnknownVal>(), CastTy, OriginalTy);
+ case SVal::LocKind:
+ return evalCastKind(V.castAs<Loc>(), CastTy, OriginalTy);
+ case SVal::NonLocKind:
+ return evalCastKind(V.castAs<NonLoc>(), CastTy, OriginalTy);
+ }
- // Check for casts from pointers to integers.
- if (castTy->isIntegralOrEnumerationType() && Loc::isLocType(originalTy))
- return evalCastFromLoc(val.castAs<Loc>(), castTy);
+ llvm_unreachable("Unknown SVal kind");
+}
- // Check for casts from integers to pointers.
- if (Loc::isLocType(castTy) && originalTy->isIntegralOrEnumerationType()) {
- if (Optional<nonloc::LocAsInteger> LV = val.getAs<nonloc::LocAsInteger>()) {
- if (const MemRegion *R = LV->getLoc().getAsRegion()) {
- StoreManager &storeMgr = StateMgr.getStoreManager();
- R = storeMgr.castRegion(R, castTy);
- return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
+SVal SValBuilder::evalCastKind(UndefinedVal V, QualType CastTy,
+ QualType OriginalTy) {
+ return V;
+}
+
+SVal SValBuilder::evalCastKind(UnknownVal V, QualType CastTy,
+ QualType OriginalTy) {
+ return V;
+}
+
+SVal SValBuilder::evalCastKind(Loc V, QualType CastTy, QualType OriginalTy) {
+ switch (V.getSubKind()) {
+ case loc::ConcreteIntKind:
+ return evalCastSubKind(V.castAs<loc::ConcreteInt>(), CastTy, OriginalTy);
+ case loc::GotoLabelKind:
+ return evalCastSubKind(V.castAs<loc::GotoLabel>(), CastTy, OriginalTy);
+ case loc::MemRegionValKind:
+ return evalCastSubKind(V.castAs<loc::MemRegionVal>(), CastTy, OriginalTy);
+ }
+
+ llvm_unreachable("Unknown SVal kind");
+}
+
+SVal SValBuilder::evalCastKind(NonLoc V, QualType CastTy, QualType OriginalTy) {
+ switch (V.getSubKind()) {
+ case nonloc::CompoundValKind:
+ return evalCastSubKind(V.castAs<nonloc::CompoundVal>(), CastTy, OriginalTy);
+ case nonloc::ConcreteIntKind:
+ return evalCastSubKind(V.castAs<nonloc::ConcreteInt>(), CastTy, OriginalTy);
+ case nonloc::LazyCompoundValKind:
+ return evalCastSubKind(V.castAs<nonloc::LazyCompoundVal>(), CastTy,
+ OriginalTy);
+ case nonloc::LocAsIntegerKind:
+ return evalCastSubKind(V.castAs<nonloc::LocAsInteger>(), CastTy,
+ OriginalTy);
+ case nonloc::SymbolValKind:
+ return evalCastSubKind(V.castAs<nonloc::SymbolVal>(), CastTy, OriginalTy);
+ case nonloc::PointerToMemberKind:
+ return evalCastSubKind(V.castAs<nonloc::PointerToMember>(), CastTy,
+ OriginalTy);
+ }
+
+ llvm_unreachable("Unknown SVal kind");
+}
+
+SVal SValBuilder::evalCastSubKind(loc::ConcreteInt V, QualType CastTy,
+ QualType OriginalTy) {
+ // Pointer to bool.
+ if (CastTy->isBooleanType())
+ return makeTruthVal(V.getValue().getBoolValue(), CastTy);
+
+ // Pointer to integer.
+ if (CastTy->isIntegralOrEnumerationType()) {
+ llvm::APSInt Value = V.getValue();
+ BasicVals.getAPSIntType(CastTy).apply(Value);
+ return makeIntVal(Value);
+ }
+
+ // Pointer to any pointer.
+ if (Loc::isLocType(CastTy))
+ return V;
+
+ // Pointer to whatever else.
+ return UnknownVal();
+}
+
+SVal SValBuilder::evalCastSubKind(loc::GotoLabel V, QualType CastTy,
+ QualType OriginalTy) {
+ // Pointer to bool.
+ if (CastTy->isBooleanType())
+ // Labels are always true.
+ return makeTruthVal(true, CastTy);
+
+ // Pointer to integer.
+ if (CastTy->isIntegralOrEnumerationType()) {
+ const unsigned BitWidth = Context.getIntWidth(CastTy);
+ return makeLocAsInteger(V, BitWidth);
+ }
+
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ if (!IsUnknownOriginalType) {
+ // Array to pointer.
+ if (isa<ArrayType>(OriginalTy))
+ if (CastTy->isPointerType() || CastTy->isReferenceType())
+ return UnknownVal();
+ }
+
+ // Pointer to any pointer.
+ if (Loc::isLocType(CastTy))
+ return V;
+
+ // Pointer to whatever else.
+ return UnknownVal();
+}
+
+static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) {
+ return ty1->getPointeeType().getCanonicalType().getTypePtr() ==
+ ty2->getPointeeType().getCanonicalType().getTypePtr();
+}
+
+SVal SValBuilder::evalCastSubKind(loc::MemRegionVal V, QualType CastTy,
+ QualType OriginalTy) {
+ // Pointer to bool.
+ if (CastTy->isBooleanType()) {
+ const MemRegion *R = V.getRegion();
+ if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R))
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
+ if (FD->isWeak())
+ // FIXME: Currently we are using an extent symbol here,
+ // because there are no generic region address metadata
+ // symbols to use, only content metadata.
+ return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR));
+
+ if (const SymbolicRegion *SymR = R->getSymbolicBase()) {
+ SymbolRef Sym = SymR->getSymbol();
+ QualType Ty = Sym->getType();
+ // This change is needed for architectures with varying
+ // pointer widths. See the amdgcn opencl reproducer with
+ // this change as an example: solver-sym-simplification-ptr-bool.cl
+ // FIXME: We could encounter a reference here,
+ // try returning a concrete 'true' since it might
+ // be easier on the solver.
+ // FIXME: Cleanup remainder of `getZeroWithPtrWidth ()`
+ // and `getIntWithPtrWidth()` functions to prevent future
+ // confusion
+ const llvm::APSInt &Zero = Ty->isReferenceType()
+ ? BasicVals.getZeroWithPtrWidth()
+ : BasicVals.getZeroWithTypeSize(Ty);
+ return makeNonLoc(Sym, BO_NE, Zero, CastTy);
+ }
+ // Non-symbolic memory regions are always true.
+ return makeTruthVal(true, CastTy);
+ }
+
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ // Try to cast to array
+ const auto *ArrayTy =
+ IsUnknownOriginalType
+ ? nullptr
+ : dyn_cast<ArrayType>(OriginalTy.getCanonicalType());
+
+ // Pointer to integer.
+ if (CastTy->isIntegralOrEnumerationType()) {
+ SVal Val = V;
+ // Array to integer.
+ if (ArrayTy) {
+ // We will always decay to a pointer.
+ QualType ElemTy = ArrayTy->getElementType();
+ Val = StateMgr.ArrayToPointer(V, ElemTy);
+ // FIXME: Keep these here for now in case we decide soon that we
+ // need the original decayed type.
+ // QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
+ // QualType pointerTy = C.getPointerType(elemTy);
+ }
+ const unsigned BitWidth = Context.getIntWidth(CastTy);
+ return makeLocAsInteger(Val.castAs<Loc>(), BitWidth);
+ }
+
+ // Pointer to pointer.
+ if (Loc::isLocType(CastTy)) {
+
+ if (IsUnknownOriginalType) {
+ // When retrieving symbolic pointer and expecting a non-void pointer,
+ // wrap them into element regions of the expected type if necessary.
+ // It is necessary to make sure that the retrieved value makes sense,
+ // because there's no other cast in the AST that would tell us to cast
+ // it to the correct pointer type. We might need to do that for non-void
+ // pointers as well.
+ // FIXME: We really need a single good function to perform casts for us
+ // correctly every time we need it.
+ const MemRegion *R = V.getRegion();
+ if (CastTy->isPointerType() && !CastTy->isVoidPointerType()) {
+ if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
+ QualType SRTy = SR->getSymbol()->getType();
+ if (!hasSameUnqualifiedPointeeType(SRTy, CastTy)) {
+ if (auto OptMemRegV = getCastedMemRegionVal(SR, CastTy))
+ return *OptMemRegV;
+ }
+ }
}
- return LV->getLoc();
+ // Next fixes pointer dereference using type different from its initial
+ // one. See PR37503 and PR49007 for details.
+ if (const auto *ER = dyn_cast<ElementRegion>(R)) {
+ if (auto OptMemRegV = getCastedMemRegionVal(ER, CastTy))
+ return *OptMemRegV;
+ }
+
+ return V;
}
- return dispatchCast(val, castTy);
- }
- // Just pass through function and block pointers.
- if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
- assert(Loc::isLocType(castTy));
- return val;
- }
+ if (OriginalTy->isIntegralOrEnumerationType() ||
+ OriginalTy->isBlockPointerType() || OriginalTy->isFunctionPointerType())
+ return V;
- // Check for casts from array type to another type.
- if (const auto *arrayT =
- dyn_cast<ArrayType>(originalTy.getCanonicalType())) {
- // We will always decay to a pointer.
- QualType elemTy = arrayT->getElementType();
- val = StateMgr.ArrayToPointer(val.castAs<Loc>(), elemTy);
-
- // Are we casting from an array to a pointer? If so just pass on
- // the decayed value.
- if (castTy->isPointerType() || castTy->isReferenceType())
- return val;
-
- // Are we casting from an array to an integer? If so, cast the decayed
- // pointer value to an integer.
- assert(castTy->isIntegralOrEnumerationType());
-
- // FIXME: Keep these here for now in case we decide soon that we
- // need the original decayed type.
- // QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
- // QualType pointerTy = C.getPointerType(elemTy);
- return evalCastFromLoc(val.castAs<Loc>(), castTy);
- }
-
- // Check for casts from a region to a specific type.
- if (const MemRegion *R = val.getAsRegion()) {
- // Handle other casts of locations to integers.
- if (castTy->isIntegralOrEnumerationType())
- return evalCastFromLoc(loc::MemRegionVal(R), castTy);
-
- // FIXME: We should handle the case where we strip off view layers to get
- // to a desugared type.
- if (!Loc::isLocType(castTy)) {
- // FIXME: There can be gross cases where one casts the result of a function
- // (that returns a pointer) to some other value that happens to fit
- // within that pointer value. We currently have no good way to
- // model such operations. When this happens, the underlying operation
- // is that the caller is reasoning about bits. Conceptually we are
- // layering a "view" of a location on top of those bits. Perhaps
- // we need to be more lazy about mutual possible views, even on an
- // SVal? This may be necessary for bit-level reasoning as well.
- return UnknownVal();
+ // Array to pointer.
+ if (ArrayTy) {
+ // Are we casting from an array to a pointer? If so just pass on
+ // the decayed value.
+ if (CastTy->isPointerType() || CastTy->isReferenceType()) {
+ // We will always decay to a pointer.
+ QualType ElemTy = ArrayTy->getElementType();
+ return StateMgr.ArrayToPointer(V, ElemTy);
+ }
+ // Are we casting from an array to an integer? If so, cast the decayed
+ // pointer value to an integer.
+ assert(CastTy->isIntegralOrEnumerationType());
}
+ // Other pointer to pointer.
+ assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
+ CastTy->isReferenceType());
+
// We get a symbolic function pointer for a dereference of a function
// pointer, but it is of function type. Example:
@@ -647,17 +833,161 @@
// return bar(x)+1; // no-warning
// }
- assert(Loc::isLocType(originalTy) || originalTy->isFunctionType() ||
- originalTy->isBlockPointerType() || castTy->isReferenceType());
-
- StoreManager &storeMgr = StateMgr.getStoreManager();
-
- // Delegate to store manager to get the result of casting a region to a
- // different type. If the MemRegion* returned is NULL, this expression
- // Evaluates to UnknownVal.
- R = storeMgr.castRegion(R, castTy);
- return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
+ // Get the result of casting a region to a different type.
+ const MemRegion *R = V.getRegion();
+ if (auto OptMemRegV = getCastedMemRegionVal(R, CastTy))
+ return *OptMemRegV;
}
- return dispatchCast(val, castTy);
+ // Pointer to whatever else.
+ // FIXME: There can be gross cases where one casts the result of a
+ // function (that returns a pointer) to some other value that happens to
+ // fit within that pointer value. We currently have no good way to model
+ // such operations. When this happens, the underlying operation is that
+ // the caller is reasoning about bits. Conceptually we are layering a
+ // "view" of a location on top of those bits. Perhaps we need to be more
+ // lazy about mutual possible views, even on an SVal? This may be
+ // necessary for bit-level reasoning as well.
+ return UnknownVal();
+}
+
+SVal SValBuilder::evalCastSubKind(nonloc::CompoundVal V, QualType CastTy,
+ QualType OriginalTy) {
+ // Compound to whatever.
+ return UnknownVal();
+}
+
+SVal SValBuilder::evalCastSubKind(nonloc::ConcreteInt V, QualType CastTy,
+ QualType OriginalTy) {
+ auto CastedValue = [V, CastTy, this]() {
+ llvm::APSInt Value = V.getValue();
+ BasicVals.getAPSIntType(CastTy).apply(Value);
+ return Value;
+ };
+
+ // Integer to bool.
+ if (CastTy->isBooleanType())
+ return makeTruthVal(V.getValue().getBoolValue(), CastTy);
+
+ // Integer to pointer.
+ if (CastTy->isIntegralOrEnumerationType())
+ return makeIntVal(CastedValue());
+
+ // Integer to pointer.
+ if (Loc::isLocType(CastTy))
+ return makeIntLocVal(CastedValue());
+
+ // Pointer to whatever else.
+ return UnknownVal();
+}
+
+SVal SValBuilder::evalCastSubKind(nonloc::LazyCompoundVal V, QualType CastTy,
+ QualType OriginalTy) {
+ // Compound to whatever.
+ return UnknownVal();
+}
+
+SVal SValBuilder::evalCastSubKind(nonloc::LocAsInteger V, QualType CastTy,
+ QualType OriginalTy) {
+ Loc L = V.getLoc();
+
+ // Pointer as integer to bool.
+ if (CastTy->isBooleanType())
+ // Pass to Loc function.
+ return evalCastKind(L, CastTy, OriginalTy);
+
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ // Pointer as integer to pointer.
+ if (!IsUnknownOriginalType && Loc::isLocType(CastTy) &&
+ OriginalTy->isIntegralOrEnumerationType()) {
+ if (const MemRegion *R = L.getAsRegion())
+ if (auto OptMemRegV = getCastedMemRegionVal(R, CastTy))
+ return *OptMemRegV;
+ return L;
+ }
+
+ // Pointer as integer with region to integer/pointer.
+ const MemRegion *R = L.getAsRegion();
+ if (!IsUnknownOriginalType && R) {
+ if (CastTy->isIntegralOrEnumerationType())
+ return evalCastSubKind(loc::MemRegionVal(R), CastTy, OriginalTy);
+
+ if (Loc::isLocType(CastTy)) {
+ assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
+ CastTy->isReferenceType());
+ // Delegate to store manager to get the result of casting a region to a
+ // different type. If the MemRegion* returned is NULL, this expression
+ // Evaluates to UnknownVal.
+ if (auto OptMemRegV = getCastedMemRegionVal(R, CastTy))
+ return *OptMemRegV;
+ }
+ } else {
+ if (Loc::isLocType(CastTy)) {
+ if (IsUnknownOriginalType)
+ return evalCastSubKind(loc::MemRegionVal(R), CastTy, OriginalTy);
+ return L;
+ }
+
+ SymbolRef SE = nullptr;
+ if (R) {
+ if (const SymbolicRegion *SR =
+ dyn_cast<SymbolicRegion>(R->StripCasts())) {
+ SE = SR->getSymbol();
+ }
+ }
+
+ if (!CastTy->isFloatingType() || !SE || SE->getType()->isFloatingType()) {
+ // FIXME: Correctly support promotions/truncations.
+ const unsigned CastSize = Context.getIntWidth(CastTy);
+ if (CastSize == V.getNumBits())
+ return V;
+
+ return makeLocAsInteger(L, CastSize);
+ }
+ }
+
+ // Pointer as integer to whatever else.
+ return UnknownVal();
+}
+
+SVal SValBuilder::evalCastSubKind(nonloc::SymbolVal V, QualType CastTy,
+ QualType OriginalTy) {
+ SymbolRef SE = V.getSymbol();
+
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ // Symbol to bool.
+ if (!IsUnknownOriginalType && CastTy->isBooleanType()) {
+ // Non-float to bool.
+ if (Loc::isLocType(OriginalTy) ||
+ OriginalTy->isIntegralOrEnumerationType() ||
+ OriginalTy->isMemberPointerType()) {
+ BasicValueFactory &BVF = getBasicValueFactory();
+ return makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy);
+ }
+ } else {
+ // Symbol to integer, float.
+ QualType T = Context.getCanonicalType(SE->getType());
+ // If types are the same or both are integers, ignore the cast.
+ // FIXME: Remove this hack when we support symbolic truncation/extension.
+ // HACK: If both castTy and T are integers, ignore the cast. This is
+ // not a permanent solution. Eventually we want to precisely handle
+ // extension/truncation of symbolic integers. This prevents us from losing
+ // precision when we assign 'x = y' and 'y' is symbolic and x and y are
+ // different integer types.
+ if (haveSameType(T, CastTy))
+ return V;
+ if (!Loc::isLocType(CastTy))
+ if (!IsUnknownOriginalType || !CastTy->isFloatingType() ||
+ T->isFloatingType())
+ return makeNonLoc(SE, T, CastTy);
+ }
+
+ // Symbol to pointer and whatever else.
+ return UnknownVal();
+}
+
+SVal SValBuilder::evalCastSubKind(nonloc::PointerToMember V, QualType CastTy,
+ QualType OriginalTy) {
+ // Member pointer to whatever.
+ return V;
}
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp
index 2525968..117546e 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
@@ -21,6 +22,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/Optional.h"
@@ -136,6 +138,63 @@
return nullptr;
}
+namespace {
+class TypeRetrievingVisitor
+ : public FullSValVisitor<TypeRetrievingVisitor, QualType> {
+private:
+ const ASTContext &Context;
+
+public:
+ TypeRetrievingVisitor(const ASTContext &Context) : Context(Context) {}
+
+ QualType VisitLocMemRegionVal(loc::MemRegionVal MRV) {
+ return Visit(MRV.getRegion());
+ }
+ QualType VisitLocGotoLabel(loc::GotoLabel GL) {
+ return QualType{Context.VoidPtrTy};
+ }
+ template <class ConcreteInt> QualType VisitConcreteInt(ConcreteInt CI) {
+ const llvm::APSInt &Value = CI.getValue();
+ return Context.getIntTypeForBitwidth(Value.getBitWidth(), Value.isSigned());
+ }
+ QualType VisitLocConcreteInt(loc::ConcreteInt CI) {
+ return VisitConcreteInt(CI);
+ }
+ QualType VisitNonLocConcreteInt(nonloc::ConcreteInt CI) {
+ return VisitConcreteInt(CI);
+ }
+ QualType VisitNonLocLocAsInteger(nonloc::LocAsInteger LI) {
+ QualType NestedType = Visit(LI.getLoc());
+ if (NestedType.isNull())
+ return NestedType;
+
+ return Context.getIntTypeForBitwidth(LI.getNumBits(),
+ NestedType->isSignedIntegerType());
+ }
+ QualType VisitNonLocCompoundVal(nonloc::CompoundVal CV) {
+ return CV.getValue()->getType();
+ }
+ QualType VisitNonLocLazyCompoundVal(nonloc::LazyCompoundVal LCV) {
+ return LCV.getRegion()->getValueType();
+ }
+ QualType VisitNonLocSymbolVal(nonloc::SymbolVal SV) {
+ return Visit(SV.getSymbol());
+ }
+ QualType VisitSymbolicRegion(const SymbolicRegion *SR) {
+ return Visit(SR->getSymbol());
+ }
+ QualType VisitTypedRegion(const TypedRegion *TR) {
+ return TR->getLocationType();
+ }
+ QualType VisitSymExpr(const SymExpr *SE) { return SE->getType(); }
+};
+} // end anonymous namespace
+
+QualType SVal::getType(const ASTContext &Context) const {
+ TypeRetrievingVisitor TRV{Context};
+ return TRV.Visit(*this);
+}
+
const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
const MemRegion *R = getRegion();
return R ? R->StripCasts(StripBaseCasts) : nullptr;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
index f93d04c..e1319a4 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Analysis/MacroExpansionContext.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Version.h"
@@ -48,7 +49,8 @@
void ento::createSarifDiagnosticConsumer(
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
const std::string &Output, const Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions) {
// TODO: Emit an error here.
if (Output.empty())
@@ -56,7 +58,7 @@
C.push_back(new SarifDiagnostics(Output, PP.getLangOpts()));
createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP,
- CTU);
+ CTU, MacroExpansions);
}
static StringRef getFileName(const FileEntry &FE) {
@@ -385,7 +387,7 @@
// file can become large very quickly, so decoding into JSON to append a run
// may be an expensive operation.
std::error_code EC;
- llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_Text);
+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
if (EC) {
llvm::errs() << "warning: could not create file: " << EC.message() << '\n';
return;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index facadaf..e57d92f 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -22,11 +22,6 @@
namespace {
class SimpleSValBuilder : public SValBuilder {
-protected:
- SVal dispatchCast(SVal val, QualType castTy) override;
- SVal evalCastFromNonLoc(NonLoc val, QualType castTy) override;
- SVal evalCastFromLoc(Loc val, QualType castTy) override;
-
public:
SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
ProgramStateManager &stateMgr)
@@ -62,133 +57,6 @@
}
//===----------------------------------------------------------------------===//
-// Transfer function for Casts.
-//===----------------------------------------------------------------------===//
-
-SVal SimpleSValBuilder::dispatchCast(SVal Val, QualType CastTy) {
- assert(Val.getAs<Loc>() || Val.getAs<NonLoc>());
- return Val.getAs<Loc>() ? evalCastFromLoc(Val.castAs<Loc>(), CastTy)
- : evalCastFromNonLoc(Val.castAs<NonLoc>(), CastTy);
-}
-
-SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
- bool isLocType = Loc::isLocType(castTy);
- if (val.getAs<nonloc::PointerToMember>())
- return val;
-
- if (Optional<nonloc::LocAsInteger> LI = val.getAs<nonloc::LocAsInteger>()) {
- if (isLocType)
- return LI->getLoc();
- // FIXME: Correctly support promotions/truncations.
- unsigned castSize = Context.getIntWidth(castTy);
- if (castSize == LI->getNumBits())
- return val;
- return makeLocAsInteger(LI->getLoc(), castSize);
- }
-
- if (SymbolRef se = val.getAsSymbol()) {
- QualType T = Context.getCanonicalType(se->getType());
- // If types are the same or both are integers, ignore the cast.
- // FIXME: Remove this hack when we support symbolic truncation/extension.
- // HACK: If both castTy and T are integers, ignore the cast. This is
- // not a permanent solution. Eventually we want to precisely handle
- // extension/truncation of symbolic integers. This prevents us from losing
- // precision when we assign 'x = y' and 'y' is symbolic and x and y are
- // different integer types.
- if (haveSameType(T, castTy))
- return val;
-
- if (!isLocType)
- return makeNonLoc(se, T, castTy);
- return UnknownVal();
- }
-
- // If value is a non-integer constant, produce unknown.
- if (!val.getAs<nonloc::ConcreteInt>())
- return UnknownVal();
-
- // Handle casts to a boolean type.
- if (castTy->isBooleanType()) {
- bool b = val.castAs<nonloc::ConcreteInt>().getValue().getBoolValue();
- return makeTruthVal(b, castTy);
- }
-
- // Only handle casts from integers to integers - if val is an integer constant
- // being cast to a non-integer type, produce unknown.
- if (!isLocType && !castTy->isIntegralOrEnumerationType())
- return UnknownVal();
-
- llvm::APSInt i = val.castAs<nonloc::ConcreteInt>().getValue();
- BasicVals.getAPSIntType(castTy).apply(i);
-
- if (isLocType)
- return makeIntLocVal(i);
- else
- return makeIntVal(i);
-}
-
-SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) {
-
- // Casts from pointers -> pointers, just return the lval.
- //
- // Casts from pointers -> references, just return the lval. These
- // can be introduced by the frontend for corner cases, e.g
- // casting from va_list* to __builtin_va_list&.
- //
- if (Loc::isLocType(castTy) || castTy->isReferenceType())
- return val;
-
- // FIXME: Handle transparent unions where a value can be "transparently"
- // lifted into a union type.
- if (castTy->isUnionType())
- return UnknownVal();
-
- // Casting a Loc to a bool will almost always be true,
- // unless this is a weak function or a symbolic region.
- if (castTy->isBooleanType()) {
- switch (val.getSubKind()) {
- case loc::MemRegionValKind: {
- const MemRegion *R = val.castAs<loc::MemRegionVal>().getRegion();
- if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R))
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
- if (FD->isWeak())
- // FIXME: Currently we are using an extent symbol here,
- // because there are no generic region address metadata
- // symbols to use, only content metadata.
- return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR));
-
- if (const SymbolicRegion *SymR = R->getSymbolicBase())
- return makeNonLoc(SymR->getSymbol(), BO_NE,
- BasicVals.getZeroWithPtrWidth(), castTy);
-
- // FALL-THROUGH
- LLVM_FALLTHROUGH;
- }
-
- case loc::GotoLabelKind:
- // Labels and non-symbolic memory regions are always true.
- return makeTruthVal(true, castTy);
- }
- }
-
- if (castTy->isIntegralOrEnumerationType()) {
- unsigned BitWidth = Context.getIntWidth(castTy);
-
- if (!val.getAs<loc::ConcreteInt>())
- return makeLocAsInteger(val, BitWidth);
-
- llvm::APSInt i = val.castAs<loc::ConcreteInt>().getValue();
- BasicVals.getAPSIntType(castTy).apply(i);
- return makeIntVal(i);
- }
-
- // All other cases: return 'UnknownVal'. This includes casting pointers
- // to floats, which is probably badness it itself, but this is a good
- // intermediate solution until we do something better.
- return UnknownVal();
-}
-
-//===----------------------------------------------------------------------===//
// Transfer function for unary operators.
//===----------------------------------------------------------------------===//
@@ -276,10 +144,10 @@
}
// Idempotent ops (like a*1) can still change the type of an expression.
- // Wrap the LHS up in a NonLoc again and let evalCastFromNonLoc do the
+ // Wrap the LHS up in a NonLoc again and let evalCast do the
// dirty work.
if (isIdempotent)
- return evalCastFromNonLoc(nonloc::SymbolVal(LHS), resultTy);
+ return evalCast(nonloc::SymbolVal(LHS), resultTy, QualType{});
// If we reach this point, the expression cannot be simplified.
// Make a SymbolVal for the entire expression, after converting the RHS.
@@ -525,10 +393,11 @@
case BO_Sub:
if (resultTy->isIntegralOrEnumerationType())
return makeIntVal(0, resultTy);
- return evalCastFromNonLoc(makeIntVal(0, /*isUnsigned=*/false), resultTy);
+ return evalCast(makeIntVal(0, /*isUnsigned=*/false), resultTy,
+ QualType{});
case BO_Or:
case BO_And:
- return evalCastFromNonLoc(lhs, resultTy);
+ return evalCast(lhs, resultTy, QualType{});
}
while (1) {
@@ -645,13 +514,15 @@
case BO_Shr:
// (~0)>>a
if (LHSValue.isAllOnesValue() && LHSValue.isSigned())
- return evalCastFromNonLoc(lhs, resultTy);
+ return evalCast(lhs, resultTy, QualType{});
LLVM_FALLTHROUGH;
case BO_Shl:
// 0<<a and 0>>a
if (LHSValue == 0)
- return evalCastFromNonLoc(lhs, resultTy);
+ return evalCast(lhs, resultTy, QualType{});
return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
+ case BO_Div:
+ // 0 / x == 0
case BO_Rem:
// 0 % x == 0
if (LHSValue == 0)
@@ -865,7 +736,7 @@
default:
break;
case BO_Sub:
- return evalCastFromLoc(lhs, resultTy);
+ return evalCast(lhs, resultTy, QualType{});
case BO_EQ:
case BO_LE:
case BO_LT:
@@ -902,7 +773,7 @@
SVal ResultVal =
lhs.castAs<loc::ConcreteInt>().evalBinOp(BasicVals, op, *rInt);
if (Optional<NonLoc> Result = ResultVal.getAs<NonLoc>())
- return evalCastFromNonLoc(*Result, resultTy);
+ return evalCast(*Result, resultTy, QualType{});
assert(!ResultVal.getAs<Loc>() && "Loc-Loc ops should not produce Locs");
return UnknownVal();
@@ -947,11 +818,11 @@
// to be non-NULL.
if (rInt->isZeroConstant()) {
if (op == BO_Sub)
- return evalCastFromLoc(lhs, resultTy);
+ return evalCast(lhs, resultTy, QualType{});
if (BinaryOperator::isComparisonOp(op)) {
QualType boolType = getContext().BoolTy;
- NonLoc l = evalCastFromLoc(lhs, boolType).castAs<NonLoc>();
+ NonLoc l = evalCast(lhs, boolType, QualType{}).castAs<NonLoc>();
NonLoc r = makeTruthVal(false, boolType).castAs<NonLoc>();
return evalBinOpNN(state, op, l, r, resultTy);
}
@@ -1033,7 +904,7 @@
Optional<NonLoc> LeftIndex = LeftIndexVal.getAs<NonLoc>();
if (!LeftIndex)
return UnknownVal();
- LeftIndexVal = evalCastFromNonLoc(*LeftIndex, ArrayIndexTy);
+ LeftIndexVal = evalCast(*LeftIndex, ArrayIndexTy, QualType{});
LeftIndex = LeftIndexVal.getAs<NonLoc>();
if (!LeftIndex)
return UnknownVal();
@@ -1043,7 +914,7 @@
Optional<NonLoc> RightIndex = RightIndexVal.getAs<NonLoc>();
if (!RightIndex)
return UnknownVal();
- RightIndexVal = evalCastFromNonLoc(*RightIndex, ArrayIndexTy);
+ RightIndexVal = evalCast(*RightIndex, ArrayIndexTy, QualType{});
RightIndex = RightIndexVal.getAs<NonLoc>();
if (!RightIndex)
return UnknownVal();
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/Store.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/Store.cpp
index ea617bb..b867b07 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/Store.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -71,7 +71,8 @@
return MRMgr.getElementRegion(T, idx, R, Ctx);
}
-const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) {
+Optional<const MemRegion *> StoreManager::castRegion(const MemRegion *R,
+ QualType CastToTy) {
ASTContext &Ctx = StateMgr.getContext();
// Handle casts to Objective-C objects.
@@ -88,7 +89,7 @@
// We don't know what to make of it. Return a NULL region, which
// will be interpreted as UnknownVal.
- return nullptr;
+ return None;
}
// Now assume we are casting from pointer to pointer. Other cases should
@@ -168,7 +169,7 @@
// If we cannot compute a raw offset, throw up our hands and return
// a NULL MemRegion*.
if (!baseR)
- return nullptr;
+ return None;
CharUnits off = rawOff.getOffset();
@@ -394,48 +395,6 @@
return UnknownVal();
}
-static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) {
- return ty1->getPointeeType().getCanonicalType().getTypePtr() ==
- ty2->getPointeeType().getCanonicalType().getTypePtr();
-}
-
-/// CastRetrievedVal - Used by subclasses of StoreManager to implement
-/// implicit casts that arise from loads from regions that are reinterpreted
-/// as another region.
-SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
- QualType castTy) {
- if (castTy.isNull() || V.isUnknownOrUndef())
- return V;
-
- // The dispatchCast() call below would convert the int into a float.
- // What we want, however, is a bit-by-bit reinterpretation of the int
- // as a float, which usually yields nothing garbage. For now skip casts
- // from ints to floats.
- // TODO: What other combinations of types are affected?
- if (castTy->isFloatingType()) {
- SymbolRef Sym = V.getAsSymbol();
- if (Sym && !Sym->getType()->isFloatingType())
- return UnknownVal();
- }
-
- // When retrieving symbolic pointer and expecting a non-void pointer,
- // wrap them into element regions of the expected type if necessary.
- // SValBuilder::dispatchCast() doesn't do that, but it is necessary to
- // make sure that the retrieved value makes sense, because there's no other
- // cast in the AST that would tell us to cast it to the correct pointer type.
- // We might need to do that for non-void pointers as well.
- // FIXME: We really need a single good function to perform casts for us
- // correctly every time we need it.
- if (castTy->isPointerType() && !castTy->isVoidPointerType())
- if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) {
- QualType sr = SR->getSymbol()->getType();
- if (!hasSameUnqualifiedPointeeType(sr, castTy))
- return loc::MemRegionVal(castRegion(SR, castTy));
- }
-
- return svalBuilder.dispatchCast(V, castTy);
-}
-
SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) {
if (Base.isUnknownOrUndef())
return Base;
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp
index ae2bad7..4f3be7c 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Analysis/MacroExpansionContext.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
@@ -138,8 +139,9 @@
void ento::createTextPathDiagnosticConsumer(
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
- const std::string &Prefix, const clang::Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
+ const std::string &Prefix, const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions) {
C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),
PP.getLangOpts(),
/*ShouldDisplayPathNotes=*/true));
@@ -147,8 +149,9 @@
void ento::createTextMinimalPathDiagnosticConsumer(
PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
- const std::string &Prefix, const clang::Preprocessor &PP,
- const cross_tu::CrossTranslationUnitContext &CTU) {
+ const std::string &Prefix, const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU,
+ const MacroExpansionContext &MacroExpansions) {
C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),
PP.getLangOpts(),
/*ShouldDisplayPathNotes=*/false));
diff --git a/src/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/src/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index f2a19b2..31de490 100644
--- a/src/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/src/llvm-project/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -20,6 +20,7 @@
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/Analysis/CodeInjector.h"
+#include "clang/Analysis/MacroExpansionContext.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/CrossTU/CrossTranslationUnit.h"
@@ -98,6 +99,8 @@
/// working with a PCH file.
SetOfDecls LocalTUDecls;
+ MacroExpansionContext MacroExpansions;
+
// Set of PathDiagnosticConsumers. Owned by AnalysisManager.
PathDiagnosticConsumers PathConsumers;
@@ -122,9 +125,11 @@
CodeInjector *injector)
: RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr),
PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
- Plugins(plugins), Injector(injector), CTU(CI) {
+ Plugins(plugins), Injector(injector), CTU(CI),
+ MacroExpansions(CI.getLangOpts()) {
DigestAnalyzerOptions();
- if (Opts->PrintStats || Opts->ShouldSerializeStats) {
+ if (Opts->AnalyzerDisplayProgress || Opts->PrintStats ||
+ Opts->ShouldSerializeStats) {
AnalyzerTimers = std::make_unique<llvm::TimerGroup>(
"analyzer", "Analyzer timers");
SyntaxCheckTimer = std::make_unique<llvm::Timer>(
@@ -134,8 +139,14 @@
BugReporterTimer = std::make_unique<llvm::Timer>(
"bugreporter", "Path-sensitive report post-processing time",
*AnalyzerTimers);
+ }
+
+ if (Opts->PrintStats || Opts->ShouldSerializeStats) {
llvm::EnableStatistics(/* PrintOnExit= */ false);
}
+
+ if (Opts->ShouldDisplayMacroExpansions)
+ MacroExpansions.registerForPreprocessor(PP);
}
~AnalysisConsumer() override {
@@ -150,7 +161,8 @@
break;
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \
case PD_##NAME: \
- CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU); \
+ CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU, \
+ MacroExpansions); \
break;
#include "clang/StaticAnalyzer/Core/Analyses.def"
default:
@@ -175,6 +187,14 @@
}
}
+ void DisplayTime(llvm::TimeRecord &Time) {
+ if (!Opts->AnalyzerDisplayProgress) {
+ return;
+ }
+ llvm::errs() << " : " << llvm::format("%1.1f", Time.getWallTime() * 1000)
+ << " ms\n";
+ }
+
void DisplayFunction(const Decl *D, AnalysisMode Mode,
ExprEngine::InliningModes IMode) {
if (!Opts->AnalyzerDisplayProgress)
@@ -201,8 +221,8 @@
} else
assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");
- llvm::errs() << ": " << Loc.getFilename() << ' ' << getFunctionName(D)
- << '\n';
+ llvm::errs() << ": " << Loc.getFilename() << ' '
+ << AnalysisDeclContext::getFunctionName(D);
}
}
@@ -560,63 +580,10 @@
Mgr.reset();
}
-std::string AnalysisConsumer::getFunctionName(const Decl *D) {
- std::string Str;
- llvm::raw_string_ostream OS(Str);
-
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- OS << FD->getQualifiedNameAsString();
-
- // In C++, there are overloads.
- if (Ctx->getLangOpts().CPlusPlus) {
- OS << '(';
- for (const auto &P : FD->parameters()) {
- if (P != *FD->param_begin())
- OS << ", ";
- OS << P->getType().getAsString();
- }
- OS << ')';
- }
-
- } else if (isa<BlockDecl>(D)) {
- PresumedLoc Loc = Ctx->getSourceManager().getPresumedLoc(D->getLocation());
-
- if (Loc.isValid()) {
- OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
- << ')';
- }
-
- } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
-
- // FIXME: copy-pasted from CGDebugInfo.cpp.
- OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
- const DeclContext *DC = OMD->getDeclContext();
- if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
- OS << OID->getName();
- } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
- OS << OID->getName();
- } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
- if (OC->IsClassExtension()) {
- OS << OC->getClassInterface()->getName();
- } else {
- OS << OC->getIdentifier()->getNameStart() << '('
- << OC->getIdentifier()->getNameStart() << ')';
- }
- } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
- OS << OCD->getClassInterface()->getName() << '('
- << OCD->getName() << ')';
- }
- OS << ' ' << OMD->getSelector().getAsString() << ']';
-
- }
-
- return OS.str();
-}
-
AnalysisConsumer::AnalysisMode
AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) {
if (!Opts->AnalyzeSpecificFunction.empty() &&
- getFunctionName(D) != Opts->AnalyzeSpecificFunction)
+ AnalysisDeclContext::getFunctionName(D) != Opts->AnalyzeSpecificFunction)
return AM_None;
// Unless -analyze-all is specified, treat decls differently depending on
@@ -653,19 +620,26 @@
if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized())
return;
- DisplayFunction(D, Mode, IMode);
CFG *DeclCFG = Mgr->getCFG(D);
if (DeclCFG)
MaxCFGSize.updateMax(DeclCFG->size());
+ DisplayFunction(D, Mode, IMode);
BugReporter BR(*Mgr);
if (Mode & AM_Syntax) {
- if (SyntaxCheckTimer)
+ llvm::TimeRecord CheckerStartTime;
+ if (SyntaxCheckTimer) {
+ CheckerStartTime = SyntaxCheckTimer->getTotalTime();
SyntaxCheckTimer->startTimer();
+ }
checkerMgr->runCheckersOnASTBody(D, *Mgr, BR);
- if (SyntaxCheckTimer)
+ if (SyntaxCheckTimer) {
SyntaxCheckTimer->stopTimer();
+ llvm::TimeRecord CheckerEndTime = SyntaxCheckTimer->getTotalTime();
+ CheckerEndTime -= CheckerStartTime;
+ DisplayTime(CheckerEndTime);
+ }
}
BR.FlushReports();
@@ -696,12 +670,19 @@
ExprEngine Eng(CTU, *Mgr, VisitedCallees, &FunctionSummaries, IMode);
// Execute the worklist algorithm.
- if (ExprEngineTimer)
+ llvm::TimeRecord ExprEngineStartTime;
+ if (ExprEngineTimer) {
+ ExprEngineStartTime = ExprEngineTimer->getTotalTime();
ExprEngineTimer->startTimer();
+ }
Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
Mgr->options.MaxNodesPerTopLevelFunction);
- if (ExprEngineTimer)
+ if (ExprEngineTimer) {
ExprEngineTimer->stopTimer();
+ llvm::TimeRecord ExprEngineEndTime = ExprEngineTimer->getTotalTime();
+ ExprEngineEndTime -= ExprEngineStartTime;
+ DisplayTime(ExprEngineEndTime);
+ }
if (!Mgr->options.DumpExplodedGraphTo.empty())
Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
diff --git a/src/llvm-project/clang/lib/Tooling/ArgumentsAdjusters.cpp b/src/llvm-project/clang/lib/Tooling/ArgumentsAdjusters.cpp
index bcfb5b3..7f5dc4d 100644
--- a/src/llvm-project/clang/lib/Tooling/ArgumentsAdjusters.cpp
+++ b/src/llvm-project/clang/lib/Tooling/ArgumentsAdjusters.cpp
@@ -62,7 +62,8 @@
HasSyntaxOnly = true;
}
if (!HasSyntaxOnly)
- AdjustedArgs.push_back("-fsyntax-only");
+ AdjustedArgs =
+ getInsertArgumentAdjuster("-fsyntax-only")(AdjustedArgs, "");
return AdjustedArgs;
};
}
@@ -85,22 +86,6 @@
};
}
-ArgumentsAdjuster getClangStripSerializeDiagnosticAdjuster() {
- return [](const CommandLineArguments &Args, StringRef /*unused*/) {
- CommandLineArguments AdjustedArgs;
- for (size_t i = 0, e = Args.size(); i < e; ++i) {
- StringRef Arg = Args[i];
- if (Arg == "--serialize-diagnostics") {
- // Skip the diagnostic output argument.
- ++i;
- continue;
- }
- AdjustedArgs.push_back(Args[i]);
- }
- return AdjustedArgs;
- };
-}
-
ArgumentsAdjuster getClangStripDependencyFileAdjuster() {
return [](const CommandLineArguments &Args, StringRef /*unused*/) {
auto UsingClDriver = (getDriverMode(Args) == "cl");
@@ -137,7 +122,7 @@
CommandLineArguments::iterator I;
if (Pos == ArgumentInsertPosition::END) {
- I = Return.end();
+ I = std::find(Return.begin(), Return.end(), "--");
} else {
I = Return.begin();
++I; // To leave the program name in place
diff --git a/src/llvm-project/clang/lib/Tooling/CMakeLists.txt b/src/llvm-project/clang/lib/Tooling/CMakeLists.txt
index 7a58af5..558385b 100644
--- a/src/llvm-project/clang/lib/Tooling/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/Tooling/CMakeLists.txt
@@ -8,10 +8,96 @@
add_subdirectory(Inclusions)
add_subdirectory(Refactoring)
add_subdirectory(ASTDiff)
+add_subdirectory(DumpTool)
add_subdirectory(Syntax)
add_subdirectory(DependencyScanning)
add_subdirectory(Transformer)
+# Replace the last lib component of the current binary directory with include
+string(FIND ${CMAKE_CURRENT_BINARY_DIR} "/lib/" PATH_LIB_START REVERSE)
+if(PATH_LIB_START EQUAL -1)
+ message(FATAL_ERROR "Couldn't find lib component in binary directory")
+endif()
+math(EXPR PATH_LIB_END "${PATH_LIB_START}+5")
+string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD)
+string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} ${PATH_LIB_END} -1 PATH_TAIL)
+string(CONCAT BINARY_INCLUDE_DIR ${PATH_HEAD} "/include/clang/" ${PATH_TAIL})
+
+if (NOT Python3_EXECUTABLE
+ OR APPLE
+ OR CMAKE_CROSSCOMPILING
+ OR GENERATOR_IS_MULTI_CONFIG
+ OR NOT LLVM_NATIVE_ARCH IN_LIST LLVM_TARGETS_TO_BUILD
+ )
+ configure_file(
+ EmptyNodeIntrospection.inc.in
+ ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
+ COPYONLY
+ )
+ set(CLANG_TOOLING_BUILD_AST_INTROSPECTION "OFF" CACHE BOOL "")
+else()
+ # The generation of ASTNodeAPI.json takes a long time in a
+ # Debug build due to parsing AST.h. Disable the processing
+ # but setting CLANG_TOOLING_BUILD_AST_INTROSPECTION as an
+ # internal hidden setting to override.
+ # When the processing is disabled, a trivial/empty JSON
+ # file is generated by clang-ast-dump and generate_cxx_src_locs.py
+ # generates the same API, but with a trivial implementation.
+ option(CLANG_TOOLING_BUILD_AST_INTROSPECTION "Enable AST introspection" TRUE)
+
+ set(skip_expensive_processing $<OR:$<CONFIG:Debug>,$<NOT:$<BOOL:${CLANG_TOOLING_BUILD_AST_INTROSPECTION}>>>)
+
+ set(implicitDirs)
+ foreach(implicitDir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
+ list(APPEND implicitDirs -I ${implicitDir})
+ endforeach()
+
+ add_custom_command(
+ COMMENT Generate ASTNodeAPI.json
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
+ DEPENDS clang-ast-dump clang-resource-headers
+ COMMAND
+ $<TARGET_FILE:clang-ast-dump>
+ # Skip this in debug mode because parsing AST.h is too slow
+ --skip-processing=${skip_expensive_processing}
+ -I ${CMAKE_BINARY_DIR}/lib/clang/${CLANG_VERSION}/include
+ -I ${CMAKE_SOURCE_DIR}/../clang/include
+ -I ${CMAKE_BINARY_DIR}/tools/clang/include
+ -I ${CMAKE_BINARY_DIR}/include
+ -I ${CMAKE_SOURCE_DIR}/include
+ ${implicitDirs}
+ --json-output-path ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
+ )
+
+ add_custom_target(run-ast-api-dump-tool
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
+ )
+
+ add_custom_command(
+ COMMENT Generate NodeIntrospection.inc
+ OUTPUT ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
+ ${CMAKE_CURRENT_SOURCE_DIR}/DumpTool/generate_cxx_src_locs.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/EmptyNodeIntrospection.inc.in
+ COMMAND
+ ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/DumpTool/generate_cxx_src_locs.py
+ --json-input-path ${CMAKE_CURRENT_BINARY_DIR}/ASTNodeAPI.json
+ --output-file NodeIntrospection.inc
+ --use-empty-implementation ${skip_expensive_processing}
+ --empty-implementation
+ "${CMAKE_CURRENT_SOURCE_DIR}/EmptyNodeIntrospection.inc.in"
+ COMMAND
+ ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_CURRENT_BINARY_DIR}/NodeIntrospection.inc
+ ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
+ )
+
+ add_custom_target(run-ast-api-generate-tool
+ DEPENDS
+ ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
+ )
+endif()
+
add_clang_library(clangTooling
AllTUsExecution.cpp
ArgumentsAdjusters.cpp
@@ -27,6 +113,8 @@
Refactoring.cpp
RefactoringCallbacks.cpp
StandaloneExecution.cpp
+ NodeIntrospection.cpp
+ ${BINARY_INCLUDE_DIR}/NodeIntrospection.inc
Tooling.cpp
DEPENDS
diff --git a/src/llvm-project/clang/lib/Tooling/CommonOptionsParser.cpp b/src/llvm-project/clang/lib/Tooling/CommonOptionsParser.cpp
index 5d881aa..6301544 100644
--- a/src/llvm-project/clang/lib/Tooling/CommonOptionsParser.cpp
+++ b/src/llvm-project/clang/lib/Tooling/CommonOptionsParser.cpp
@@ -115,8 +115,7 @@
// Stop initializing if command-line option parsing failed.
if (!cl::ParseCommandLineOptions(argc, argv, Overview, &OS)) {
OS.flush();
- return llvm::make_error<llvm::StringError>("[CommonOptionsParser]: " +
- ErrorMessage,
+ return llvm::make_error<llvm::StringError>(ErrorMessage,
llvm::inconvertibleErrorCode());
}
diff --git a/src/llvm-project/clang/lib/Tooling/Core/Diagnostic.cpp b/src/llvm-project/clang/lib/Tooling/Core/Diagnostic.cpp
index b0c4ea8..fb33580 100644
--- a/src/llvm-project/clang/lib/Tooling/Core/Diagnostic.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Core/Diagnostic.cpp
@@ -53,10 +53,9 @@
Diagnostic::Diagnostic(llvm::StringRef DiagnosticName,
const DiagnosticMessage &Message,
const SmallVector<DiagnosticMessage, 1> &Notes,
- Level DiagLevel, llvm::StringRef BuildDirectory,
- const SmallVector<FileByteRange, 1> &Ranges)
+ Level DiagLevel, llvm::StringRef BuildDirectory)
: DiagnosticName(DiagnosticName), Message(Message), Notes(Notes),
- DiagLevel(DiagLevel), BuildDirectory(BuildDirectory), Ranges(Ranges) {}
+ DiagLevel(DiagLevel), BuildDirectory(BuildDirectory) {}
const llvm::StringMap<Replacements> *selectFirstFix(const Diagnostic& D) {
if (!D.Message.Fix.empty())
diff --git a/src/llvm-project/clang/lib/Tooling/DependencyScanning/CMakeLists.txt b/src/llvm-project/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
index c6fe207..ce455e5 100644
--- a/src/llvm-project/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
+++ b/src/llvm-project/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
@@ -1,4 +1,5 @@
set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
Core
Support
)
@@ -16,6 +17,7 @@
LINK_LIBS
clangAST
clangBasic
+ clangCodeGen
clangDriver
clangFrontend
clangFrontendTool
diff --git a/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
index 1c10b7d..40e8bd2 100644
--- a/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
+++ b/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp
@@ -99,8 +99,7 @@
return Result;
}
-DependencyScanningFilesystemSharedCache::
- DependencyScanningFilesystemSharedCache() {
+DependencyScanningFilesystemSharedCache::SingleCache::SingleCache() {
// This heuristic was chosen using a empirical testing on a
// reasonably high core machine (iMacPro 18 cores / 36 threads). The cache
// sharding gives a performance edge by reducing the lock contention.
@@ -111,18 +110,20 @@
CacheShards = std::make_unique<CacheShard[]>(NumShards);
}
-/// Returns a cache entry for the corresponding key.
-///
-/// A new cache entry is created if the key is not in the cache. This is a
-/// thread safe call.
DependencyScanningFilesystemSharedCache::SharedFileSystemEntry &
-DependencyScanningFilesystemSharedCache::get(StringRef Key) {
+DependencyScanningFilesystemSharedCache::SingleCache::get(StringRef Key) {
CacheShard &Shard = CacheShards[llvm::hash_value(Key) % NumShards];
std::unique_lock<std::mutex> LockGuard(Shard.CacheLock);
auto It = Shard.Cache.try_emplace(Key);
return It.first->getValue();
}
+DependencyScanningFilesystemSharedCache::SharedFileSystemEntry &
+DependencyScanningFilesystemSharedCache::get(StringRef Key, bool Minimized) {
+ SingleCache &Cache = Minimized ? CacheMinimized : CacheOriginal;
+ return Cache.get(Key);
+}
+
/// Whitelist file extensions that should be minimized, treating no extension as
/// a source file that should be minimized.
///
@@ -149,20 +150,32 @@
return shouldMinimize(Filename); // Only cache stat failures on source files.
}
+void DependencyScanningWorkerFilesystem::ignoreFile(StringRef RawFilename) {
+ llvm::SmallString<256> Filename;
+ llvm::sys::path::native(RawFilename, Filename);
+ IgnoredFiles.insert(Filename);
+}
+
+bool DependencyScanningWorkerFilesystem::shouldIgnoreFile(
+ StringRef RawFilename) {
+ llvm::SmallString<256> Filename;
+ llvm::sys::path::native(RawFilename, Filename);
+ return IgnoredFiles.contains(Filename);
+}
+
llvm::ErrorOr<const CachedFileSystemEntry *>
DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry(
const StringRef Filename) {
- if (const CachedFileSystemEntry *Entry = getCachedEntry(Filename)) {
+ bool ShouldMinimize = !shouldIgnoreFile(Filename) && shouldMinimize(Filename);
+
+ if (const auto *Entry = Cache.getCachedEntry(Filename, ShouldMinimize))
return Entry;
- }
// FIXME: Handle PCM/PCH files.
// FIXME: Handle module map files.
- bool KeepOriginalSource = IgnoredFiles.count(Filename) ||
- !shouldMinimize(Filename);
DependencyScanningFilesystemSharedCache::SharedFileSystemEntry
- &SharedCacheEntry = SharedCache.get(Filename);
+ &SharedCacheEntry = SharedCache.get(Filename, ShouldMinimize);
const CachedFileSystemEntry *Result;
{
std::unique_lock<std::mutex> LockGuard(SharedCacheEntry.ValueLock);
@@ -184,15 +197,15 @@
CacheEntry = CachedFileSystemEntry::createDirectoryEntry(
std::move(*MaybeStatus));
else
- CacheEntry = CachedFileSystemEntry::createFileEntry(
- Filename, FS, !KeepOriginalSource);
+ CacheEntry = CachedFileSystemEntry::createFileEntry(Filename, FS,
+ ShouldMinimize);
}
Result = &CacheEntry;
}
// Store the result in the local cache.
- setCachedEntry(Filename, Result);
+ Cache.setCachedEntry(Filename, ShouldMinimize, Result);
return Result;
}
diff --git a/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp b/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp
index 93bb0cd..4f3e574 100644
--- a/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp
+++ b/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
+#include "llvm/Support/TargetSelect.h"
using namespace clang;
using namespace tooling;
@@ -16,4 +17,10 @@
ScanningMode Mode, ScanningOutputFormat Format, bool ReuseFileManager,
bool SkipExcludedPPRanges)
: Mode(Mode), Format(Format), ReuseFileManager(ReuseFileManager),
- SkipExcludedPPRanges(SkipExcludedPPRanges) {}
+ SkipExcludedPPRanges(SkipExcludedPPRanges) {
+ // Initialize targets for object file support.
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllAsmParsers();
+}
diff --git a/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
index 16040c2..2fd12f7 100644
--- a/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
+++ b/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
@@ -13,17 +13,38 @@
namespace tooling{
namespace dependencies{
-std::vector<std::string> FullDependencies::getAdditionalCommandLine(
- std::function<StringRef(ClangModuleDep)> LookupPCMPath,
- std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps) const {
- std::vector<std::string> Ret = AdditionalNonPathCommandLine;
+std::vector<std::string> FullDependencies::getAdditionalArgs(
+ std::function<StringRef(ModuleID)> LookupPCMPath,
+ std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const {
+ std::vector<std::string> Ret = getAdditionalArgsWithoutModulePaths();
- dependencies::detail::appendCommonModuleArguments(
- ClangModuleDeps, LookupPCMPath, LookupModuleDeps, Ret);
+ std::vector<std::string> PCMPaths;
+ std::vector<std::string> ModMapPaths;
+ dependencies::detail::collectPCMAndModuleMapPaths(
+ ClangModuleDeps, LookupPCMPath, LookupModuleDeps, PCMPaths, ModMapPaths);
+ for (const std::string &PCMPath : PCMPaths)
+ Ret.push_back("-fmodule-file=" + PCMPath);
+ for (const std::string &ModMapPath : ModMapPaths)
+ Ret.push_back("-fmodule-map-file=" + ModMapPath);
return Ret;
}
+std::vector<std::string>
+FullDependencies::getAdditionalArgsWithoutModulePaths() const {
+ std::vector<std::string> Args{
+ "-fno-implicit-modules",
+ "-fno-implicit-module-maps",
+ };
+
+ for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps) {
+ Args.push_back("-fmodule-file=" + PMD.ModuleName + "=" + PMD.PCMFile);
+ Args.push_back("-fmodule-map-file=" + PMD.ModuleMapFile);
+ }
+
+ return Args;
+}
+
DependencyScanningTool::DependencyScanningTool(
DependencyScanningService &Service)
: Worker(Service) {}
@@ -33,13 +54,19 @@
/// Prints out all of the gathered dependencies into a string.
class MakeDependencyPrinterConsumer : public DependencyConsumer {
public:
- void handleFileDependency(const DependencyOutputOptions &Opts,
- StringRef File) override {
- if (!this->Opts)
- this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
+ void
+ handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
+ this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
+ }
+
+ void handleFileDependency(StringRef File) override {
Dependencies.push_back(std::string(File));
}
+ void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
+ // Same as `handleModuleDependency`.
+ }
+
void handleModuleDependency(ModuleDeps MD) override {
// These are ignored for the make format as it can't support the full
// set of deps, and handleFileDependency handles enough for implicitly
@@ -49,8 +76,7 @@
void handleContextHash(std::string Hash) override {}
void printDependencies(std::string &S) {
- if (!Opts)
- return;
+ assert(Opts && "Handled dependency output options.");
class DependencyPrinter : public DependencyFileGenerator {
public:
@@ -103,13 +129,19 @@
FullDependencyPrinterConsumer(const llvm::StringSet<> &AlreadySeen)
: AlreadySeen(AlreadySeen) {}
- void handleFileDependency(const DependencyOutputOptions &Opts,
- StringRef File) override {
+ void
+ handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {}
+
+ void handleFileDependency(StringRef File) override {
Dependencies.push_back(std::string(File));
}
+ void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
+ PrebuiltModuleDeps.emplace_back(std::move(PMD));
+ }
+
void handleModuleDependency(ModuleDeps MD) override {
- ClangModuleDeps[MD.ContextHash + MD.ModuleName] = std::move(MD);
+ ClangModuleDeps[MD.ID.ContextHash + MD.ID.ModuleName] = std::move(MD);
}
void handleContextHash(std::string Hash) override {
@@ -119,16 +151,18 @@
FullDependenciesResult getFullDependencies() const {
FullDependencies FD;
- FD.ContextHash = std::move(ContextHash);
+ FD.ID.ContextHash = std::move(ContextHash);
FD.FileDeps.assign(Dependencies.begin(), Dependencies.end());
for (auto &&M : ClangModuleDeps) {
auto &MD = M.second;
if (MD.ImportedByMainFile)
- FD.ClangModuleDeps.push_back({MD.ModuleName, ContextHash});
+ FD.ClangModuleDeps.push_back(MD.ID);
}
+ FD.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
+
FullDependenciesResult FDR;
for (auto &&M : ClangModuleDeps) {
@@ -145,6 +179,7 @@
private:
std::vector<std::string> Dependencies;
+ std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
std::unordered_map<std::string, ModuleDeps> ClangModuleDeps;
std::string ContextHash;
std::vector<std::string> OutputPaths;
diff --git a/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 63264b0..d651ff2 100644
--- a/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/src/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
@@ -31,11 +32,12 @@
: DependencyFileGenerator(*Opts), Opts(std::move(Opts)), C(C) {}
void finishedMainFile(DiagnosticsEngine &Diags) override {
+ C.handleDependencyOutputOpts(*Opts);
llvm::SmallString<256> CanonPath;
for (const auto &File : getDependencies()) {
CanonPath = File;
llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true);
- C.handleFileDependency(*Opts, CanonPath);
+ C.handleFileDependency(CanonPath);
}
}
@@ -44,6 +46,93 @@
DependencyConsumer &C;
};
+/// A listener that collects the imported modules and optionally the input
+/// files.
+class PrebuiltModuleListener : public ASTReaderListener {
+public:
+ PrebuiltModuleListener(llvm::StringMap<std::string> &PrebuiltModuleFiles,
+ llvm::StringSet<> &InputFiles, bool VisitInputFiles)
+ : PrebuiltModuleFiles(PrebuiltModuleFiles), InputFiles(InputFiles),
+ VisitInputFiles(VisitInputFiles) {}
+
+ bool needsImportVisitation() const override { return true; }
+ bool needsInputFileVisitation() override { return VisitInputFiles; }
+ bool needsSystemInputFileVisitation() override { return VisitInputFiles; }
+
+ void visitImport(StringRef ModuleName, StringRef Filename) override {
+ PrebuiltModuleFiles.insert({ModuleName, Filename.str()});
+ }
+
+ bool visitInputFile(StringRef Filename, bool isSystem, bool isOverridden,
+ bool isExplicitModule) override {
+ InputFiles.insert(Filename);
+ return true;
+ }
+
+private:
+ llvm::StringMap<std::string> &PrebuiltModuleFiles;
+ llvm::StringSet<> &InputFiles;
+ bool VisitInputFiles;
+};
+
+using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles);
+
+/// Visit the given prebuilt module and collect all of the modules it
+/// transitively imports and contributing input files.
+static void visitPrebuiltModule(StringRef PrebuiltModuleFilename,
+ CompilerInstance &CI,
+ PrebuiltModuleFilesT &ModuleFiles,
+ llvm::StringSet<> &InputFiles,
+ bool VisitInputFiles) {
+ // Maps the names of modules that weren't yet visited to their PCM path.
+ llvm::StringMap<std::string> ModuleFilesWorklist;
+ // Contains PCM paths of all visited modules.
+ llvm::StringSet<> VisitedModuleFiles;
+
+ PrebuiltModuleListener Listener(ModuleFilesWorklist, InputFiles,
+ VisitInputFiles);
+
+ auto GatherModuleFileInfo = [&](StringRef ASTFile) {
+ ASTReader::readASTFileControlBlock(
+ ASTFile, CI.getFileManager(), CI.getPCHContainerReader(),
+ /*FindModuleFileExtensions=*/false, Listener,
+ /*ValidateDiagnosticOptions=*/false);
+ };
+
+ GatherModuleFileInfo(PrebuiltModuleFilename);
+ while (!ModuleFilesWorklist.empty()) {
+ auto WorklistItemIt = ModuleFilesWorklist.begin();
+
+ if (!VisitedModuleFiles.contains(WorklistItemIt->getValue())) {
+ VisitedModuleFiles.insert(WorklistItemIt->getValue());
+ GatherModuleFileInfo(WorklistItemIt->getValue());
+ ModuleFiles[WorklistItemIt->getKey().str()] = WorklistItemIt->getValue();
+ }
+
+ ModuleFilesWorklist.erase(WorklistItemIt);
+ }
+}
+
+/// Transform arbitrary file name into an object-like file name.
+static std::string makeObjFileName(StringRef FileName) {
+ SmallString<128> ObjFileName(FileName);
+ llvm::sys::path::replace_extension(ObjFileName, "o");
+ return std::string(ObjFileName.str());
+}
+
+/// Deduce the dependency target based on the output file and input files.
+static std::string
+deduceDepTarget(const std::string &OutputFile,
+ const SmallVectorImpl<FrontendInputFile> &InputFiles) {
+ if (OutputFile != "-")
+ return OutputFile;
+
+ if (InputFiles.empty() || !InputFiles.front().isFile())
+ return "clang-scan-deps\\ dependency";
+
+ return makeObjFileName(InputFiles.front().getFile());
+}
+
/// A clang tool that runs the preprocessor in a mode that's optimized for
/// dependency scanning for the given compiler invocation.
class DependencyScanningAction : public tooling::ToolAction {
@@ -61,28 +150,57 @@
FileManager *FileMgr,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override {
+ // Make a deep copy of the original Clang invocation.
+ CompilerInvocation OriginalInvocation(*Invocation);
+
// Create a compiler instance to handle the actual work.
CompilerInstance Compiler(std::move(PCHContainerOps));
Compiler.setInvocation(std::move(Invocation));
// Don't print 'X warnings and Y errors generated'.
Compiler.getDiagnosticOpts().ShowCarets = false;
+ // Don't write out diagnostic file.
+ Compiler.getDiagnosticOpts().DiagnosticSerializationFile.clear();
+ // Don't treat warnings as errors.
+ Compiler.getDiagnosticOpts().Warnings.push_back("no-error");
// Create the compiler's actual diagnostics engine.
Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!Compiler.hasDiagnostics())
return false;
- // Use the dependency scanning optimized file system if we can.
+ Compiler.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath = true;
+
+ FileMgr->getFileSystemOpts().WorkingDir = std::string(WorkingDirectory);
+ Compiler.setFileManager(FileMgr);
+ Compiler.createSourceManager(*FileMgr);
+
+ llvm::StringSet<> PrebuiltModulesInputFiles;
+ // Store the list of prebuilt module files into header search options. This
+ // will prevent the implicit build to create duplicate modules and will
+ // force reuse of the existing prebuilt module files instead.
+ if (!Compiler.getPreprocessorOpts().ImplicitPCHInclude.empty())
+ visitPrebuiltModule(
+ Compiler.getPreprocessorOpts().ImplicitPCHInclude, Compiler,
+ Compiler.getHeaderSearchOpts().PrebuiltModuleFiles,
+ PrebuiltModulesInputFiles, /*VisitInputFiles=*/DepFS != nullptr);
+
+ // Use the dependency scanning optimized file system if requested to do so.
if (DepFS) {
const CompilerInvocation &CI = Compiler.getInvocation();
+ DepFS->clearIgnoredFiles();
+ // Ignore any files that contributed to prebuilt modules. The implicit
+ // build validates the modules by comparing the reported sizes of their
+ // inputs to the current state of the filesystem. Minimization would throw
+ // this mechanism off.
+ for (const auto &File : PrebuiltModulesInputFiles)
+ DepFS->ignoreFile(File.getKey());
// Add any filenames that were explicity passed in the build settings and
// that might be opened, as we want to ensure we don't run source
// minimization on them.
- DepFS->IgnoredFiles.clear();
for (const auto &Entry : CI.getHeaderSearchOpts().UserEntries)
- DepFS->IgnoredFiles.insert(Entry.Path);
+ DepFS->ignoreFile(Entry.Path);
for (const auto &Entry : CI.getHeaderSearchOpts().VFSOverlayFiles)
- DepFS->IgnoredFiles.insert(Entry);
+ DepFS->ignoreFile(Entry);
// Support for virtual file system overlays on top of the caching
// filesystem.
@@ -96,10 +214,6 @@
.ExcludedConditionalDirectiveSkipMappings = PPSkipMappings;
}
- FileMgr->getFileSystemOpts().WorkingDir = std::string(WorkingDirectory);
- Compiler.setFileManager(FileMgr);
- Compiler.createSourceManager(*FileMgr);
-
// Create the dependency collector that will collect the produced
// dependencies.
//
@@ -107,11 +221,14 @@
// invocation to the collector. The options in the invocation are reset,
// which ensures that the compiler won't create new dependency collectors,
// and thus won't write out the extra '.d' files to disk.
- auto Opts = std::make_unique<DependencyOutputOptions>(
- std::move(Compiler.getInvocation().getDependencyOutputOpts()));
- // We need at least one -MT equivalent for the generator to work.
+ auto Opts = std::make_unique<DependencyOutputOptions>();
+ std::swap(*Opts, Compiler.getInvocation().getDependencyOutputOpts());
+ // We need at least one -MT equivalent for the generator of make dependency
+ // files to work.
if (Opts->Targets.empty())
- Opts->Targets = {"clang-scan-deps dependency"};
+ Opts->Targets = {deduceDepTarget(Compiler.getFrontendOpts().OutputFile,
+ Compiler.getFrontendOpts().Inputs)};
+ Opts->IncludeSystemHeaders = true;
switch (Format) {
case ScanningOutputFormat::Make:
@@ -121,7 +238,7 @@
break;
case ScanningOutputFormat::Full:
Compiler.addDependencyCollector(std::make_shared<ModuleDepCollector>(
- std::move(Opts), Compiler, Consumer));
+ std::move(Opts), Compiler, Consumer, std::move(OriginalInvocation)));
break;
}
@@ -132,7 +249,7 @@
// the impact of strict context hashing.
Compiler.getHeaderSearchOpts().ModulesStrictContextHash = true;
- auto Action = std::make_unique<PreprocessOnlyAction>();
+ auto Action = std::make_unique<ReadPCHAndPreprocessAction>();
const bool Result = Compiler.ExecuteAction(*Action);
if (!DepFS)
FileMgr->clearStatCache();
@@ -153,7 +270,15 @@
DependencyScanningService &Service)
: Format(Service.getFormat()) {
DiagOpts = new DiagnosticOptions();
+
PCHContainerOps = std::make_shared<PCHContainerOperations>();
+ PCHContainerOps->registerReader(
+ std::make_unique<ObjectFilePCHContainerReader>());
+ // We don't need to write object files, but the current PCH implementation
+ // requires the writer to be registered as well.
+ PCHContainerOps->registerWriter(
+ std::make_unique<ObjectFilePCHContainerWriter>());
+
RealFS = llvm::vfs::createPhysicalFileSystem();
if (Service.canSkipExcludedPPRanges())
PPSkipMappings =
diff --git a/src/llvm-project/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/src/llvm-project/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index f74ce73..88cee63 100644
--- a/src/llvm-project/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/src/llvm-project/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -12,49 +12,97 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
+#include "llvm/Support/StringSaver.h"
using namespace clang;
using namespace tooling;
using namespace dependencies;
-std::vector<std::string> ModuleDeps::getFullCommandLine(
- std::function<StringRef(ClangModuleDep)> LookupPCMPath,
- std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps) const {
- std::vector<std::string> Ret = NonPathCommandLine;
+CompilerInvocation ModuleDepCollector::makeInvocationForModuleBuildWithoutPaths(
+ const ModuleDeps &Deps) const {
+ // Make a deep copy of the original Clang invocation.
+ CompilerInvocation CI(OriginalInvocation);
- // TODO: Build full command line. That also means capturing the original
- // command line into NonPathCommandLine.
+ // Remove options incompatible with explicit module build.
+ CI.getFrontendOpts().Inputs.clear();
+ CI.getFrontendOpts().OutputFile.clear();
- dependencies::detail::appendCommonModuleArguments(
- ClangModuleDeps, LookupPCMPath, LookupModuleDeps, Ret);
+ CI.getFrontendOpts().ProgramAction = frontend::GenerateModule;
+ CI.getLangOpts()->ModuleName = Deps.ID.ModuleName;
+ CI.getFrontendOpts().IsSystemModule = Deps.IsSystem;
- return Ret;
+ CI.getLangOpts()->ImplicitModules = false;
+
+ // Report the prebuilt modules this module uses.
+ for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps) {
+ CI.getFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
+ CI.getFrontendOpts().ModuleMapFiles.push_back(PrebuiltModule.ModuleMapFile);
+ }
+
+ CI.getPreprocessorOpts().ImplicitPCHInclude.clear();
+
+ return CI;
}
-void dependencies::detail::appendCommonModuleArguments(
- llvm::ArrayRef<ClangModuleDep> Modules,
- std::function<StringRef(ClangModuleDep)> LookupPCMPath,
- std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps,
- std::vector<std::string> &Result) {
+static std::vector<std::string>
+serializeCompilerInvocation(const CompilerInvocation &CI) {
+ // Set up string allocator.
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver Strings(Alloc);
+ auto SA = [&Strings](const Twine &Arg) { return Strings.save(Arg).data(); };
+
+ // Synthesize full command line from the CompilerInvocation, including "-cc1".
+ SmallVector<const char *, 32> Args{"-cc1"};
+ CI.generateCC1CommandLine(Args, SA);
+
+ // Convert arguments to the return type.
+ return std::vector<std::string>{Args.begin(), Args.end()};
+}
+
+std::vector<std::string> ModuleDeps::getCanonicalCommandLine(
+ std::function<StringRef(ModuleID)> LookupPCMPath,
+ std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const {
+ CompilerInvocation CI(Invocation);
+ FrontendOptions &FrontendOpts = CI.getFrontendOpts();
+
+ InputKind ModuleMapInputKind(FrontendOpts.DashX.getLanguage(),
+ InputKind::Format::ModuleMap);
+ FrontendOpts.Inputs.emplace_back(ClangModuleMapFile, ModuleMapInputKind);
+ FrontendOpts.OutputFile = std::string(LookupPCMPath(ID));
+
+ dependencies::detail::collectPCMAndModuleMapPaths(
+ ClangModuleDeps, LookupPCMPath, LookupModuleDeps,
+ FrontendOpts.ModuleFiles, FrontendOpts.ModuleMapFiles);
+
+ return serializeCompilerInvocation(CI);
+}
+
+std::vector<std::string>
+ModuleDeps::getCanonicalCommandLineWithoutModulePaths() const {
+ return serializeCompilerInvocation(Invocation);
+}
+
+void dependencies::detail::collectPCMAndModuleMapPaths(
+ llvm::ArrayRef<ModuleID> Modules,
+ std::function<StringRef(ModuleID)> LookupPCMPath,
+ std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps,
+ std::vector<std::string> &PCMPaths, std::vector<std::string> &ModMapPaths) {
llvm::StringSet<> AlreadyAdded;
- std::function<void(llvm::ArrayRef<ClangModuleDep>)> AddArgs =
- [&](llvm::ArrayRef<ClangModuleDep> Modules) {
- for (const ClangModuleDep &CMD : Modules) {
- if (!AlreadyAdded.insert(CMD.ModuleName + CMD.ContextHash).second)
+ std::function<void(llvm::ArrayRef<ModuleID>)> AddArgs =
+ [&](llvm::ArrayRef<ModuleID> Modules) {
+ for (const ModuleID &MID : Modules) {
+ if (!AlreadyAdded.insert(MID.ModuleName + MID.ContextHash).second)
continue;
- const ModuleDeps &M = LookupModuleDeps(CMD);
+ const ModuleDeps &M = LookupModuleDeps(MID);
// Depth first traversal.
AddArgs(M.ClangModuleDeps);
- Result.push_back(("-fmodule-file=" + LookupPCMPath(CMD)).str());
- if (!M.ClangModuleMapFile.empty()) {
- Result.push_back("-fmodule-map-file=" + M.ClangModuleMapFile);
- }
+ PCMPaths.push_back(LookupPCMPath(MID).str());
+ if (!M.ClangModuleMapFile.empty())
+ ModMapPaths.push_back(M.ClangModuleMapFile);
}
};
- Result.push_back("-fno-implicit-modules");
- Result.push_back("-fno-implicit-module-maps");
AddArgs(Modules);
}
@@ -79,7 +127,7 @@
// We do not want #line markers to affect dependency generation!
if (Optional<StringRef> Filename =
SM.getNonBuiltinFilenameForID(SM.getFileID(SM.getExpansionLoc(Loc))))
- MDC.MainDeps.push_back(
+ MDC.FileDeps.push_back(
std::string(llvm::sys::path::remove_leading_dotslash(*Filename)));
}
@@ -91,7 +139,7 @@
if (!File && !Imported) {
// This is a non-modular include that HeaderSearch failed to find. Add it
// here as `FileChanged` will never see it.
- MDC.MainDeps.push_back(std::string(FileName));
+ MDC.FileDeps.push_back(std::string(FileName));
}
handleImport(Imported);
}
@@ -106,9 +154,12 @@
if (!Imported)
return;
- MDC.Deps[MDC.ContextHash + Imported->getTopLevelModule()->getFullModuleName()]
- .ImportedByMainFile = true;
- DirectDeps.insert(Imported->getTopLevelModule());
+ const Module *TopLevelModule = Imported->getTopLevelModule();
+
+ if (MDC.isPrebuiltModule(TopLevelModule))
+ DirectPrebuiltModularDeps.insert(TopLevelModule);
+ else
+ DirectModularDeps.insert(TopLevelModule);
}
void ModuleDepCollectorPP::EndOfMainFile() {
@@ -116,46 +167,88 @@
MDC.MainFile = std::string(
Instance.getSourceManager().getFileEntryForID(MainFileID)->getName());
- for (const Module *M : DirectDeps) {
+ if (!Instance.getPreprocessorOpts().ImplicitPCHInclude.empty())
+ MDC.FileDeps.push_back(Instance.getPreprocessorOpts().ImplicitPCHInclude);
+
+ for (const Module *M : DirectModularDeps) {
+ // A top-level module might not be actually imported as a module when
+ // -fmodule-name is used to compile a translation unit that imports this
+ // module. In that case it can be skipped. The appropriate header
+ // dependencies will still be reported as expected.
+ if (!M->getASTFile())
+ continue;
handleTopLevelModule(M);
}
- for (auto &&I : MDC.Deps)
+ MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts);
+
+ for (auto &&I : MDC.ModularDeps)
MDC.Consumer.handleModuleDependency(I.second);
- for (auto &&I : MDC.MainDeps)
- MDC.Consumer.handleFileDependency(*MDC.Opts, I);
+ for (auto &&I : MDC.FileDeps)
+ MDC.Consumer.handleFileDependency(I);
+
+ for (auto &&I : DirectPrebuiltModularDeps)
+ MDC.Consumer.handlePrebuiltModuleDependency(PrebuiltModuleDep{I});
}
-void ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
+ModuleID ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
assert(M == M->getTopLevelModule() && "Expected top level module!");
- auto ModI = MDC.Deps.insert(
- std::make_pair(MDC.ContextHash + M->getFullModuleName(), ModuleDeps{}));
-
- if (!ModI.first->second.ModuleName.empty())
- return;
+ // If this module has been handled already, just return its ID.
+ auto ModI = MDC.ModularDeps.insert({M, ModuleDeps{}});
+ if (!ModI.second)
+ return ModI.first->second.ID;
ModuleDeps &MD = ModI.first->second;
+ MD.ID.ModuleName = M->getFullModuleName();
+ MD.ImportedByMainFile = DirectModularDeps.contains(M);
+ MD.ImplicitModulePCMPath = std::string(M->getASTFile()->getName());
+ MD.IsSystem = M->IsSystem;
+
const FileEntry *ModuleMap = Instance.getPreprocessor()
.getHeaderSearchInfo()
.getModuleMap()
- .getContainingModuleMapFile(M);
-
+ .getModuleMapFileForUniquing(M);
MD.ClangModuleMapFile = std::string(ModuleMap ? ModuleMap->getName() : "");
- MD.ModuleName = M->getFullModuleName();
- MD.ImplicitModulePCMPath = std::string(M->getASTFile()->getName());
- MD.ContextHash = MDC.ContextHash;
+
serialization::ModuleFile *MF =
MDC.Instance.getASTReader()->getModuleManager().lookup(M->getASTFile());
MDC.Instance.getASTReader()->visitInputFiles(
*MF, true, true, [&](const serialization::InputFile &IF, bool isSystem) {
+ // __inferred_module.map is the result of the way in which an implicit
+ // module build handles inferred modules. It adds an overlay VFS with
+ // this file in the proper directory and relies on the rest of Clang to
+ // handle it like normal. With explicitly built modules we don't need
+ // to play VFS tricks, so replace it with the correct module map.
+ if (IF.getFile()->getName().endswith("__inferred_module.map")) {
+ MD.FileDeps.insert(ModuleMap->getName());
+ return;
+ }
MD.FileDeps.insert(IF.getFile()->getName());
});
+ // Add direct prebuilt module dependencies now, so that we can use them when
+ // creating a CompilerInvocation and computing context hash for this
+ // ModuleDeps instance.
+ addDirectPrebuiltModuleDeps(M, MD);
+
+ MD.Invocation = MDC.makeInvocationForModuleBuildWithoutPaths(MD);
+ MD.ID.ContextHash = MD.Invocation.getModuleHash();
+
llvm::DenseSet<const Module *> AddedModules;
addAllSubmoduleDeps(M, MD, AddedModules);
+
+ return MD.ID;
+}
+
+void ModuleDepCollectorPP::addDirectPrebuiltModuleDeps(const Module *M,
+ ModuleDeps &MD) {
+ for (const Module *Import : M->Imports)
+ if (Import->getTopLevelModule() != M->getTopLevelModule())
+ if (MDC.isPrebuiltModule(Import))
+ MD.PrebuiltModuleDeps.emplace_back(Import);
}
void ModuleDepCollectorPP::addAllSubmoduleDeps(
@@ -171,23 +264,35 @@
const Module *M, ModuleDeps &MD,
llvm::DenseSet<const Module *> &AddedModules) {
for (const Module *Import : M->Imports) {
- if (Import->getTopLevelModule() != M->getTopLevelModule()) {
+ if (Import->getTopLevelModule() != M->getTopLevelModule() &&
+ !MDC.isPrebuiltModule(Import)) {
+ ModuleID ImportID = handleTopLevelModule(Import->getTopLevelModule());
if (AddedModules.insert(Import->getTopLevelModule()).second)
- MD.ClangModuleDeps.push_back(
- {std::string(Import->getTopLevelModuleName()),
- Instance.getInvocation().getModuleHash()});
- handleTopLevelModule(Import->getTopLevelModule());
+ MD.ClangModuleDeps.push_back(ImportID);
}
}
}
ModuleDepCollector::ModuleDepCollector(
std::unique_ptr<DependencyOutputOptions> Opts, CompilerInstance &I,
- DependencyConsumer &C)
- : Instance(I), Consumer(C), Opts(std::move(Opts)) {}
+ DependencyConsumer &C, CompilerInvocation &&OriginalCI)
+ : Instance(I), Consumer(C), Opts(std::move(Opts)),
+ OriginalInvocation(std::move(OriginalCI)) {}
void ModuleDepCollector::attachToPreprocessor(Preprocessor &PP) {
PP.addPPCallbacks(std::make_unique<ModuleDepCollectorPP>(Instance, *this));
}
void ModuleDepCollector::attachToASTReader(ASTReader &R) {}
+
+bool ModuleDepCollector::isPrebuiltModule(const Module *M) {
+ std::string Name(M->getTopLevelModuleName());
+ const auto &PrebuiltModuleFiles =
+ Instance.getHeaderSearchOpts().PrebuiltModuleFiles;
+ auto PrebuiltModuleFileIt = PrebuiltModuleFiles.find(Name);
+ if (PrebuiltModuleFileIt == PrebuiltModuleFiles.end())
+ return false;
+ assert("Prebuilt module came from the expected AST file" &&
+ PrebuiltModuleFileIt->second == M->getASTFile()->getName());
+ return true;
+}
diff --git a/src/llvm-project/clang/lib/Tooling/DumpTool/APIData.h b/src/llvm-project/clang/lib/Tooling/DumpTool/APIData.h
new file mode 100644
index 0000000..03e247a
--- /dev/null
+++ b/src/llvm-project/clang/lib/Tooling/DumpTool/APIData.h
@@ -0,0 +1,31 @@
+//===- APIData.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 LLVM_CLANG_LIB_TOOLING_DUMPTOOL_APIDATA_H
+#define LLVM_CLANG_LIB_TOOLING_DUMPTOOL_APIDATA_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+struct ClassData {
+ std::vector<std::string> ASTClassLocations;
+ std::vector<std::string> ASTClassRanges;
+ std::vector<std::string> TemplateParms;
+ std::vector<std::string> TypeSourceInfos;
+ std::vector<std::string> TypeLocs;
+ std::vector<std::string> NestedNameLocs;
+ std::vector<std::string> DeclNameInfos;
+};
+
+} // namespace tooling
+} // namespace clang
+
+#endif
diff --git a/src/llvm-project/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp b/src/llvm-project/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp
new file mode 100644
index 0000000..2f97067
--- /dev/null
+++ b/src/llvm-project/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.cpp
@@ -0,0 +1,271 @@
+//===- ASTSrcLocProcessor.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTSrcLocProcessor.h"
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace clang::tooling;
+using namespace llvm;
+using namespace clang::ast_matchers;
+
+ASTSrcLocProcessor::ASTSrcLocProcessor(StringRef JsonPath)
+ : JsonPath(JsonPath) {
+
+ MatchFinder::MatchFinderOptions FinderOptions;
+
+ Finder = std::make_unique<MatchFinder>(std::move(FinderOptions));
+ Finder->addMatcher(
+ cxxRecordDecl(
+ isDefinition(),
+ isSameOrDerivedFrom(
+ namedDecl(
+ hasAnyName(
+ "clang::Stmt", "clang::Decl", "clang::CXXCtorInitializer",
+ "clang::NestedNameSpecifierLoc",
+ "clang::TemplateArgumentLoc", "clang::CXXBaseSpecifier",
+ "clang::DeclarationNameInfo", "clang::TypeLoc"))
+ .bind("nodeClade")),
+ optionally(isDerivedFrom(cxxRecordDecl().bind("derivedFrom"))))
+ .bind("className"),
+ this);
+ Finder->addMatcher(
+ cxxRecordDecl(isDefinition(), hasAnyName("clang::PointerLikeTypeLoc",
+ "clang::TypeofLikeTypeLoc"))
+ .bind("templateName"),
+ this);
+}
+
+std::unique_ptr<clang::ASTConsumer>
+ASTSrcLocProcessor::createASTConsumer(clang::CompilerInstance &Compiler,
+ StringRef File) {
+ return Finder->newASTConsumer();
+}
+
+llvm::json::Object toJSON(llvm::StringMap<std::vector<StringRef>> const &Obj) {
+ using llvm::json::toJSON;
+
+ llvm::json::Object JsonObj;
+ for (const auto &Item : Obj) {
+ JsonObj[Item.first()] = Item.second;
+ }
+ return JsonObj;
+}
+
+llvm::json::Object toJSON(llvm::StringMap<std::string> const &Obj) {
+ using llvm::json::toJSON;
+
+ llvm::json::Object JsonObj;
+ for (const auto &Item : Obj) {
+ JsonObj[Item.first()] = Item.second;
+ }
+ return JsonObj;
+}
+
+llvm::json::Object toJSON(ClassData const &Obj) {
+ llvm::json::Object JsonObj;
+
+ if (!Obj.ASTClassLocations.empty())
+ JsonObj["sourceLocations"] = Obj.ASTClassLocations;
+ if (!Obj.ASTClassRanges.empty())
+ JsonObj["sourceRanges"] = Obj.ASTClassRanges;
+ if (!Obj.TemplateParms.empty())
+ JsonObj["templateParms"] = Obj.TemplateParms;
+ if (!Obj.TypeSourceInfos.empty())
+ JsonObj["typeSourceInfos"] = Obj.TypeSourceInfos;
+ if (!Obj.TypeLocs.empty())
+ JsonObj["typeLocs"] = Obj.TypeLocs;
+ if (!Obj.NestedNameLocs.empty())
+ JsonObj["nestedNameLocs"] = Obj.NestedNameLocs;
+ if (!Obj.DeclNameInfos.empty())
+ JsonObj["declNameInfos"] = Obj.DeclNameInfos;
+ return JsonObj;
+}
+
+llvm::json::Object toJSON(llvm::StringMap<ClassData> const &Obj) {
+ using llvm::json::toJSON;
+
+ llvm::json::Object JsonObj;
+ for (const auto &Item : Obj)
+ JsonObj[Item.first()] = ::toJSON(Item.second);
+ return JsonObj;
+}
+
+void WriteJSON(StringRef JsonPath, llvm::json::Object &&ClassInheritance,
+ llvm::json::Object &&ClassesInClade,
+ llvm::json::Object &&ClassEntries) {
+ llvm::json::Object JsonObj;
+
+ using llvm::json::toJSON;
+
+ JsonObj["classInheritance"] = std::move(ClassInheritance);
+ JsonObj["classesInClade"] = std::move(ClassesInClade);
+ JsonObj["classEntries"] = std::move(ClassEntries);
+
+ llvm::json::Value JsonVal(std::move(JsonObj));
+
+ bool WriteChange = false;
+ std::string OutString;
+ if (auto ExistingOrErr = MemoryBuffer::getFile(JsonPath, /*IsText=*/true)) {
+ raw_string_ostream Out(OutString);
+ Out << formatv("{0:2}", JsonVal);
+ if (ExistingOrErr.get()->getBuffer() == Out.str())
+ return;
+ WriteChange = true;
+ }
+
+ std::error_code EC;
+ llvm::raw_fd_ostream JsonOut(JsonPath, EC, llvm::sys::fs::OF_Text);
+ if (EC)
+ return;
+
+ if (WriteChange)
+ JsonOut << OutString;
+ else
+ JsonOut << formatv("{0:2}", JsonVal);
+}
+
+void ASTSrcLocProcessor::generate() {
+ WriteJSON(JsonPath, ::toJSON(ClassInheritance), ::toJSON(ClassesInClade),
+ ::toJSON(ClassEntries));
+}
+
+void ASTSrcLocProcessor::generateEmpty() { WriteJSON(JsonPath, {}, {}, {}); }
+
+std::vector<std::string>
+CaptureMethods(std::string TypeString, const clang::CXXRecordDecl *ASTClass,
+ const MatchFinder::MatchResult &Result) {
+
+ auto publicAccessor = [](auto... InnerMatcher) {
+ return cxxMethodDecl(isPublic(), parameterCountIs(0), isConst(),
+ InnerMatcher...);
+ };
+
+ auto BoundNodesVec = match(
+ findAll(
+ publicAccessor(
+ ofClass(cxxRecordDecl(
+ equalsNode(ASTClass),
+ optionally(isDerivedFrom(
+ cxxRecordDecl(hasAnyName("clang::Stmt", "clang::Decl"))
+ .bind("stmtOrDeclBase"))),
+ optionally(isDerivedFrom(
+ cxxRecordDecl(hasName("clang::Expr")).bind("exprBase"))),
+ optionally(
+ isDerivedFrom(cxxRecordDecl(hasName("clang::TypeLoc"))
+ .bind("typeLocBase"))))),
+ returns(asString(TypeString)))
+ .bind("classMethod")),
+ *ASTClass, *Result.Context);
+
+ std::vector<std::string> Methods;
+ for (const auto &BN : BoundNodesVec) {
+ if (const auto *Node = BN.getNodeAs<clang::NamedDecl>("classMethod")) {
+ const auto *StmtOrDeclBase =
+ BN.getNodeAs<clang::CXXRecordDecl>("stmtOrDeclBase");
+ const auto *TypeLocBase =
+ BN.getNodeAs<clang::CXXRecordDecl>("typeLocBase");
+ const auto *ExprBase = BN.getNodeAs<clang::CXXRecordDecl>("exprBase");
+ // The clang AST has several methods on base classes which are overriden
+ // pseudo-virtually by derived classes.
+ // We record only the pseudo-virtual methods on the base classes to
+ // avoid duplication.
+ if (StmtOrDeclBase &&
+ (Node->getName() == "getBeginLoc" || Node->getName() == "getEndLoc" ||
+ Node->getName() == "getSourceRange"))
+ continue;
+ if (ExprBase && Node->getName() == "getExprLoc")
+ continue;
+ if (TypeLocBase && Node->getName() == "getLocalSourceRange")
+ continue;
+ if ((ASTClass->getName() == "PointerLikeTypeLoc" ||
+ ASTClass->getName() == "TypeofLikeTypeLoc") &&
+ Node->getName() == "getLocalSourceRange")
+ continue;
+ Methods.push_back(Node->getName().str());
+ }
+ }
+ return Methods;
+}
+
+void ASTSrcLocProcessor::run(const MatchFinder::MatchResult &Result) {
+
+ const auto *ASTClass =
+ Result.Nodes.getNodeAs<clang::CXXRecordDecl>("className");
+
+ StringRef CladeName;
+ if (ASTClass) {
+ if (const auto *NodeClade =
+ Result.Nodes.getNodeAs<clang::CXXRecordDecl>("nodeClade"))
+ CladeName = NodeClade->getName();
+ } else {
+ ASTClass = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("templateName");
+ CladeName = "TypeLoc";
+ }
+
+ StringRef ClassName = ASTClass->getName();
+
+ ClassData CD;
+
+ CD.ASTClassLocations =
+ CaptureMethods("class clang::SourceLocation", ASTClass, Result);
+ CD.ASTClassRanges =
+ CaptureMethods("class clang::SourceRange", ASTClass, Result);
+ CD.TypeSourceInfos =
+ CaptureMethods("class clang::TypeSourceInfo *", ASTClass, Result);
+ CD.TypeLocs = CaptureMethods("class clang::TypeLoc", ASTClass, Result);
+ CD.NestedNameLocs =
+ CaptureMethods("class clang::NestedNameSpecifierLoc", ASTClass, Result);
+ CD.DeclNameInfos =
+ CaptureMethods("struct clang::DeclarationNameInfo", ASTClass, Result);
+ auto DI = CaptureMethods("const struct clang::DeclarationNameInfo &",
+ ASTClass, Result);
+ CD.DeclNameInfos.insert(CD.DeclNameInfos.end(), DI.begin(), DI.end());
+
+ if (const auto *DerivedFrom =
+ Result.Nodes.getNodeAs<clang::CXXRecordDecl>("derivedFrom")) {
+
+ if (const auto *Templ =
+ llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
+ DerivedFrom)) {
+
+ const auto &TArgs = Templ->getTemplateArgs();
+
+ SmallString<256> TArgsString;
+ llvm::raw_svector_ostream OS(TArgsString);
+ OS << DerivedFrom->getName() << '<';
+
+ clang::PrintingPolicy PPol(Result.Context->getLangOpts());
+ PPol.TerseOutput = true;
+
+ for (unsigned I = 0; I < TArgs.size(); ++I) {
+ if (I > 0)
+ OS << ", ";
+ TArgs.get(I).getAsType().print(OS, PPol);
+ }
+ OS << '>';
+
+ ClassInheritance[ClassName] = TArgsString.str().str();
+ } else {
+ ClassInheritance[ClassName] = DerivedFrom->getName().str();
+ }
+ }
+
+ if (const auto *Templ = ASTClass->getDescribedClassTemplate()) {
+ if (auto *TParams = Templ->getTemplateParameters()) {
+ for (const auto &TParam : *TParams) {
+ CD.TemplateParms.push_back(TParam->getName().str());
+ }
+ }
+ }
+
+ ClassEntries[ClassName] = CD;
+ ClassesInClade[CladeName].push_back(ClassName);
+}
diff --git a/src/llvm-project/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h b/src/llvm-project/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h
new file mode 100644
index 0000000..05c4f92
--- /dev/null
+++ b/src/llvm-project/clang/lib/Tooling/DumpTool/ASTSrcLocProcessor.h
@@ -0,0 +1,53 @@
+//===- ASTSrcLocProcessor.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 LLVM_CLANG_TOOLING_DUMPTOOL_ASTSRCLOCPROCESSOR_H
+#define LLVM_CLANG_TOOLING_DUMPTOOL_ASTSRCLOCPROCESSOR_H
+
+#include "APIData.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class CompilerInstance;
+
+namespace tooling {
+
+class ASTSrcLocProcessor : public ast_matchers::MatchFinder::MatchCallback {
+public:
+ explicit ASTSrcLocProcessor(StringRef JsonPath);
+
+ std::unique_ptr<ASTConsumer> createASTConsumer(CompilerInstance &Compiler,
+ StringRef File);
+
+ void generate();
+ void generateEmpty();
+
+private:
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+ llvm::Optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+
+ llvm::StringMap<std::string> ClassInheritance;
+ llvm::StringMap<std::vector<StringRef>> ClassesInClade;
+ llvm::StringMap<ClassData> ClassEntries;
+
+ std::string JsonPath;
+ std::unique_ptr<clang::ast_matchers::MatchFinder> Finder;
+};
+
+} // namespace tooling
+} // namespace clang
+
+#endif
diff --git a/src/llvm-project/clang/lib/Tooling/DumpTool/CMakeLists.txt b/src/llvm-project/clang/lib/Tooling/DumpTool/CMakeLists.txt
new file mode 100644
index 0000000..712985b
--- /dev/null
+++ b/src/llvm-project/clang/lib/Tooling/DumpTool/CMakeLists.txt
@@ -0,0 +1,16 @@
+
+add_clang_executable(clang-ast-dump
+ ASTSrcLocProcessor.cpp
+ ClangSrcLocDump.cpp
+)
+
+target_link_libraries(clang-ast-dump
+ PRIVATE
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangDriver
+ clangFrontend
+ clangSerialization
+ clangToolingCore
+)
diff --git a/src/llvm-project/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp b/src/llvm-project/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp
new file mode 100644
index 0000000..8091a46
--- /dev/null
+++ b/src/llvm-project/clang/lib/Tooling/DumpTool/ClangSrcLocDump.cpp
@@ -0,0 +1,159 @@
+//===- ClangSrcLocDump.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/JSON.h"
+
+#include "ASTSrcLocProcessor.h"
+
+using namespace clang::tooling;
+using namespace clang;
+using namespace llvm;
+
+static cl::list<std::string> IncludeDirectories(
+ "I", cl::desc("Include directories to use while compiling"),
+ cl::value_desc("directory"), cl::Required, cl::OneOrMore, cl::Prefix);
+
+static cl::opt<bool>
+ SkipProcessing("skip-processing",
+ cl::desc("Avoid processing the AST header file"),
+ cl::Required, cl::value_desc("bool"));
+
+static cl::opt<std::string> JsonOutputPath("json-output-path",
+ cl::desc("json output path"),
+ cl::Required,
+ cl::value_desc("path"));
+
+class ASTSrcLocGenerationAction : public clang::ASTFrontendAction {
+public:
+ ASTSrcLocGenerationAction() : Processor(JsonOutputPath) {}
+
+ void ExecuteAction() override {
+ clang::ASTFrontendAction::ExecuteAction();
+ if (getCompilerInstance().getDiagnostics().getNumErrors() > 0)
+ Processor.generateEmpty();
+ else
+ Processor.generate();
+ }
+
+ std::unique_ptr<clang::ASTConsumer>
+ CreateASTConsumer(clang::CompilerInstance &Compiler,
+ llvm::StringRef File) override {
+ return Processor.createASTConsumer(Compiler, File);
+ }
+
+private:
+ ASTSrcLocProcessor Processor;
+};
+
+static const char Filename[] = "ASTTU.cpp";
+
+int main(int argc, const char **argv) {
+
+ cl::ParseCommandLineOptions(argc, argv);
+
+ if (SkipProcessing) {
+ std::error_code EC;
+ llvm::raw_fd_ostream JsonOut(JsonOutputPath, EC, llvm::sys::fs::OF_Text);
+ if (EC)
+ return 1;
+ JsonOut << formatv("{0:2}", llvm::json::Value(llvm::json::Object()));
+ return 0;
+ }
+
+ std::vector<std::string> Args;
+ Args.push_back("-cc1");
+
+ llvm::transform(IncludeDirectories, std::back_inserter(Args),
+ [](const std::string &IncDir) { return "-I" + IncDir; });
+
+ Args.push_back("-fsyntax-only");
+ Args.push_back(Filename);
+
+ std::vector<const char *> Argv(Args.size(), nullptr);
+ llvm::transform(Args, Argv.begin(),
+ [](const std::string &Arg) { return Arg.c_str(); });
+
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ unsigned MissingArgIndex, MissingArgCount;
+ auto Opts = driver::getDriverOptTable();
+ auto ParsedArgs = Opts.ParseArgs(llvm::makeArrayRef(Argv).slice(1),
+ MissingArgIndex, MissingArgCount);
+ ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
+
+ // Don't output diagnostics, because common scenarios such as
+ // cross-compiling fail with diagnostics. This is not fatal, but
+ // just causes attempts to use the introspection API to return no data.
+ TextDiagnosticPrinter DiagnosticPrinter(llvm::nulls(), &*DiagOpts);
+ DiagnosticsEngine Diagnostics(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
+ &DiagnosticPrinter, false);
+
+ auto *OFS = new llvm::vfs::OverlayFileSystem(vfs::getRealFileSystem());
+
+ auto *MemFS = new llvm::vfs::InMemoryFileSystem();
+ OFS->pushOverlay(MemFS);
+ MemFS->addFile(Filename, 0,
+ MemoryBuffer::getMemBuffer("#include \"clang/AST/AST.h\"\n"));
+
+ auto Files = llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions(), OFS);
+
+ auto Driver = std::make_unique<driver::Driver>(
+ "clang", llvm::sys::getDefaultTargetTriple(), Diagnostics,
+ "ast-api-dump-tool", OFS);
+
+ std::unique_ptr<clang::driver::Compilation> Comp(
+ Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
+ if (!Comp)
+ return 1;
+
+ const auto &Jobs = Comp->getJobs();
+ if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
+ SmallString<256> error_msg;
+ llvm::raw_svector_ostream error_stream(error_msg);
+ Jobs.Print(error_stream, "; ", true);
+ return 1;
+ }
+
+ const auto &Cmd = cast<driver::Command>(*Jobs.begin());
+ const llvm::opt::ArgStringList &CC1Args = Cmd.getArguments();
+
+ auto Invocation = std::make_unique<CompilerInvocation>();
+ CompilerInvocation::CreateFromArgs(*Invocation, CC1Args, Diagnostics);
+
+ CompilerInstance Compiler(std::make_shared<clang::PCHContainerOperations>());
+ Compiler.setInvocation(std::move(Invocation));
+
+ Compiler.createDiagnostics(&DiagnosticPrinter, false);
+ if (!Compiler.hasDiagnostics())
+ return 1;
+
+ // Suppress "2 errors generated" or similar messages
+ Compiler.getDiagnosticOpts().ShowCarets = false;
+ Compiler.createSourceManager(*Files);
+ Compiler.setFileManager(Files.get());
+
+ ASTSrcLocGenerationAction ScopedToolAction;
+ Compiler.ExecuteAction(ScopedToolAction);
+
+ Files->clearStatCache();
+
+ return 0;
+}
diff --git a/src/llvm-project/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py b/src/llvm-project/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py
new file mode 100755
index 0000000..771da5d
--- /dev/null
+++ b/src/llvm-project/clang/lib/Tooling/DumpTool/generate_cxx_src_locs.py
@@ -0,0 +1,411 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import json
+import filecmp
+import shutil
+import argparse
+
+class Generator(object):
+
+ implementationContent = ''
+
+ RefClades = {"DeclarationNameInfo",
+ "NestedNameSpecifierLoc",
+ "TemplateArgumentLoc",
+ "TypeLoc"}
+
+ def __init__(self, templateClasses):
+ self.templateClasses = templateClasses
+
+ def GeneratePrologue(self):
+
+ self.implementationContent += \
+ """
+/*===- Generated file -------------------------------------------*- C++ -*-===*\
+|* *|
+|* Introspection of available AST node SourceLocations *|
+|* *|
+|* Automatically generated file, do not edit! *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+namespace clang {
+namespace tooling {
+
+using LocationAndString = SourceLocationMap::value_type;
+using RangeAndString = SourceRangeMap::value_type;
+
+bool NodeIntrospection::hasIntrospectionSupport() { return true; }
+
+struct RecursionPopper
+{
+ RecursionPopper(std::vector<clang::TypeLoc> &TypeLocRecursionGuard)
+ : TLRG(TypeLocRecursionGuard)
+ {
+
+ }
+
+ ~RecursionPopper()
+ {
+ TLRG.pop_back();
+ }
+
+private:
+std::vector<clang::TypeLoc> &TLRG;
+};
+"""
+
+ def GenerateBaseGetLocationsDeclaration(self, CladeName):
+ InstanceDecoration = "*"
+ if CladeName in self.RefClades:
+ InstanceDecoration = "&"
+
+ self.implementationContent += \
+ """
+void GetLocationsImpl(SharedLocationCall const& Prefix,
+ clang::{0} const {1}Object, SourceLocationMap &Locs,
+ SourceRangeMap &Rngs,
+ std::vector<clang::TypeLoc> &TypeLocRecursionGuard);
+""".format(CladeName, InstanceDecoration)
+
+ def GenerateSrcLocMethod(self,
+ ClassName, ClassData, CreateLocalRecursionGuard):
+
+ NormalClassName = ClassName
+ RecursionGuardParam = ('' if CreateLocalRecursionGuard else \
+ ', std::vector<clang::TypeLoc>& TypeLocRecursionGuard')
+
+ if "templateParms" in ClassData:
+ TemplatePreamble = "template <typename "
+ ClassName += "<"
+ First = True
+ for TA in ClassData["templateParms"]:
+ if not First:
+ ClassName += ", "
+ TemplatePreamble += ", typename "
+
+ First = False
+ ClassName += TA
+ TemplatePreamble += TA
+
+ ClassName += ">"
+ TemplatePreamble += ">\n";
+ self.implementationContent += TemplatePreamble
+
+ self.implementationContent += \
+ """
+static void GetLocations{0}(SharedLocationCall const& Prefix,
+ clang::{1} const &Object,
+ SourceLocationMap &Locs, SourceRangeMap &Rngs {2})
+{{
+""".format(NormalClassName, ClassName, RecursionGuardParam)
+
+ if 'sourceLocations' in ClassData:
+ for locName in ClassData['sourceLocations']:
+ self.implementationContent += \
+ """
+ Locs.insert(LocationAndString(Object.{0}(),
+ llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}")));
+""".format(locName)
+
+ self.implementationContent += '\n'
+
+ if 'sourceRanges' in ClassData:
+ for rngName in ClassData['sourceRanges']:
+ self.implementationContent += \
+ """
+ Rngs.insert(RangeAndString(Object.{0}(),
+ llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}")));
+""".format(rngName)
+
+ self.implementationContent += '\n'
+
+ if 'typeLocs' in ClassData or 'typeSourceInfos' in ClassData \
+ or 'nestedNameLocs' in ClassData \
+ or 'declNameInfos' in ClassData:
+ if CreateLocalRecursionGuard:
+ self.implementationContent += \
+ 'std::vector<clang::TypeLoc> TypeLocRecursionGuard;\n'
+
+ self.implementationContent += '\n'
+
+ if 'typeLocs' in ClassData:
+ for typeLoc in ClassData['typeLocs']:
+
+ self.implementationContent += \
+ """
+ if (Object.{0}()) {{
+ GetLocationsImpl(
+ llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
+ Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
+ }}
+ """.format(typeLoc)
+
+ self.implementationContent += '\n'
+ if 'typeSourceInfos' in ClassData:
+ for tsi in ClassData['typeSourceInfos']:
+ self.implementationContent += \
+ """
+ if (Object.{0}()) {{
+ GetLocationsImpl(llvm::makeIntrusiveRefCnt<LocationCall>(
+ llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}",
+ LocationCall::ReturnsPointer), "getTypeLoc"),
+ Object.{0}()->getTypeLoc(), Locs, Rngs, TypeLocRecursionGuard);
+ }}
+ """.format(tsi)
+
+ self.implementationContent += '\n'
+
+ if 'nestedNameLocs' in ClassData:
+ for NN in ClassData['nestedNameLocs']:
+ self.implementationContent += \
+ """
+ if (Object.{0}())
+ GetLocationsImpl(
+ llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
+ Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
+ """.format(NN)
+
+ if 'declNameInfos' in ClassData:
+ for declName in ClassData['declNameInfos']:
+
+ self.implementationContent += \
+ """
+ GetLocationsImpl(
+ llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
+ Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
+ """.format(declName)
+
+ self.implementationContent += '}\n'
+
+ def GenerateFiles(self, OutputFile):
+ with open(os.path.join(os.getcwd(),
+ OutputFile), 'w') as f:
+ f.write(self.implementationContent)
+
+ def GenerateBaseGetLocationsFunction(self, ASTClassNames,
+ ClassEntries, CladeName, InheritanceMap,
+ CreateLocalRecursionGuard):
+
+ MethodReturnType = 'NodeLocationAccessors'
+ InstanceDecoration = "*"
+ if CladeName in self.RefClades:
+ InstanceDecoration = "&"
+
+ Signature = \
+ 'GetLocations(clang::{0} const {1}Object)'.format(
+ CladeName, InstanceDecoration)
+ ImplSignature = \
+ """
+ GetLocationsImpl(SharedLocationCall const& Prefix,
+ clang::{0} const {1}Object, SourceLocationMap &Locs,
+ SourceRangeMap &Rngs,
+ std::vector<clang::TypeLoc> &TypeLocRecursionGuard)
+ """.format(CladeName, InstanceDecoration)
+
+ self.implementationContent += 'void {0} {{ '.format(ImplSignature)
+
+ if CladeName == "TypeLoc":
+ self.implementationContent += 'if (Object.isNull()) return;'
+
+ self.implementationContent += \
+ """
+ if (llvm::find(TypeLocRecursionGuard, Object) != TypeLocRecursionGuard.end())
+ return;
+ TypeLocRecursionGuard.push_back(Object);
+ RecursionPopper RAII(TypeLocRecursionGuard);
+ """
+
+ RecursionGuardParam = ''
+ if not CreateLocalRecursionGuard:
+ RecursionGuardParam = ', TypeLocRecursionGuard'
+
+ ArgPrefix = '*'
+ if CladeName in self.RefClades:
+ ArgPrefix = ''
+ self.implementationContent += \
+ 'GetLocations{0}(Prefix, {1}Object, Locs, Rngs {2});'.format(
+ CladeName, ArgPrefix, RecursionGuardParam)
+
+ if CladeName == "TypeLoc":
+ self.implementationContent += \
+ '''
+ if (auto QTL = Object.getAs<clang::QualifiedTypeLoc>()) {
+ auto Dequalified = QTL.getNextTypeLoc();
+ return GetLocationsImpl(llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "getNextTypeLoc"),
+ Dequalified,
+ Locs,
+ Rngs,
+ TypeLocRecursionGuard);
+ }'''
+
+ for ASTClassName in ASTClassNames:
+ if ASTClassName in self.templateClasses:
+ continue
+ if ASTClassName == CladeName:
+ continue
+ if CladeName != "TypeLoc":
+ self.implementationContent += \
+ """
+if (auto Derived = llvm::dyn_cast<clang::{0}>(Object)) {{
+ GetLocations{0}(Prefix, *Derived, Locs, Rngs {1});
+}}
+""".format(ASTClassName, RecursionGuardParam)
+ continue
+
+ self.GenerateBaseTypeLocVisit(ASTClassName, ClassEntries,
+ RecursionGuardParam, InheritanceMap)
+
+ self.implementationContent += '}'
+
+ self.implementationContent += \
+ """
+{0} NodeIntrospection::{1} {{
+ NodeLocationAccessors Result;
+ SharedLocationCall Prefix;
+ std::vector<clang::TypeLoc> TypeLocRecursionGuard;
+
+ GetLocationsImpl(Prefix, Object, Result.LocationAccessors,
+ Result.RangeAccessors, TypeLocRecursionGuard);
+""".format(MethodReturnType, Signature)
+
+ self.implementationContent += 'return Result; }'
+
+ def GenerateBaseTypeLocVisit(self, ASTClassName, ClassEntries,
+ RecursionGuardParam, InheritanceMap):
+ CallPrefix = 'Prefix'
+ if ASTClassName != 'TypeLoc':
+ CallPrefix = \
+ '''llvm::makeIntrusiveRefCnt<LocationCall>(Prefix,
+ "getAs<clang::{0}>", LocationCall::IsCast)
+ '''.format(ASTClassName)
+
+ if ASTClassName in ClassEntries:
+
+ self.implementationContent += \
+ """
+ if (auto ConcreteTL = Object.getAs<clang::{0}>())
+ GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3});
+ """.format(ASTClassName, ASTClassName,
+ CallPrefix, RecursionGuardParam)
+
+ if ASTClassName in InheritanceMap:
+ for baseTemplate in self.templateClasses:
+ if baseTemplate in InheritanceMap[ASTClassName]:
+ self.implementationContent += \
+ """
+ if (auto ConcreteTL = Object.getAs<clang::{0}>())
+ GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3});
+ """.format(InheritanceMap[ASTClassName], baseTemplate,
+ CallPrefix, RecursionGuardParam)
+
+
+ def GenerateDynNodeVisitor(self, CladeNames):
+ MethodReturnType = 'NodeLocationAccessors'
+
+ Signature = \
+ 'GetLocations(clang::DynTypedNode const &Node)'
+
+ self.implementationContent += MethodReturnType \
+ + ' NodeIntrospection::' + Signature + '{'
+
+ for CladeName in CladeNames:
+ if CladeName == "DeclarationNameInfo":
+ continue
+ self.implementationContent += \
+ """
+ if (const auto *N = Node.get<{0}>())
+ """.format(CladeName)
+ ArgPrefix = ""
+ if CladeName in self.RefClades:
+ ArgPrefix = "*"
+ self.implementationContent += \
+ """
+ return GetLocations({0}const_cast<{1} *>(N));""".format(ArgPrefix, CladeName)
+
+ self.implementationContent += '\nreturn {}; }'
+
+ def GenerateEpilogue(self):
+
+ self.implementationContent += '''
+ }
+}
+'''
+
+def main():
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--json-input-path',
+ help='Read API description from FILE', metavar='FILE')
+ parser.add_argument('--output-file', help='Generate output in FILEPATH',
+ metavar='FILEPATH')
+ parser.add_argument('--use-empty-implementation',
+ help='Generate empty implementation',
+ action="store", type=int)
+ parser.add_argument('--empty-implementation',
+ help='Copy empty implementation from FILEPATH',
+ action="store", metavar='FILEPATH')
+
+ options = parser.parse_args()
+
+ use_empty_implementation = options.use_empty_implementation
+
+ if (not use_empty_implementation
+ and not os.path.exists(options.json_input_path)):
+ use_empty_implementation = True
+
+ if not use_empty_implementation:
+ with open(options.json_input_path) as f:
+ jsonData = json.load(f)
+
+ if not 'classesInClade' in jsonData or not jsonData["classesInClade"]:
+ use_empty_implementation = True
+
+ if use_empty_implementation:
+ if not os.path.exists(options.output_file) or \
+ not filecmp.cmp(options.empty_implementation, options.output_file):
+ shutil.copyfile(options.empty_implementation, options.output_file)
+ sys.exit(0)
+
+ templateClasses = []
+ for (ClassName, ClassAccessors) in jsonData['classEntries'].items():
+ if "templateParms" in ClassAccessors:
+ templateClasses.append(ClassName)
+
+ g = Generator(templateClasses)
+
+ g.GeneratePrologue()
+
+ for (CladeName, ClassNameData) in jsonData['classesInClade'].items():
+ g.GenerateBaseGetLocationsDeclaration(CladeName)
+
+ def getCladeName(ClassName):
+ for (CladeName, ClassNameData) in jsonData['classesInClade'].items():
+ if ClassName in ClassNameData:
+ return CladeName
+
+ for (ClassName, ClassAccessors) in jsonData['classEntries'].items():
+ cladeName = getCladeName(ClassName)
+ g.GenerateSrcLocMethod(
+ ClassName, ClassAccessors,
+ cladeName not in Generator.RefClades)
+
+ for (CladeName, ClassNameData) in jsonData['classesInClade'].items():
+ g.GenerateBaseGetLocationsFunction(
+ ClassNameData,
+ jsonData['classEntries'],
+ CladeName,
+ jsonData["classInheritance"],
+ CladeName not in Generator.RefClades)
+
+ g.GenerateDynNodeVisitor(jsonData['classesInClade'].keys())
+
+ g.GenerateEpilogue()
+
+ g.GenerateFiles(options.output_file)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/llvm-project/clang/lib/Tooling/EmptyNodeIntrospection.inc.in b/src/llvm-project/clang/lib/Tooling/EmptyNodeIntrospection.inc.in
new file mode 100644
index 0000000..2071c34
--- /dev/null
+++ b/src/llvm-project/clang/lib/Tooling/EmptyNodeIntrospection.inc.in
@@ -0,0 +1,48 @@
+//===- EmptyNodeIntrospection.inc.in --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+namespace tooling {
+bool NodeIntrospection::hasIntrospectionSupport() { return false; }
+
+NodeLocationAccessors NodeIntrospection::GetLocations(clang::Stmt const *) {
+ return {};
+}
+NodeLocationAccessors NodeIntrospection::GetLocations(clang::Decl const *) {
+ return {};
+}
+NodeLocationAccessors NodeIntrospection::GetLocations(
+ clang::CXXCtorInitializer const *) {
+ return {};
+}
+NodeLocationAccessors NodeIntrospection::GetLocations(
+ clang::NestedNameSpecifierLoc const&) {
+ return {};
+}
+NodeLocationAccessors NodeIntrospection::GetLocations(
+ clang::TemplateArgumentLoc const&) {
+ return {};
+}
+NodeLocationAccessors NodeIntrospection::GetLocations(
+ clang::CXXBaseSpecifier const*) {
+ return {};
+}
+NodeLocationAccessors NodeIntrospection::GetLocations(
+ clang::TypeLoc const&) {
+ return {};
+}
+NodeLocationAccessors NodeIntrospection::GetLocations(
+ clang::DeclarationNameInfo const&) {
+ return {};
+}
+NodeLocationAccessors
+NodeIntrospection::GetLocations(clang::DynTypedNode const &) {
+ return {};
+}
+} // namespace tooling
+} // namespace clang
diff --git a/src/llvm-project/clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp b/src/llvm-project/clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
index f1ab2ae..29787b8 100644
--- a/src/llvm-project/clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
+++ b/src/llvm-project/clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
@@ -54,14 +54,15 @@
Argv.reserve(Cmd.CommandLine.size());
for (auto &Arg : Cmd.CommandLine) {
Argv.push_back(Arg.c_str());
- SeenRSPFile |= Arg.front() == '@';
+ if (!Arg.empty())
+ SeenRSPFile |= Arg.front() == '@';
}
if (!SeenRSPFile)
continue;
llvm::BumpPtrAllocator Alloc;
llvm::StringSaver Saver(Alloc);
- llvm::cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false, *FS,
- llvm::StringRef(Cmd.Directory));
+ llvm::cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false,
+ llvm::StringRef(Cmd.Directory), *FS);
// Don't assign directly, Argv aliases CommandLine.
std::vector<std::string> ExpandedArgv(Argv.begin(), Argv.end());
Cmd.CommandLine = std::move(ExpandedArgv);
diff --git a/src/llvm-project/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/src/llvm-project/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
index d1f9846..fbceb26 100644
--- a/src/llvm-project/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -252,9 +252,9 @@
// 1) foo.h => bar.cc
// 2) foo.proto.h => foo.cc
StringRef Matching;
- if (MatchingFileStem.startswith_lower(HeaderStem))
+ if (MatchingFileStem.startswith_insensitive(HeaderStem))
Matching = MatchingFileStem; // example 1), 2)
- else if (FileStem.equals_lower(HeaderStem))
+ else if (FileStem.equals_insensitive(HeaderStem))
Matching = FileStem; // example 3)
if (!Matching.empty()) {
llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
diff --git a/src/llvm-project/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp b/src/llvm-project/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
index fa61560..c1e25c4 100644
--- a/src/llvm-project/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
+++ b/src/llvm-project/clang/lib/Tooling/InterpolatingCompilationDatabase.cpp
@@ -43,9 +43,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/LangStandard.h"
+#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Types.h"
#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringExtras.h"
@@ -134,8 +136,7 @@
bool ClangCLMode;
TransferableCommand(CompileCommand C)
- : Cmd(std::move(C)), Type(guessType(Cmd.Filename)),
- ClangCLMode(checkIsCLMode(Cmd.CommandLine)) {
+ : Cmd(std::move(C)), Type(guessType(Cmd.Filename)) {
std::vector<std::string> OldArgs = std::move(Cmd.CommandLine);
Cmd.CommandLine.clear();
@@ -145,6 +146,9 @@
SmallVector<const char *, 16> TmpArgv;
for (const std::string &S : OldArgs)
TmpArgv.push_back(S.c_str());
+ ClangCLMode = !TmpArgv.empty() &&
+ driver::IsClangCL(driver::getDriverMode(
+ TmpArgv.front(), llvm::makeArrayRef(TmpArgv).slice(1)));
ArgList = {TmpArgv.begin(), TmpArgv.end()};
}
@@ -177,6 +181,10 @@
Opt.matches(OPT__SLASH_Fo))))
continue;
+ // ...including when the inputs are passed after --.
+ if (Opt.matches(OPT__DASH_DASH))
+ break;
+
// Strip -x, but record the overridden language.
if (const auto GivenType = tryParseTypeArg(*Arg)) {
Type = *GivenType;
@@ -204,8 +212,10 @@
}
// Produce a CompileCommand for \p filename, based on this one.
- CompileCommand transferTo(StringRef Filename) const {
- CompileCommand Result = Cmd;
+ // (This consumes the TransferableCommand just to avoid copying Cmd).
+ CompileCommand transferTo(StringRef Filename) && {
+ CompileCommand Result = std::move(Cmd);
+ Result.Heuristic = "inferred from " + Result.Filename;
Result.Filename = std::string(Filename);
bool TypeCertain;
auto TargetType = guessType(Filename, &TypeCertain);
@@ -233,25 +243,13 @@
llvm::Twine(ClangCLMode ? "/std:" : "-std=") +
LangStandard::getLangStandardForKind(Std).getName()).str());
}
+ if (Filename.startswith("-") || (ClangCLMode && Filename.startswith("/")))
+ Result.CommandLine.push_back("--");
Result.CommandLine.push_back(std::string(Filename));
- Result.Heuristic = "inferred from " + Cmd.Filename;
return Result;
}
private:
- // Determine whether the given command line is intended for the CL driver.
- static bool checkIsCLMode(ArrayRef<std::string> CmdLine) {
- // First look for --driver-mode.
- for (StringRef S : llvm::reverse(CmdLine)) {
- if (S.consume_front("--driver-mode="))
- return S == "cl";
- }
-
- // Otherwise just check the clang executable file name.
- return !CmdLine.empty() &&
- llvm::sys::path::stem(CmdLine.front()).endswith_lower("cl");
- }
-
// Map the language from the --std flag to that of the -x flag.
static types::ID toType(Language Lang) {
switch (Lang) {
@@ -521,7 +519,7 @@
Inner->getCompileCommands(Index.chooseProxy(Filename, foldType(Lang)));
if (ProxyCommands.empty())
return {};
- return {TransferableCommand(ProxyCommands[0]).transferTo(Filename)};
+ return {transferCompileCommand(std::move(ProxyCommands.front()), Filename)};
}
std::vector<std::string> getAllFiles() const override {
@@ -544,5 +542,10 @@
return std::make_unique<InterpolatingCompilationDatabase>(std::move(Inner));
}
+tooling::CompileCommand transferCompileCommand(CompileCommand Cmd,
+ StringRef Filename) {
+ return TransferableCommand(std::move(Cmd)).transferTo(Filename);
+}
+
} // namespace tooling
} // namespace clang
diff --git a/src/llvm-project/clang/lib/Tooling/JSONCompilationDatabase.cpp b/src/llvm-project/clang/lib/Tooling/JSONCompilationDatabase.cpp
index 2d8847a..97ba7e4 100644
--- a/src/llvm-project/clang/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/src/llvm-project/clang/lib/Tooling/JSONCompilationDatabase.cpp
@@ -198,7 +198,7 @@
JSONCommandLineSyntax Syntax) {
// Don't mmap: if we're a long-lived process, the build system may overwrite.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> DatabaseBuffer =
- llvm::MemoryBuffer::getFile(FilePath, /*FileSize=*/-1,
+ llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/false,
/*RequiresNullTerminator=*/true,
/*IsVolatile=*/true);
if (std::error_code Result = DatabaseBuffer.getError()) {
diff --git a/src/llvm-project/clang/lib/Tooling/NodeIntrospection.cpp b/src/llvm-project/clang/lib/Tooling/NodeIntrospection.cpp
new file mode 100644
index 0000000..f01bb1c
--- /dev/null
+++ b/src/llvm-project/clang/lib/Tooling/NodeIntrospection.cpp
@@ -0,0 +1,88 @@
+//===- NodeIntrospection.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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the implementation of the NodeIntrospection.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/NodeIntrospection.h"
+
+#include "clang/AST/AST.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+namespace tooling {
+
+void LocationCallFormatterCpp::print(const LocationCall &Call,
+ llvm::raw_ostream &OS) {
+ if (const LocationCall *On = Call.on()) {
+ print(*On, OS);
+ if (On->returnsPointer())
+ OS << "->";
+ else
+ OS << '.';
+ }
+
+ OS << Call.name() << "()";
+}
+
+std::string LocationCallFormatterCpp::format(const LocationCall &Call) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ print(Call, OS);
+ OS.flush();
+ return Result;
+}
+
+namespace internal {
+
+static bool locationCallLessThan(const LocationCall *LHS,
+ const LocationCall *RHS) {
+ if (!LHS && !RHS)
+ return false;
+ if (LHS && !RHS)
+ return true;
+ if (!LHS && RHS)
+ return false;
+ auto compareResult = LHS->name().compare(RHS->name());
+ if (compareResult < 0)
+ return true;
+ if (compareResult > 0)
+ return false;
+ return locationCallLessThan(LHS->on(), RHS->on());
+}
+
+bool RangeLessThan::operator()(
+ std::pair<SourceRange, SharedLocationCall> const &LHS,
+ std::pair<SourceRange, SharedLocationCall> const &RHS) const {
+ if (LHS.first.getBegin() < RHS.first.getBegin())
+ return true;
+ else if (LHS.first.getBegin() != RHS.first.getBegin())
+ return false;
+
+ if (LHS.first.getEnd() < RHS.first.getEnd())
+ return true;
+ else if (LHS.first.getEnd() != RHS.first.getEnd())
+ return false;
+
+ return locationCallLessThan(LHS.second.get(), RHS.second.get());
+}
+bool RangeLessThan::operator()(
+ std::pair<SourceLocation, SharedLocationCall> const &LHS,
+ std::pair<SourceLocation, SharedLocationCall> const &RHS) const {
+ if (LHS.first == RHS.first)
+ return locationCallLessThan(LHS.second.get(), RHS.second.get());
+ return LHS.first < RHS.first;
+}
+} // namespace internal
+
+} // namespace tooling
+} // namespace clang
+
+#include "clang/Tooling/NodeIntrospection.inc"
diff --git a/src/llvm-project/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/src/llvm-project/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
index 6a08c7f..aecfffc 100644
--- a/src/llvm-project/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
@@ -226,6 +226,24 @@
return true;
}
+ bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) {
+ for (const DesignatedInitExpr::Designator &D : E->designators()) {
+ if (D.isFieldDesignator() && D.getField()) {
+ const FieldDecl *Decl = D.getField();
+ if (isInUSRSet(Decl)) {
+ auto StartLoc = D.getFieldLoc();
+ auto EndLoc = D.getFieldLoc();
+ RenameInfos.push_back({StartLoc, EndLoc,
+ /*FromDecl=*/nullptr,
+ /*Context=*/nullptr,
+ /*Specifier=*/nullptr,
+ /*IgnorePrefixQualifiers=*/true});
+ }
+ }
+ }
+ return true;
+ }
+
bool VisitCXXConstructorDecl(const CXXConstructorDecl *CD) {
// Fix the constructor initializer when renaming class members.
for (const auto *Initializer : CD->inits()) {
diff --git a/src/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp b/src/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp
index 7654e3d..07888b5 100644
--- a/src/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -294,11 +294,12 @@
SourceRange Initializer) {
SourceLocation Start = GetStartLoc().Visit(T);
SourceLocation End = T.getEndLoc();
- assert(End.isValid());
if (Name.isValid()) {
if (Start.isInvalid())
Start = Name;
- if (SM.isBeforeInTranslationUnit(End, Name))
+ // End of TypeLoc could be invalid if the type is invalid, fallback to the
+ // NameLoc.
+ if (End.isInvalid() || SM.isBeforeInTranslationUnit(End, Name))
End = Name;
}
if (Initializer.isValid()) {
@@ -800,6 +801,30 @@
return true;
}
+ bool TraverseIfStmt(IfStmt *S) {
+ bool Result = [&, this]() {
+ if (S->getInit() && !TraverseStmt(S->getInit())) {
+ return false;
+ }
+ // In cases where the condition is an initialized declaration in a
+ // statement, we want to preserve the declaration and ignore the
+ // implicit condition expression in the syntax tree.
+ if (S->hasVarStorage()) {
+ if (!TraverseStmt(S->getConditionVariableDeclStmt()))
+ return false;
+ } else if (S->getCond() && !TraverseStmt(S->getCond()))
+ return false;
+
+ if (S->getThen() && !TraverseStmt(S->getThen()))
+ return false;
+ if (S->getElse() && !TraverseStmt(S->getElse()))
+ return false;
+ return true;
+ }();
+ WalkUpFromIfStmt(S);
+ return Result;
+ }
+
bool TraverseCXXForRangeStmt(CXXForRangeStmt *S) {
// We override to traverse range initializer as VarDecl.
// RAV traverses it as a statement, we produce invalid node kinds in that
@@ -831,6 +856,11 @@
return RecursiveASTVisitor::TraverseStmt(S);
}
+ bool TraverseOpaqueValueExpr(OpaqueValueExpr *VE) {
+ // OpaqueValue doesn't correspond to concrete syntax, ignore it.
+ return true;
+ }
+
// Some expressions are not yet handled by syntax trees.
bool WalkUpFromExpr(Expr *E) {
assert(!isImplicitExpr(E) && "should be handled by TraverseStmt");
@@ -1426,6 +1456,10 @@
bool WalkUpFromIfStmt(IfStmt *S) {
Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword);
+ Stmt *ConditionStatement = S->getCond();
+ if (S->hasVarStorage())
+ ConditionStatement = S->getConditionVariableDeclStmt();
+ Builder.markStmtChild(ConditionStatement, syntax::NodeRole::Condition);
Builder.markStmtChild(S->getThen(), syntax::NodeRole::ThenStatement);
Builder.markChildToken(S->getElseLoc(), syntax::NodeRole::ElseKeyword);
Builder.markStmtChild(S->getElse(), syntax::NodeRole::ElseStatement);
diff --git a/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp b/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp
index 234df9cb..8a31e77 100644
--- a/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Syntax/Tokens.cpp
@@ -183,7 +183,39 @@
return Text.substr(Begin, length());
}
+void TokenBuffer::indexExpandedTokens() {
+ // No-op if the index is already created.
+ if (!ExpandedTokIndex.empty())
+ return;
+ ExpandedTokIndex.reserve(ExpandedTokens.size());
+ // Index ExpandedTokens for faster lookups by SourceLocation.
+ for (size_t I = 0, E = ExpandedTokens.size(); I != E; ++I) {
+ SourceLocation Loc = ExpandedTokens[I].location();
+ if (Loc.isValid())
+ ExpandedTokIndex[Loc] = I;
+ }
+}
+
llvm::ArrayRef<syntax::Token> TokenBuffer::expandedTokens(SourceRange R) const {
+ if (R.isInvalid())
+ return {};
+ if (!ExpandedTokIndex.empty()) {
+ // Quick lookup if `R` is a token range.
+ // This is a huge win since majority of the users use ranges provided by an
+ // AST. Ranges in AST are token ranges from expanded token stream.
+ const auto B = ExpandedTokIndex.find(R.getBegin());
+ const auto E = ExpandedTokIndex.find(R.getEnd());
+ if (B != ExpandedTokIndex.end() && E != ExpandedTokIndex.end()) {
+ const Token *L = ExpandedTokens.data() + B->getSecond();
+ // Add 1 to End to make a half-open range.
+ const Token *R = ExpandedTokens.data() + E->getSecond() + 1;
+ if (L > R)
+ return {};
+ return {L, R};
+ }
+ }
+ // Slow case. Use `isBeforeInTranslationUnit` to binary search for the
+ // required range.
return getTokensCovering(expandedTokens(), R, *SourceMgr);
}
diff --git a/src/llvm-project/clang/lib/Tooling/Tooling.cpp b/src/llvm-project/clang/lib/Tooling/Tooling.cpp
index 79851ac..5242134 100644
--- a/src/llvm-project/clang/lib/Tooling/Tooling.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Tooling.cpp
@@ -83,16 +83,20 @@
return CompilerDriver;
}
-/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
-///
-/// Returns nullptr on error.
-static const llvm::opt::ArgStringList *getCC1Arguments(
- DiagnosticsEngine *Diagnostics, driver::Compilation *Compilation) {
- // We expect to get back exactly one Command job, if we didn't something
- // failed. Extract that job from the Compilation.
+/// Decide whether extra compiler frontend commands can be ignored.
+static bool ignoreExtraCC1Commands(const driver::Compilation *Compilation) {
const driver::JobList &Jobs = Compilation->getJobs();
const driver::ActionList &Actions = Compilation->getActions();
+
bool OffloadCompilation = false;
+
+ // Jobs and Actions look very different depending on whether the Clang tool
+ // injected -fsyntax-only or not. Try to handle both cases here.
+
+ for (const auto &Job : Jobs)
+ if (StringRef(Job.getExecutable()) == "clang-offload-bundler")
+ OffloadCompilation = true;
+
if (Jobs.size() > 1) {
for (auto A : Actions){
// On MacOSX real actions may end up being wrapped in BindArchAction
@@ -117,8 +121,33 @@
}
}
}
- if (Jobs.size() == 0 || !isa<driver::Command>(*Jobs.begin()) ||
- (Jobs.size() > 1 && !OffloadCompilation)) {
+
+ return OffloadCompilation;
+}
+
+namespace clang {
+namespace tooling {
+
+const llvm::opt::ArgStringList *
+getCC1Arguments(DiagnosticsEngine *Diagnostics,
+ driver::Compilation *Compilation) {
+ const driver::JobList &Jobs = Compilation->getJobs();
+
+ auto IsCC1Command = [](const driver::Command &Cmd) {
+ return StringRef(Cmd.getCreator().getName()) == "clang";
+ };
+
+ auto IsSrcFile = [](const driver::InputInfo &II) {
+ return isSrcFile(II.getType());
+ };
+
+ llvm::SmallVector<const driver::Command *, 1> CC1Jobs;
+ for (const driver::Command &Job : Jobs)
+ if (IsCC1Command(Job) && llvm::all_of(Job.getInputInfos(), IsSrcFile))
+ CC1Jobs.push_back(&Job);
+
+ if (CC1Jobs.empty() ||
+ (CC1Jobs.size() > 1 && !ignoreExtraCC1Commands(Compilation))) {
SmallString<256> error_msg;
llvm::raw_svector_ostream error_stream(error_msg);
Jobs.Print(error_stream, "; ", true);
@@ -127,19 +156,9 @@
return nullptr;
}
- // The one job we find should be to invoke clang again.
- const auto &Cmd = cast<driver::Command>(*Jobs.begin());
- if (StringRef(Cmd.getCreator().getName()) != "clang") {
- Diagnostics->Report(diag::err_fe_expected_clang_command);
- return nullptr;
- }
-
- return &Cmd.getArguments();
+ return &CC1Jobs[0]->getArguments();
}
-namespace clang {
-namespace tooling {
-
/// Returns a clang build invocation initialized from the CC1 flags.
CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
const llvm::opt::ArgStringList &CC1Args,
@@ -334,6 +353,10 @@
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
+ // Although `Diagnostics` are used only for command-line parsing, the custom
+ // `DiagConsumer` might expect a `SourceManager` to be present.
+ SourceManager SrcMgr(Diagnostics, *Files);
+ Diagnostics.setSourceManager(&SrcMgr);
const std::unique_ptr<driver::Driver> Driver(
newDriver(&Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
@@ -440,8 +463,9 @@
return;
// If there's no override in place add our resource dir.
- Args.push_back("-resource-dir=" +
- CompilerInvocation::GetResourcesPath(Argv0, MainAddr));
+ Args = getInsertArgumentAdjuster(
+ ("-resource-dir=" + CompilerInvocation::GetResourcesPath(Argv0, MainAddr))
+ .c_str())(Args, "");
}
int ClangTool::run(ToolAction *Action) {
diff --git a/src/llvm-project/clang/lib/Tooling/Transformer/RangeSelector.cpp b/src/llvm-project/clang/lib/Tooling/Transformer/RangeSelector.cpp
index 0f3138d..753e89e 100644
--- a/src/llvm-project/clang/lib/Tooling/Transformer/RangeSelector.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Transformer/RangeSelector.cpp
@@ -8,6 +8,7 @@
#include "clang/Tooling/Transformer/RangeSelector.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
@@ -228,8 +229,16 @@
SourceLocation L = I->getMemberLocation();
return CharSourceRange::getTokenRange(L, L);
}
+ if (const auto *T = Node.get<TypeLoc>()) {
+ TypeLoc Loc = *T;
+ auto ET = Loc.getAs<ElaboratedTypeLoc>();
+ if (!ET.isNull()) {
+ Loc = ET.getNamedTypeLoc();
+ }
+ return CharSourceRange::getTokenRange(Loc.getSourceRange());
+ }
return typeError(ID, Node.getNodeKind(),
- "DeclRefExpr, NamedDecl, CXXCtorInitializer");
+ "DeclRefExpr, NamedDecl, CXXCtorInitializer, TypeLoc");
};
}
diff --git a/src/llvm-project/clang/lib/Tooling/Transformer/SourceCodeBuilders.cpp b/src/llvm-project/clang/lib/Tooling/Transformer/SourceCodeBuilders.cpp
index 56ec45e..a1c99b6 100644
--- a/src/llvm-project/clang/lib/Tooling/Transformer/SourceCodeBuilders.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Transformer/SourceCodeBuilders.cpp
@@ -93,6 +93,8 @@
llvm::Optional<std::string> tooling::buildAddressOf(const Expr &E,
const ASTContext &Context) {
+ if (E.isImplicitCXXThis())
+ return std::string("this");
if (const auto *Op = dyn_cast<UnaryOperator>(&E))
if (Op->getOpcode() == UO_Deref) {
// Strip leading '*'.
diff --git a/src/llvm-project/clang/lib/Tooling/Transformer/Stencil.cpp b/src/llvm-project/clang/lib/Tooling/Transformer/Stencil.cpp
index d46087e..4dc3544 100644
--- a/src/llvm-project/clang/lib/Tooling/Transformer/Stencil.cpp
+++ b/src/llvm-project/clang/lib/Tooling/Transformer/Stencil.cpp
@@ -43,141 +43,6 @@
return It->second;
}
-namespace {
-// An arbitrary fragment of code within a stencil.
-struct RawTextData {
- explicit RawTextData(std::string T) : Text(std::move(T)) {}
- std::string Text;
-};
-
-// A debugging operation to dump the AST for a particular (bound) AST node.
-struct DebugPrintNodeData {
- explicit DebugPrintNodeData(std::string S) : Id(std::move(S)) {}
- std::string Id;
-};
-
-// Operators that take a single node Id as an argument.
-enum class UnaryNodeOperator {
- Parens,
- Deref,
- MaybeDeref,
- AddressOf,
- MaybeAddressOf,
- Describe,
-};
-
-// Generic container for stencil operations with a (single) node-id argument.
-struct UnaryOperationData {
- UnaryOperationData(UnaryNodeOperator Op, std::string Id)
- : Op(Op), Id(std::move(Id)) {}
- UnaryNodeOperator Op;
- std::string Id;
-};
-
-// The fragment of code corresponding to the selected range.
-struct SelectorData {
- explicit SelectorData(RangeSelector S) : Selector(std::move(S)) {}
- RangeSelector Selector;
-};
-
-// A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
-struct AccessData {
- AccessData(StringRef BaseId, Stencil Member)
- : BaseId(std::string(BaseId)), Member(std::move(Member)) {}
- std::string BaseId;
- Stencil Member;
-};
-
-struct IfBoundData {
- IfBoundData(StringRef Id, Stencil TrueStencil, Stencil FalseStencil)
- : Id(std::string(Id)), TrueStencil(std::move(TrueStencil)),
- FalseStencil(std::move(FalseStencil)) {}
- std::string Id;
- Stencil TrueStencil;
- Stencil FalseStencil;
-};
-
-struct SequenceData {
- SequenceData(std::vector<Stencil> Stencils) : Stencils(std::move(Stencils)) {}
- std::vector<Stencil> Stencils;
-};
-
-std::string toStringData(const RawTextData &Data) {
- std::string Result;
- llvm::raw_string_ostream OS(Result);
- OS << "\"";
- OS.write_escaped(Data.Text);
- OS << "\"";
- OS.flush();
- return Result;
-}
-
-std::string toStringData(const DebugPrintNodeData &Data) {
- return (llvm::Twine("dPrint(\"") + Data.Id + "\")").str();
-}
-
-std::string toStringData(const UnaryOperationData &Data) {
- StringRef OpName;
- switch (Data.Op) {
- case UnaryNodeOperator::Parens:
- OpName = "expression";
- break;
- case UnaryNodeOperator::Deref:
- OpName = "deref";
- break;
- case UnaryNodeOperator::MaybeDeref:
- OpName = "maybeDeref";
- break;
- case UnaryNodeOperator::AddressOf:
- OpName = "addressOf";
- break;
- case UnaryNodeOperator::MaybeAddressOf:
- OpName = "maybeAddressOf";
- break;
- case UnaryNodeOperator::Describe:
- OpName = "describe";
- break;
- }
- return (OpName + "(\"" + Data.Id + "\")").str();
-}
-
-std::string toStringData(const SelectorData &) { return "selection(...)"; }
-
-std::string toStringData(const AccessData &Data) {
- return (llvm::Twine("access(\"") + Data.BaseId + "\", " +
- Data.Member->toString() + ")")
- .str();
-}
-
-std::string toStringData(const IfBoundData &Data) {
- return (llvm::Twine("ifBound(\"") + Data.Id + "\", " +
- Data.TrueStencil->toString() + ", " + Data.FalseStencil->toString() +
- ")")
- .str();
-}
-
-std::string toStringData(const MatchConsumer<std::string> &) {
- return "run(...)";
-}
-
-std::string toStringData(const SequenceData &Data) {
- llvm::SmallVector<std::string, 2> Parts;
- Parts.reserve(Data.Stencils.size());
- for (const auto &S : Data.Stencils)
- Parts.push_back(S->toString());
- return (llvm::Twine("seq(") + llvm::join(Parts, ", ") + ")").str();
-}
-
-// The `evalData()` overloads evaluate the given stencil data to a string, given
-// the match result, and append it to `Result`. We define an overload for each
-// type of stencil data.
-
-Error evalData(const RawTextData &Data, const MatchFinder::MatchResult &,
- std::string *Result) {
- Result->append(Data.Text);
- return Error::success();
-}
-
static Error printNode(StringRef Id, const MatchFinder::MatchResult &Match,
std::string *Result) {
std::string Output;
@@ -190,11 +55,6 @@
return Error::success();
}
-Error evalData(const DebugPrintNodeData &Data,
- const MatchFinder::MatchResult &Match, std::string *Result) {
- return printNode(Data.Id, Match, Result);
-}
-
// FIXME: Consider memoizing this function using the `ASTContext`.
static bool isSmartPointerType(QualType Ty, ASTContext &Context) {
using namespace ::clang::ast_matchers;
@@ -213,229 +73,402 @@
return match(SmartPointer, Ty, Context).size() > 0;
}
-Error evalData(const UnaryOperationData &Data,
- const MatchFinder::MatchResult &Match, std::string *Result) {
- // The `Describe` operation can be applied to any node, not just expressions,
- // so it is handled here, separately.
- if (Data.Op == UnaryNodeOperator::Describe)
- return printNode(Data.Id, Match, Result);
+// Identifies use of `operator*` on smart pointers, and returns the underlying
+// smart-pointer expression; otherwise, returns null.
+static const Expr *isSmartDereference(const Expr &E, ASTContext &Context) {
+ using namespace ::clang::ast_matchers;
- const auto *E = Match.Nodes.getNodeAs<Expr>(Data.Id);
- if (E == nullptr)
- return llvm::make_error<StringError>(
- errc::invalid_argument, "Id not bound or not Expr: " + Data.Id);
- llvm::Optional<std::string> Source;
- switch (Data.Op) {
- case UnaryNodeOperator::Parens:
- Source = tooling::buildParens(*E, *Match.Context);
- break;
- case UnaryNodeOperator::Deref:
- Source = tooling::buildDereference(*E, *Match.Context);
- break;
- case UnaryNodeOperator::MaybeDeref:
- if (E->getType()->isAnyPointerType() ||
- isSmartPointerType(E->getType(), *Match.Context)) {
- // Strip off any operator->. This can only occur inside an actual arrow
- // member access, so we treat it as equivalent to an actual object
- // expression.
- if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
- if (OpCall->getOperator() == clang::OO_Arrow &&
- OpCall->getNumArgs() == 1) {
- E = OpCall->getArg(0);
- }
- }
- Source = tooling::buildDereference(*E, *Match.Context);
- break;
- }
- *Result += tooling::getText(*E, *Match.Context);
- return Error::success();
- case UnaryNodeOperator::AddressOf:
- Source = tooling::buildAddressOf(*E, *Match.Context);
- break;
- case UnaryNodeOperator::MaybeAddressOf:
- if (E->getType()->isAnyPointerType() ||
- isSmartPointerType(E->getType(), *Match.Context)) {
- // Strip off any operator->. This can only occur inside an actual arrow
- // member access, so we treat it as equivalent to an actual object
- // expression.
- if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
- if (OpCall->getOperator() == clang::OO_Arrow &&
- OpCall->getNumArgs() == 1) {
- E = OpCall->getArg(0);
- }
- }
- *Result += tooling::getText(*E, *Match.Context);
- return Error::success();
- }
- Source = tooling::buildAddressOf(*E, *Match.Context);
- break;
- case UnaryNodeOperator::Describe:
- llvm_unreachable("This case is handled at the start of the function");
- }
- if (!Source)
- return llvm::make_error<StringError>(
- errc::invalid_argument,
- "Could not construct expression source from ID: " + Data.Id);
- *Result += *Source;
- return Error::success();
+ const auto HasOverloadedArrow = cxxRecordDecl(hasMethod(cxxMethodDecl(
+ hasOverloadedOperatorName("->"), returns(qualType(pointsTo(type()))))));
+ // Verify it is a smart pointer by finding `operator->` in the class
+ // declaration.
+ auto Deref = cxxOperatorCallExpr(
+ hasOverloadedOperatorName("*"), hasUnaryOperand(expr().bind("arg")),
+ callee(cxxMethodDecl(ofClass(HasOverloadedArrow))));
+ return selectFirst<Expr>("arg", match(Deref, E, Context));
}
-Error evalData(const SelectorData &Data, const MatchFinder::MatchResult &Match,
- std::string *Result) {
- auto RawRange = Data.Selector(Match);
- if (!RawRange)
- return RawRange.takeError();
- CharSourceRange Range = Lexer::makeFileCharRange(
- *RawRange, *Match.SourceManager, Match.Context->getLangOpts());
- if (Range.isInvalid()) {
- // Validate the original range to attempt to get a meaningful error message.
- // If it's valid, then something else is the cause and we just return the
- // generic failure message.
- if (auto Err = tooling::validateEditRange(*RawRange, *Match.SourceManager))
- return handleErrors(std::move(Err), [](std::unique_ptr<StringError> E) {
- assert(E->convertToErrorCode() ==
- llvm::make_error_code(errc::invalid_argument) &&
- "Validation errors must carry the invalid_argument code");
- return llvm::createStringError(
- errc::invalid_argument,
- "selected range could not be resolved to a valid source range; " +
- E->getMessage());
- });
- return llvm::createStringError(
- errc::invalid_argument,
- "selected range could not be resolved to a valid source range");
- }
- // Validate `Range`, because `makeFileCharRange` accepts some ranges that
- // `validateEditRange` rejects.
- if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager))
- return joinErrors(
- llvm::createStringError(errc::invalid_argument,
- "selected range is not valid for editing"),
- std::move(Err));
- *Result += tooling::getText(Range, *Match.Context);
- return Error::success();
-}
-
-Error evalData(const AccessData &Data, const MatchFinder::MatchResult &Match,
- std::string *Result) {
- const auto *E = Match.Nodes.getNodeAs<Expr>(Data.BaseId);
- if (E == nullptr)
- return llvm::make_error<StringError>(errc::invalid_argument,
- "Id not bound: " + Data.BaseId);
- if (!E->isImplicitCXXThis()) {
- if (llvm::Optional<std::string> S =
- E->getType()->isAnyPointerType()
- ? tooling::buildArrow(*E, *Match.Context)
- : tooling::buildDot(*E, *Match.Context))
- *Result += *S;
- else
- return llvm::make_error<StringError>(
- errc::invalid_argument,
- "Could not construct object text from ID: " + Data.BaseId);
- }
- return Data.Member->eval(Match, Result);
-}
-
-Error evalData(const IfBoundData &Data, const MatchFinder::MatchResult &Match,
- std::string *Result) {
- auto &M = Match.Nodes.getMap();
- return (M.find(Data.Id) != M.end() ? Data.TrueStencil : Data.FalseStencil)
- ->eval(Match, Result);
-}
-
-Error evalData(const MatchConsumer<std::string> &Fn,
- const MatchFinder::MatchResult &Match, std::string *Result) {
- Expected<std::string> Value = Fn(Match);
- if (!Value)
- return Value.takeError();
- *Result += *Value;
- return Error::success();
-}
-
-Error evalData(const SequenceData &Data, const MatchFinder::MatchResult &Match,
- std::string *Result) {
- for (const auto &S : Data.Stencils)
- if (auto Err = S->eval(Match, Result))
- return Err;
- return Error::success();
-}
-
-template <typename T> class StencilImpl : public StencilInterface {
- T Data;
+namespace {
+// An arbitrary fragment of code within a stencil.
+class RawTextStencil : public StencilInterface {
+ std::string Text;
public:
- template <typename... Ps>
- explicit StencilImpl(Ps &&... Args) : Data(std::forward<Ps>(Args)...) {}
+ explicit RawTextStencil(std::string T) : Text(std::move(T)) {}
+
+ std::string toString() const override {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ OS << "\"";
+ OS.write_escaped(Text);
+ OS << "\"";
+ OS.flush();
+ return Result;
+ }
Error eval(const MatchFinder::MatchResult &Match,
std::string *Result) const override {
- return evalData(Data, Match, Result);
+ Result->append(Text);
+ return Error::success();
+ }
+};
+
+// A debugging operation to dump the AST for a particular (bound) AST node.
+class DebugPrintNodeStencil : public StencilInterface {
+ std::string Id;
+
+public:
+ explicit DebugPrintNodeStencil(std::string S) : Id(std::move(S)) {}
+
+ std::string toString() const override {
+ return (llvm::Twine("dPrint(\"") + Id + "\")").str();
}
- std::string toString() const override { return toStringData(Data); }
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ return printNode(Id, Match, Result);
+ }
+};
+
+// Operators that take a single node Id as an argument.
+enum class UnaryNodeOperator {
+ Parens,
+ Deref,
+ MaybeDeref,
+ AddressOf,
+ MaybeAddressOf,
+ Describe,
+};
+
+// Generic container for stencil operations with a (single) node-id argument.
+class UnaryOperationStencil : public StencilInterface {
+ UnaryNodeOperator Op;
+ std::string Id;
+
+public:
+ UnaryOperationStencil(UnaryNodeOperator Op, std::string Id)
+ : Op(Op), Id(std::move(Id)) {}
+
+ std::string toString() const override {
+ StringRef OpName;
+ switch (Op) {
+ case UnaryNodeOperator::Parens:
+ OpName = "expression";
+ break;
+ case UnaryNodeOperator::Deref:
+ OpName = "deref";
+ break;
+ case UnaryNodeOperator::MaybeDeref:
+ OpName = "maybeDeref";
+ break;
+ case UnaryNodeOperator::AddressOf:
+ OpName = "addressOf";
+ break;
+ case UnaryNodeOperator::MaybeAddressOf:
+ OpName = "maybeAddressOf";
+ break;
+ case UnaryNodeOperator::Describe:
+ OpName = "describe";
+ break;
+ }
+ return (OpName + "(\"" + Id + "\")").str();
+ }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ // The `Describe` operation can be applied to any node, not just
+ // expressions, so it is handled here, separately.
+ if (Op == UnaryNodeOperator::Describe)
+ return printNode(Id, Match, Result);
+
+ const auto *E = Match.Nodes.getNodeAs<Expr>(Id);
+ if (E == nullptr)
+ return llvm::make_error<StringError>(errc::invalid_argument,
+ "Id not bound or not Expr: " + Id);
+ llvm::Optional<std::string> Source;
+ switch (Op) {
+ case UnaryNodeOperator::Parens:
+ Source = tooling::buildParens(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::Deref:
+ Source = tooling::buildDereference(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::MaybeDeref:
+ if (E->getType()->isAnyPointerType() ||
+ isSmartPointerType(E->getType(), *Match.Context)) {
+ // Strip off any operator->. This can only occur inside an actual arrow
+ // member access, so we treat it as equivalent to an actual object
+ // expression.
+ if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
+ if (OpCall->getOperator() == clang::OO_Arrow &&
+ OpCall->getNumArgs() == 1) {
+ E = OpCall->getArg(0);
+ }
+ }
+ Source = tooling::buildDereference(*E, *Match.Context);
+ break;
+ }
+ *Result += tooling::getText(*E, *Match.Context);
+ return Error::success();
+ case UnaryNodeOperator::AddressOf:
+ Source = tooling::buildAddressOf(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::MaybeAddressOf:
+ if (E->getType()->isAnyPointerType() ||
+ isSmartPointerType(E->getType(), *Match.Context)) {
+ // Strip off any operator->. This can only occur inside an actual arrow
+ // member access, so we treat it as equivalent to an actual object
+ // expression.
+ if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
+ if (OpCall->getOperator() == clang::OO_Arrow &&
+ OpCall->getNumArgs() == 1) {
+ E = OpCall->getArg(0);
+ }
+ }
+ *Result += tooling::getText(*E, *Match.Context);
+ return Error::success();
+ }
+ Source = tooling::buildAddressOf(*E, *Match.Context);
+ break;
+ case UnaryNodeOperator::Describe:
+ llvm_unreachable("This case is handled at the start of the function");
+ }
+ if (!Source)
+ return llvm::make_error<StringError>(
+ errc::invalid_argument,
+ "Could not construct expression source from ID: " + Id);
+ *Result += *Source;
+ return Error::success();
+ }
+};
+
+// The fragment of code corresponding to the selected range.
+class SelectorStencil : public StencilInterface {
+ RangeSelector Selector;
+
+public:
+ explicit SelectorStencil(RangeSelector S) : Selector(std::move(S)) {}
+
+ std::string toString() const override { return "selection(...)"; }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ auto RawRange = Selector(Match);
+ if (!RawRange)
+ return RawRange.takeError();
+ CharSourceRange Range = Lexer::makeFileCharRange(
+ *RawRange, *Match.SourceManager, Match.Context->getLangOpts());
+ if (Range.isInvalid()) {
+ // Validate the original range to attempt to get a meaningful error
+ // message. If it's valid, then something else is the cause and we just
+ // return the generic failure message.
+ if (auto Err =
+ tooling::validateEditRange(*RawRange, *Match.SourceManager))
+ return handleErrors(std::move(Err), [](std::unique_ptr<StringError> E) {
+ assert(E->convertToErrorCode() ==
+ llvm::make_error_code(errc::invalid_argument) &&
+ "Validation errors must carry the invalid_argument code");
+ return llvm::createStringError(
+ errc::invalid_argument,
+ "selected range could not be resolved to a valid source range; " +
+ E->getMessage());
+ });
+ return llvm::createStringError(
+ errc::invalid_argument,
+ "selected range could not be resolved to a valid source range");
+ }
+ // Validate `Range`, because `makeFileCharRange` accepts some ranges that
+ // `validateEditRange` rejects.
+ if (auto Err = tooling::validateEditRange(Range, *Match.SourceManager))
+ return joinErrors(
+ llvm::createStringError(errc::invalid_argument,
+ "selected range is not valid for editing"),
+ std::move(Err));
+ *Result += tooling::getText(Range, *Match.Context);
+ return Error::success();
+ }
+};
+
+// A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
+class AccessStencil : public StencilInterface {
+ std::string BaseId;
+ Stencil Member;
+
+public:
+ AccessStencil(StringRef BaseId, Stencil Member)
+ : BaseId(std::string(BaseId)), Member(std::move(Member)) {}
+
+ std::string toString() const override {
+ return (llvm::Twine("access(\"") + BaseId + "\", " + Member->toString() +
+ ")")
+ .str();
+ }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ const auto *E = Match.Nodes.getNodeAs<Expr>(BaseId);
+ if (E == nullptr)
+ return llvm::make_error<StringError>(errc::invalid_argument,
+ "Id not bound: " + BaseId);
+ if (!E->isImplicitCXXThis()) {
+ llvm::Optional<std::string> S;
+ if (E->getType()->isAnyPointerType() ||
+ isSmartPointerType(E->getType(), *Match.Context)) {
+ // Strip off any operator->. This can only occur inside an actual arrow
+ // member access, so we treat it as equivalent to an actual object
+ // expression.
+ if (const auto *OpCall = dyn_cast<clang::CXXOperatorCallExpr>(E)) {
+ if (OpCall->getOperator() == clang::OO_Arrow &&
+ OpCall->getNumArgs() == 1) {
+ E = OpCall->getArg(0);
+ }
+ }
+ S = tooling::buildArrow(*E, *Match.Context);
+ } else if (const auto *Operand = isSmartDereference(*E, *Match.Context)) {
+ // `buildDot` already handles the built-in dereference operator, so we
+ // only need to catch overloaded `operator*`.
+ S = tooling::buildArrow(*Operand, *Match.Context);
+ } else {
+ S = tooling::buildDot(*E, *Match.Context);
+ }
+ if (S.hasValue())
+ *Result += *S;
+ else
+ return llvm::make_error<StringError>(
+ errc::invalid_argument,
+ "Could not construct object text from ID: " + BaseId);
+ }
+ return Member->eval(Match, Result);
+ }
+};
+
+class IfBoundStencil : public StencilInterface {
+ std::string Id;
+ Stencil TrueStencil;
+ Stencil FalseStencil;
+
+public:
+ IfBoundStencil(StringRef Id, Stencil TrueStencil, Stencil FalseStencil)
+ : Id(std::string(Id)), TrueStencil(std::move(TrueStencil)),
+ FalseStencil(std::move(FalseStencil)) {}
+
+ std::string toString() const override {
+ return (llvm::Twine("ifBound(\"") + Id + "\", " + TrueStencil->toString() +
+ ", " + FalseStencil->toString() + ")")
+ .str();
+ }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ auto &M = Match.Nodes.getMap();
+ return (M.find(Id) != M.end() ? TrueStencil : FalseStencil)
+ ->eval(Match, Result);
+ }
+};
+
+class SequenceStencil : public StencilInterface {
+ std::vector<Stencil> Stencils;
+
+public:
+ SequenceStencil(std::vector<Stencil> Stencils)
+ : Stencils(std::move(Stencils)) {}
+
+ std::string toString() const override {
+ llvm::SmallVector<std::string, 2> Parts;
+ Parts.reserve(Stencils.size());
+ for (const auto &S : Stencils)
+ Parts.push_back(S->toString());
+ return (llvm::Twine("seq(") + llvm::join(Parts, ", ") + ")").str();
+ }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+ for (const auto &S : Stencils)
+ if (auto Err = S->eval(Match, Result))
+ return Err;
+ return Error::success();
+ }
+};
+
+class RunStencil : public StencilInterface {
+ MatchConsumer<std::string> Consumer;
+
+public:
+ explicit RunStencil(MatchConsumer<std::string> C) : Consumer(std::move(C)) {}
+
+ std::string toString() const override { return "run(...)"; }
+
+ Error eval(const MatchFinder::MatchResult &Match,
+ std::string *Result) const override {
+
+ Expected<std::string> Value = Consumer(Match);
+ if (!Value)
+ return Value.takeError();
+ *Result += *Value;
+ return Error::success();
+ }
};
} // namespace
Stencil transformer::detail::makeStencil(StringRef Text) {
- return std::make_shared<StencilImpl<RawTextData>>(std::string(Text));
+ return std::make_shared<RawTextStencil>(std::string(Text));
}
Stencil transformer::detail::makeStencil(RangeSelector Selector) {
- return std::make_shared<StencilImpl<SelectorData>>(std::move(Selector));
+ return std::make_shared<SelectorStencil>(std::move(Selector));
}
Stencil transformer::dPrint(StringRef Id) {
- return std::make_shared<StencilImpl<DebugPrintNodeData>>(std::string(Id));
+ return std::make_shared<DebugPrintNodeStencil>(std::string(Id));
}
Stencil transformer::expression(llvm::StringRef Id) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::Parens, std::string(Id));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Parens,
+ std::string(Id));
}
Stencil transformer::deref(llvm::StringRef ExprId) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::Deref, std::string(ExprId));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Deref,
+ std::string(ExprId));
}
Stencil transformer::maybeDeref(llvm::StringRef ExprId) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::MaybeDeref, std::string(ExprId));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::MaybeDeref,
+ std::string(ExprId));
}
Stencil transformer::addressOf(llvm::StringRef ExprId) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::AddressOf, std::string(ExprId));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::AddressOf,
+ std::string(ExprId));
}
Stencil transformer::maybeAddressOf(llvm::StringRef ExprId) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
+ return std::make_shared<UnaryOperationStencil>(
UnaryNodeOperator::MaybeAddressOf, std::string(ExprId));
}
Stencil transformer::describe(StringRef Id) {
- return std::make_shared<StencilImpl<UnaryOperationData>>(
- UnaryNodeOperator::Describe, std::string(Id));
+ return std::make_shared<UnaryOperationStencil>(UnaryNodeOperator::Describe,
+ std::string(Id));
}
Stencil transformer::access(StringRef BaseId, Stencil Member) {
- return std::make_shared<StencilImpl<AccessData>>(BaseId, std::move(Member));
+ return std::make_shared<AccessStencil>(BaseId, std::move(Member));
}
Stencil transformer::ifBound(StringRef Id, Stencil TrueStencil,
Stencil FalseStencil) {
- return std::make_shared<StencilImpl<IfBoundData>>(Id, std::move(TrueStencil),
- std::move(FalseStencil));
+ return std::make_shared<IfBoundStencil>(Id, std::move(TrueStencil),
+ std::move(FalseStencil));
}
Stencil transformer::run(MatchConsumer<std::string> Fn) {
- return std::make_shared<StencilImpl<MatchConsumer<std::string>>>(
- std::move(Fn));
+ return std::make_shared<RunStencil>(std::move(Fn));
}
Stencil transformer::catVector(std::vector<Stencil> Parts) {
// Only one argument, so don't wrap in sequence.
if (Parts.size() == 1)
return std::move(Parts[0]);
- return std::make_shared<StencilImpl<SequenceData>>(std::move(Parts));
+ return std::make_shared<SequenceStencil>(std::move(Parts));
}